am 2529a453
: Merge "Make bad notifications crash their application." into gingerbread
Merge commit '2529a45339b7e02d9d2b813358bcecd144a971ea' into gingerbread-plus-aosp * commit '2529a45339b7e02d9d2b813358bcecd144a971ea': Make bad notifications crash their application.
This commit is contained in:
@ -1293,6 +1293,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CRASH_APPLICATION_TRANSACTION: {
|
||||||
|
data.enforceInterface(IActivityManager.descriptor);
|
||||||
|
int uid = data.readInt();
|
||||||
|
int initialPid = data.readInt();
|
||||||
|
String packageName = data.readString();
|
||||||
|
String message = data.readString();
|
||||||
|
crashApplication(uid, initialPid, packageName, message);
|
||||||
|
reply.writeNoException();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onTransact(code, data, reply, flags);
|
return super.onTransact(code, data, reply, flags);
|
||||||
@ -2867,5 +2878,20 @@ class ActivityManagerProxy implements IActivityManager
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void crashApplication(int uid, int initialPid, String packageName,
|
||||||
|
String message) throws RemoteException {
|
||||||
|
Parcel data = Parcel.obtain();
|
||||||
|
Parcel reply = Parcel.obtain();
|
||||||
|
data.writeInterfaceToken(IActivityManager.descriptor);
|
||||||
|
data.writeInt(uid);
|
||||||
|
data.writeInt(initialPid);
|
||||||
|
data.writeString(packageName);
|
||||||
|
data.writeString(message);
|
||||||
|
mRemote.transact(CRASH_APPLICATION_TRANSACTION, data, reply, 0);
|
||||||
|
reply.readException();
|
||||||
|
data.recycle();
|
||||||
|
reply.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
private IBinder mRemote;
|
private IBinder mRemote;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,12 @@ final class SuperNotCalledException extends AndroidRuntimeException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class RemoteServiceException extends AndroidRuntimeException {
|
||||||
|
public RemoteServiceException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This manages the execution of the main thread in an
|
* This manages the execution of the main thread in an
|
||||||
* application process, scheduling and executing activities,
|
* application process, scheduling and executing activities,
|
||||||
@ -645,6 +651,10 @@ public final class ActivityThread {
|
|||||||
queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
|
queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void scheduleCrash(String msg) {
|
||||||
|
queueOrSendMessage(H.SCHEDULE_CRASH, msg);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
long nativeMax = Debug.getNativeHeapSize() / 1024;
|
long nativeMax = Debug.getNativeHeapSize() / 1024;
|
||||||
@ -870,6 +880,7 @@ public final class ActivityThread {
|
|||||||
public static final int REMOVE_PROVIDER = 131;
|
public static final int REMOVE_PROVIDER = 131;
|
||||||
public static final int ENABLE_JIT = 132;
|
public static final int ENABLE_JIT = 132;
|
||||||
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
|
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
|
||||||
|
public static final int SCHEDULE_CRASH = 134;
|
||||||
String codeToString(int code) {
|
String codeToString(int code) {
|
||||||
if (localLOGV) {
|
if (localLOGV) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
@ -907,6 +918,7 @@ public final class ActivityThread {
|
|||||||
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
|
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
|
||||||
case ENABLE_JIT: return "ENABLE_JIT";
|
case ENABLE_JIT: return "ENABLE_JIT";
|
||||||
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
|
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
|
||||||
|
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
@ -1030,6 +1042,8 @@ public final class ActivityThread {
|
|||||||
case DISPATCH_PACKAGE_BROADCAST:
|
case DISPATCH_PACKAGE_BROADCAST:
|
||||||
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
|
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
|
||||||
break;
|
break;
|
||||||
|
case SCHEDULE_CRASH:
|
||||||
|
throw new RemoteServiceException((String)msg.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,6 +402,14 @@ public abstract class ApplicationThreadNative extends Binder
|
|||||||
dispatchPackageBroadcast(cmd, packages);
|
dispatchPackageBroadcast(cmd, packages);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SCHEDULE_CRASH_TRANSACTION:
|
||||||
|
{
|
||||||
|
data.enforceInterface(IApplicationThread.descriptor);
|
||||||
|
String msg = data.readString();
|
||||||
|
scheduleCrash(msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onTransact(code, data, reply, flags);
|
return super.onTransact(code, data, reply, flags);
|
||||||
@ -826,5 +834,15 @@ class ApplicationThreadProxy implements IApplicationThread {
|
|||||||
data.recycle();
|
data.recycle();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void scheduleCrash(String msg) throws RemoteException {
|
||||||
|
Parcel data = Parcel.obtain();
|
||||||
|
data.writeInterfaceToken(IApplicationThread.descriptor);
|
||||||
|
data.writeString(msg);
|
||||||
|
mRemote.transact(SCHEDULE_CRASH_TRANSACTION, data, null,
|
||||||
|
IBinder.FLAG_ONEWAY);
|
||||||
|
data.recycle();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,6 +316,9 @@ public interface IActivityManager extends IInterface {
|
|||||||
public boolean isImmersive(IBinder token) throws RemoteException;
|
public boolean isImmersive(IBinder token) throws RemoteException;
|
||||||
public boolean isTopActivityImmersive() throws RemoteException;
|
public boolean isTopActivityImmersive() throws RemoteException;
|
||||||
|
|
||||||
|
public void crashApplication(int uid, int initialPid, String packageName,
|
||||||
|
String message) throws RemoteException;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private non-Binder interfaces
|
* Private non-Binder interfaces
|
||||||
*/
|
*/
|
||||||
@ -531,4 +534,5 @@ public interface IActivityManager extends IInterface {
|
|||||||
int IS_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+110;
|
int IS_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+110;
|
||||||
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
|
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
|
||||||
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
|
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
|
||||||
|
int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,7 @@ public interface IApplicationThread extends IInterface {
|
|||||||
static final int PACKAGE_REMOVED = 0;
|
static final int PACKAGE_REMOVED = 0;
|
||||||
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
|
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
|
||||||
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
|
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
|
||||||
|
void scheduleCrash(String msg) throws RemoteException;
|
||||||
|
|
||||||
String descriptor = "android.app.IApplicationThread";
|
String descriptor = "android.app.IApplicationThread";
|
||||||
|
|
||||||
@ -139,4 +140,5 @@ public interface IApplicationThread extends IInterface {
|
|||||||
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
|
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
|
||||||
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
|
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
|
||||||
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
|
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
|
||||||
|
int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ interface IStatusBarService
|
|||||||
out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
|
out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
|
||||||
void onPanelRevealed();
|
void onPanelRevealed();
|
||||||
void onNotificationClick(String pkg, String tag, int id);
|
void onNotificationClick(String pkg, String tag, int id);
|
||||||
void onNotificationError(String pkg, String tag, int id, String message);
|
void onNotificationError(String pkg, String tag, int id,
|
||||||
|
int uid, int initialPid, String message);
|
||||||
void onClearAllNotifications();
|
void onClearAllNotifications();
|
||||||
}
|
}
|
||||||
|
@ -38,18 +38,23 @@ public class StatusBarNotification implements Parcelable {
|
|||||||
public String pkg;
|
public String pkg;
|
||||||
public int id;
|
public int id;
|
||||||
public String tag;
|
public String tag;
|
||||||
|
public int uid;
|
||||||
|
public int initialPid;
|
||||||
public Notification notification;
|
public Notification notification;
|
||||||
|
|
||||||
public StatusBarNotification() {
|
public StatusBarNotification() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StatusBarNotification(String pkg, int id, String tag, Notification notification) {
|
public StatusBarNotification(String pkg, int id, String tag,
|
||||||
|
int uid, int initialPid, Notification notification) {
|
||||||
if (pkg == null) throw new NullPointerException();
|
if (pkg == null) throw new NullPointerException();
|
||||||
if (notification == null) throw new NullPointerException();
|
if (notification == null) throw new NullPointerException();
|
||||||
|
|
||||||
this.pkg = pkg;
|
this.pkg = pkg;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
this.uid = uid;
|
||||||
|
this.initialPid = initialPid;
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +70,8 @@ public class StatusBarNotification implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
this.tag = null;
|
this.tag = null;
|
||||||
}
|
}
|
||||||
|
this.uid = in.readInt();
|
||||||
|
this.initialPid = in.readInt();
|
||||||
this.notification = new Notification(in);
|
this.notification = new Notification(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +84,8 @@ public class StatusBarNotification implements Parcelable {
|
|||||||
} else {
|
} else {
|
||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
|
out.writeInt(this.uid);
|
||||||
|
out.writeInt(this.initialPid);
|
||||||
this.notification.writeToParcel(out, flags);
|
this.notification.writeToParcel(out, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +108,8 @@ public class StatusBarNotification implements Parcelable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public StatusBarNotification clone() {
|
public StatusBarNotification clone() {
|
||||||
return new StatusBarNotification(this.pkg, this.id, this.tag, this.notification.clone());
|
return new StatusBarNotification(this.pkg, this.id, this.tag,
|
||||||
|
this.uid, this.initialPid, this.notification.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -989,7 +989,7 @@ public class PhoneStatusBarService extends StatusBarService {
|
|||||||
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
|
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
|
||||||
removeNotification(key);
|
removeNotification(key);
|
||||||
try {
|
try {
|
||||||
mBarService.onNotificationError(n.pkg, n.tag, n.id, message);
|
mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
|
||||||
} catch (RemoteException ex) {
|
} catch (RemoteException ex) {
|
||||||
// The end is nigh.
|
// The end is nigh.
|
||||||
}
|
}
|
||||||
|
@ -164,16 +164,21 @@ class NotificationManagerService extends INotificationManager.Stub
|
|||||||
final String pkg;
|
final String pkg;
|
||||||
final String tag;
|
final String tag;
|
||||||
final int id;
|
final int id;
|
||||||
|
final int uid;
|
||||||
|
final int initialPid;
|
||||||
ITransientNotification callback;
|
ITransientNotification callback;
|
||||||
int duration;
|
int duration;
|
||||||
final Notification notification;
|
final Notification notification;
|
||||||
IBinder statusBarKey;
|
IBinder statusBarKey;
|
||||||
|
|
||||||
NotificationRecord(String pkg, String tag, int id, Notification notification)
|
NotificationRecord(String pkg, String tag, int id, int uid, int initialPid,
|
||||||
|
Notification notification)
|
||||||
{
|
{
|
||||||
this.pkg = pkg;
|
this.pkg = pkg;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.uid = uid;
|
||||||
|
this.initialPid = initialPid;
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,10 +309,18 @@ class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNotificationError(String pkg, String tag, int id, String message) {
|
public void onNotificationError(String pkg, String tag, int id,
|
||||||
|
int uid, int initialPid, String message) {
|
||||||
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id);
|
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id);
|
||||||
cancelNotification(pkg, tag, id, 0, 0);
|
cancelNotification(pkg, tag, id, 0, 0);
|
||||||
// TODO: Tell the activity manager.
|
long ident = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
|
||||||
|
"Bad notification posted from package " + pkg
|
||||||
|
+ ": " + message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -663,6 +676,9 @@ class NotificationManagerService extends INotificationManager.Stub
|
|||||||
public void enqueueNotificationWithTag(String pkg, String tag, int id,
|
public void enqueueNotificationWithTag(String pkg, String tag, int id,
|
||||||
Notification notification, int[] idOut)
|
Notification notification, int[] idOut)
|
||||||
{
|
{
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
final int callingPid = Binder.getCallingPid();
|
||||||
|
|
||||||
checkIncomingCall(pkg);
|
checkIncomingCall(pkg);
|
||||||
|
|
||||||
// Limit the number of notifications that any given package except the android
|
// Limit the number of notifications that any given package except the android
|
||||||
@ -708,7 +724,8 @@ class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mNotificationList) {
|
synchronized (mNotificationList) {
|
||||||
NotificationRecord r = new NotificationRecord(pkg, tag, id, notification);
|
NotificationRecord r = new NotificationRecord(pkg, tag, id,
|
||||||
|
callingUid, callingPid, notification);
|
||||||
NotificationRecord old = null;
|
NotificationRecord old = null;
|
||||||
|
|
||||||
int index = indexOfNotificationLocked(pkg, tag, id);
|
int index = indexOfNotificationLocked(pkg, tag, id);
|
||||||
@ -732,7 +749,8 @@ class NotificationManagerService extends INotificationManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (notification.icon != 0) {
|
if (notification.icon != 0) {
|
||||||
StatusBarNotification n = new StatusBarNotification(pkg, id, tag, notification);
|
StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
|
||||||
|
r.uid, r.initialPid, notification);
|
||||||
if (old != null && old.statusBarKey != null) {
|
if (old != null && old.statusBarKey != null) {
|
||||||
r.statusBarKey = old.statusBarKey;
|
r.statusBarKey = old.statusBarKey;
|
||||||
long identity = Binder.clearCallingIdentity();
|
long identity = Binder.clearCallingIdentity();
|
||||||
|
@ -85,7 +85,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
|||||||
void onClearAll();
|
void onClearAll();
|
||||||
void onNotificationClick(String pkg, String tag, int id);
|
void onNotificationClick(String pkg, String tag, int id);
|
||||||
void onPanelRevealed();
|
void onPanelRevealed();
|
||||||
void onNotificationError(String pkg, String tag, int id, String message);
|
void onNotificationError(String pkg, String tag, int id,
|
||||||
|
int uid, int initialPid, String message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,11 +294,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub
|
|||||||
mNotificationCallbacks.onNotificationClick(pkg, tag, id);
|
mNotificationCallbacks.onNotificationClick(pkg, tag, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onNotificationError(String pkg, String tag, int id, String message) {
|
public void onNotificationError(String pkg, String tag, int id,
|
||||||
|
int uid, int initialPid, String message) {
|
||||||
enforceStatusBarService();
|
enforceStatusBarService();
|
||||||
|
|
||||||
// WARNING: this will call back into us to do the remove. Don't hold any locks.
|
// WARNING: this will call back into us to do the remove. Don't hold any locks.
|
||||||
mNotificationCallbacks.onNotificationError(pkg, tag, id, message);
|
mNotificationCallbacks.onNotificationError(pkg, tag, id, uid, initialPid, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClearAllNotifications() {
|
public void onClearAllNotifications() {
|
||||||
|
@ -4562,6 +4562,60 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void crashApplication(int uid, int initialPid, String packageName,
|
||||||
|
String message) {
|
||||||
|
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
String msg = "Permission Denial: crashApplication() from pid="
|
||||||
|
+ Binder.getCallingPid()
|
||||||
|
+ ", uid=" + Binder.getCallingUid()
|
||||||
|
+ " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
|
||||||
|
Slog.w(TAG, msg);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(this) {
|
||||||
|
ProcessRecord proc = null;
|
||||||
|
|
||||||
|
// Figure out which process to kill. We don't trust that initialPid
|
||||||
|
// still has any relation to current pids, so must scan through the
|
||||||
|
// list.
|
||||||
|
synchronized (mPidsSelfLocked) {
|
||||||
|
for (int i=0; i<mPidsSelfLocked.size(); i++) {
|
||||||
|
ProcessRecord p = mPidsSelfLocked.valueAt(i);
|
||||||
|
if (p.info.uid != uid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (p.pid == initialPid) {
|
||||||
|
proc = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (String str : p.pkgList) {
|
||||||
|
if (str.equals(packageName)) {
|
||||||
|
proc = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc == null) {
|
||||||
|
Log.w(TAG, "crashApplication: nothing for uid=" + uid
|
||||||
|
+ " initialPid=" + initialPid
|
||||||
|
+ " packageName=" + packageName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc.thread != null) {
|
||||||
|
long ident = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
proc.thread.scheduleCrash(message);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sendActivityResultLocked(int callingUid, ActivityRecord r,
|
void sendActivityResultLocked(int callingUid, ActivityRecord r,
|
||||||
String resultWho, int requestCode, int resultCode, Intent data) {
|
String resultWho, int requestCode, int resultCode, Intent data) {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user