Loading core/java/android/app/IActivityTaskManager.aidl +5 −6 Original line number Original line Diff line number Diff line Loading @@ -178,17 +178,16 @@ interface IActivityTaskManager { Point getAppTaskThumbnailSize(); Point getAppTaskThumbnailSize(); /** /** * Only callable from the system. This token grants a temporary permission to call * Only callable from the system. This token grants a temporary permission to call * #startActivityAsCallerWithToken. The token will time out after * #startActivityAsCaller. The token will time out after START_AS_CALLER_TOKEN_TIMEOUT * START_AS_CALLER_TOKEN_TIMEOUT if it is not used. * if it is not used. * * * @param delegatorToken The Binder token referencing the system Activity that wants to delegate * @param componentName The component name of the delegated component that is allowed to * the #startActivityAsCaller to another app. The "caller" will be the caller of this * call #startActivityAsCaller with the returned token. * activity's token, not the delegate's caller (which is probably the delegator itself). * * * @return Returns a token that can be given to a "delegate" app that may call * @return Returns a token that can be given to a "delegate" app that may call * #startActivityAsCaller * #startActivityAsCaller */ */ IBinder requestStartActivityPermissionToken(in IBinder delegatorToken); IBinder requestStartActivityPermissionToken(in ComponentName componentName); oneway void releaseSomeActivities(in IApplicationThread app); oneway void releaseSomeActivities(in IApplicationThread app); Bitmap getTaskDescriptionIcon(in String filename, int userId); Bitmap getTaskDescriptionIcon(in String filename, int userId); Loading core/java/com/android/internal/app/ChooserActivity.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -759,11 +759,11 @@ public class ChooserActivity extends ResolverActivity implements } } try { try { IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(getActivityToken()); Intent delegationIntent = new Intent(); Intent delegationIntent = new Intent(); final ComponentName delegateActivity = ComponentName.unflattenFromString( final ComponentName delegateActivity = ComponentName.unflattenFromString( Resources.getSystem().getString(R.string.config_chooserActivity)); Resources.getSystem().getString(R.string.config_chooserActivity)); IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(delegateActivity); delegationIntent.setComponent(delegateActivity); delegationIntent.setComponent(delegateActivity); delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent()); delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent()); delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); Loading core/java/com/android/internal/app/ResolverActivity.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1437,11 +1437,11 @@ public class ResolverActivity extends Activity implements try { try { // TODO: Once this is a small springboard activity, it can move off the UI process // TODO: Once this is a small springboard activity, it can move off the UI process // and we can move the request method to ActivityManagerInternal. // and we can move the request method to ActivityManagerInternal. IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(getActivityToken()); final Intent chooserIntent = new Intent(); final Intent chooserIntent = new Intent(); final ComponentName delegateActivity = ComponentName.unflattenFromString( final ComponentName delegateActivity = ComponentName.unflattenFromString( Resources.getSystem().getString(R.string.config_chooserActivity)); Resources.getSystem().getString(R.string.config_chooserActivity)); IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(delegateActivity); chooserIntent.setClassName(delegateActivity.getPackageName(), chooserIntent.setClassName(delegateActivity.getPackageName(), delegateActivity.getClassName()); delegateActivity.getClassName()); chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +35 −39 Original line number Original line Diff line number Diff line Loading @@ -437,9 +437,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT = private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT = START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS; START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS; // Activity tokens of system activities that are delegating their call to // The component name of the delegated activities that are allowed to call // #startActivityByCaller, keyed by the permissionToken granted to the delegate. // #startActivityAsCaller with the one-time used permission token. final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>(); final HashMap<IBinder, ComponentName> mStartActivitySources = new HashMap<>(); // Permission tokens that have expired, but we remember for error reporting. // Permission tokens that have expired, but we remember for error reporting. final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>(); final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>(); Loading Loading @@ -1513,7 +1513,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } @Override @Override public IBinder requestStartActivityPermissionToken(IBinder delegatorToken) { public IBinder requestStartActivityPermissionToken(ComponentName componentName) { int callingUid = Binder.getCallingUid(); int callingUid = Binder.getCallingUid(); if (UserHandle.getAppId(callingUid) != SYSTEM_UID) { if (UserHandle.getAppId(callingUid) != SYSTEM_UID) { throw new SecurityException("Only the system process can request a permission token, " throw new SecurityException("Only the system process can request a permission token, " Loading @@ -1521,7 +1521,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } IBinder permissionToken = new Binder(); IBinder permissionToken = new Binder(); synchronized (mGlobalLock) { synchronized (mGlobalLock) { mStartActivitySources.put(permissionToken, delegatorToken); mStartActivitySources.put(permissionToken, componentName); } } Message expireMsg = PooledLambda.obtainMessage( Message expireMsg = PooledLambda.obtainMessage( Loading @@ -1546,7 +1546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // 1) The caller is an activity that is part of the core framework, and then only when it // 1) The caller is an activity that is part of the core framework, and then only when it // is running as the system. // is running as the system. // 2) The caller provides a valid permissionToken. Permission tokens are one-time use and // 2) The caller provides a valid permissionToken. Permission tokens are one-time use and // can only be requested by a system activity, which may then delegate this call to // can only be requested from system uid, which may then delegate this call to // another app. // another app. final ActivityRecord sourceRecord; final ActivityRecord sourceRecord; final int targetUid; final int targetUid; Loading @@ -1557,18 +1557,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (resultTo == null) { if (resultTo == null) { throw new SecurityException("Must be called from an activity"); throw new SecurityException("Must be called from an activity"); } } final IBinder sourceToken; sourceRecord = ActivityRecord.isInAnyTask(resultTo); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + resultTo); } if (sourceRecord.app == null) { throw new SecurityException("Called without a process attached to activity"); } final ComponentName componentName; if (permissionToken != null) { if (permissionToken != null) { // To even attempt to use a permissionToken, an app must also have this signature // To even attempt to use a permissionToken, an app must also have this signature // permission. // permission. mAmInternal.enforceCallingPermission( mAmInternal.enforceCallingPermission( android.Manifest.permission.START_ACTIVITY_AS_CALLER, android.Manifest.permission.START_ACTIVITY_AS_CALLER, "startActivityAsCaller"); "startActivityAsCaller"); // If called with a permissionToken, we want the sourceRecord from the delegator // If called with a permissionToken, the caller must be the same component that // activity that requested this token. // was allowed to use the permissionToken. sourceToken = mStartActivitySources.remove(permissionToken); componentName = mStartActivitySources.remove(permissionToken); if (sourceToken == null) { if (!sourceRecord.mActivityComponent.equals(componentName)) { // Invalid permissionToken, check if it recently expired. if (mExpiredStartAsCallerTokens.contains(permissionToken)) { if (mExpiredStartAsCallerTokens.contains(permissionToken)) { throw new SecurityException("Called with expired permission token: " throw new SecurityException("Called with expired permission token: " + permissionToken); + permissionToken); Loading @@ -1578,25 +1586,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } } } } else { } else { // This method was called directly by the source. sourceToken = resultTo; } sourceRecord = ActivityRecord.isInAnyTask(sourceToken); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + sourceToken); } if (sourceRecord.app == null) { throw new SecurityException("Called without a process attached to activity"); } // Whether called directly or from a delegate, the source activity must be from the // Whether called directly or from a delegate, the source activity must be from the // android package. // android package. if (!sourceRecord.info.packageName.equals("android")) { if (!sourceRecord.info.packageName.equals("android")) { throw new SecurityException("Must be called from an activity that is " throw new SecurityException("Must be called from an activity that is " + "declared in the android package"); + "declared in the android package"); } } if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) { if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) { // This is still okay, as long as this activity is running under the // This is still okay, as long as this activity is running under the // uid of the original calling activity. // uid of the original calling activity. Loading @@ -1607,6 +1602,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { + sourceRecord.launchedFromUid); + sourceRecord.launchedFromUid); } } } } } if (ignoreTargetSecurity) { if (ignoreTargetSecurity) { if (intent.getComponent() == null) { if (intent.getComponent() == null) { throw new SecurityException( throw new SecurityException( Loading Loading
core/java/android/app/IActivityTaskManager.aidl +5 −6 Original line number Original line Diff line number Diff line Loading @@ -178,17 +178,16 @@ interface IActivityTaskManager { Point getAppTaskThumbnailSize(); Point getAppTaskThumbnailSize(); /** /** * Only callable from the system. This token grants a temporary permission to call * Only callable from the system. This token grants a temporary permission to call * #startActivityAsCallerWithToken. The token will time out after * #startActivityAsCaller. The token will time out after START_AS_CALLER_TOKEN_TIMEOUT * START_AS_CALLER_TOKEN_TIMEOUT if it is not used. * if it is not used. * * * @param delegatorToken The Binder token referencing the system Activity that wants to delegate * @param componentName The component name of the delegated component that is allowed to * the #startActivityAsCaller to another app. The "caller" will be the caller of this * call #startActivityAsCaller with the returned token. * activity's token, not the delegate's caller (which is probably the delegator itself). * * * @return Returns a token that can be given to a "delegate" app that may call * @return Returns a token that can be given to a "delegate" app that may call * #startActivityAsCaller * #startActivityAsCaller */ */ IBinder requestStartActivityPermissionToken(in IBinder delegatorToken); IBinder requestStartActivityPermissionToken(in ComponentName componentName); oneway void releaseSomeActivities(in IApplicationThread app); oneway void releaseSomeActivities(in IApplicationThread app); Bitmap getTaskDescriptionIcon(in String filename, int userId); Bitmap getTaskDescriptionIcon(in String filename, int userId); Loading
core/java/com/android/internal/app/ChooserActivity.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -759,11 +759,11 @@ public class ChooserActivity extends ResolverActivity implements } } try { try { IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(getActivityToken()); Intent delegationIntent = new Intent(); Intent delegationIntent = new Intent(); final ComponentName delegateActivity = ComponentName.unflattenFromString( final ComponentName delegateActivity = ComponentName.unflattenFromString( Resources.getSystem().getString(R.string.config_chooserActivity)); Resources.getSystem().getString(R.string.config_chooserActivity)); IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(delegateActivity); delegationIntent.setComponent(delegateActivity); delegationIntent.setComponent(delegateActivity); delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent()); delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent()); delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); Loading
core/java/com/android/internal/app/ResolverActivity.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1437,11 +1437,11 @@ public class ResolverActivity extends Activity implements try { try { // TODO: Once this is a small springboard activity, it can move off the UI process // TODO: Once this is a small springboard activity, it can move off the UI process // and we can move the request method to ActivityManagerInternal. // and we can move the request method to ActivityManagerInternal. IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(getActivityToken()); final Intent chooserIntent = new Intent(); final Intent chooserIntent = new Intent(); final ComponentName delegateActivity = ComponentName.unflattenFromString( final ComponentName delegateActivity = ComponentName.unflattenFromString( Resources.getSystem().getString(R.string.config_chooserActivity)); Resources.getSystem().getString(R.string.config_chooserActivity)); IBinder permissionToken = ActivityTaskManager.getService() .requestStartActivityPermissionToken(delegateActivity); chooserIntent.setClassName(delegateActivity.getPackageName(), chooserIntent.setClassName(delegateActivity.getPackageName(), delegateActivity.getClassName()); delegateActivity.getClassName()); chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken); Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +35 −39 Original line number Original line Diff line number Diff line Loading @@ -437,9 +437,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT = private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT = START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS; START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS; // Activity tokens of system activities that are delegating their call to // The component name of the delegated activities that are allowed to call // #startActivityByCaller, keyed by the permissionToken granted to the delegate. // #startActivityAsCaller with the one-time used permission token. final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>(); final HashMap<IBinder, ComponentName> mStartActivitySources = new HashMap<>(); // Permission tokens that have expired, but we remember for error reporting. // Permission tokens that have expired, but we remember for error reporting. final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>(); final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>(); Loading Loading @@ -1513,7 +1513,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } @Override @Override public IBinder requestStartActivityPermissionToken(IBinder delegatorToken) { public IBinder requestStartActivityPermissionToken(ComponentName componentName) { int callingUid = Binder.getCallingUid(); int callingUid = Binder.getCallingUid(); if (UserHandle.getAppId(callingUid) != SYSTEM_UID) { if (UserHandle.getAppId(callingUid) != SYSTEM_UID) { throw new SecurityException("Only the system process can request a permission token, " throw new SecurityException("Only the system process can request a permission token, " Loading @@ -1521,7 +1521,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } IBinder permissionToken = new Binder(); IBinder permissionToken = new Binder(); synchronized (mGlobalLock) { synchronized (mGlobalLock) { mStartActivitySources.put(permissionToken, delegatorToken); mStartActivitySources.put(permissionToken, componentName); } } Message expireMsg = PooledLambda.obtainMessage( Message expireMsg = PooledLambda.obtainMessage( Loading @@ -1546,7 +1546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // 1) The caller is an activity that is part of the core framework, and then only when it // 1) The caller is an activity that is part of the core framework, and then only when it // is running as the system. // is running as the system. // 2) The caller provides a valid permissionToken. Permission tokens are one-time use and // 2) The caller provides a valid permissionToken. Permission tokens are one-time use and // can only be requested by a system activity, which may then delegate this call to // can only be requested from system uid, which may then delegate this call to // another app. // another app. final ActivityRecord sourceRecord; final ActivityRecord sourceRecord; final int targetUid; final int targetUid; Loading @@ -1557,18 +1557,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { if (resultTo == null) { if (resultTo == null) { throw new SecurityException("Must be called from an activity"); throw new SecurityException("Must be called from an activity"); } } final IBinder sourceToken; sourceRecord = ActivityRecord.isInAnyTask(resultTo); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + resultTo); } if (sourceRecord.app == null) { throw new SecurityException("Called without a process attached to activity"); } final ComponentName componentName; if (permissionToken != null) { if (permissionToken != null) { // To even attempt to use a permissionToken, an app must also have this signature // To even attempt to use a permissionToken, an app must also have this signature // permission. // permission. mAmInternal.enforceCallingPermission( mAmInternal.enforceCallingPermission( android.Manifest.permission.START_ACTIVITY_AS_CALLER, android.Manifest.permission.START_ACTIVITY_AS_CALLER, "startActivityAsCaller"); "startActivityAsCaller"); // If called with a permissionToken, we want the sourceRecord from the delegator // If called with a permissionToken, the caller must be the same component that // activity that requested this token. // was allowed to use the permissionToken. sourceToken = mStartActivitySources.remove(permissionToken); componentName = mStartActivitySources.remove(permissionToken); if (sourceToken == null) { if (!sourceRecord.mActivityComponent.equals(componentName)) { // Invalid permissionToken, check if it recently expired. if (mExpiredStartAsCallerTokens.contains(permissionToken)) { if (mExpiredStartAsCallerTokens.contains(permissionToken)) { throw new SecurityException("Called with expired permission token: " throw new SecurityException("Called with expired permission token: " + permissionToken); + permissionToken); Loading @@ -1578,25 +1586,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } } } } else { } else { // This method was called directly by the source. sourceToken = resultTo; } sourceRecord = ActivityRecord.isInAnyTask(sourceToken); if (sourceRecord == null) { throw new SecurityException("Called with bad activity token: " + sourceToken); } if (sourceRecord.app == null) { throw new SecurityException("Called without a process attached to activity"); } // Whether called directly or from a delegate, the source activity must be from the // Whether called directly or from a delegate, the source activity must be from the // android package. // android package. if (!sourceRecord.info.packageName.equals("android")) { if (!sourceRecord.info.packageName.equals("android")) { throw new SecurityException("Must be called from an activity that is " throw new SecurityException("Must be called from an activity that is " + "declared in the android package"); + "declared in the android package"); } } if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) { if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) { // This is still okay, as long as this activity is running under the // This is still okay, as long as this activity is running under the // uid of the original calling activity. // uid of the original calling activity. Loading @@ -1607,6 +1602,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { + sourceRecord.launchedFromUid); + sourceRecord.launchedFromUid); } } } } } if (ignoreTargetSecurity) { if (ignoreTargetSecurity) { if (intent.getComponent() == null) { if (intent.getComponent() == null) { throw new SecurityException( throw new SecurityException( Loading