Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ab93641 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "Allow requesting start-activity-permission-token for an activity"

parents e5033031 47cf5f22
Loading
Loading
Loading
Loading
+5 −6
Original line number Original line Diff line number Diff line
@@ -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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -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);
+2 −2
Original line number Original line Diff line number Diff line
@@ -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);
+35 −39
Original line number Original line Diff line number Diff line
@@ -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<>();
@@ -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, "
@@ -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(
@@ -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;
@@ -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);
@@ -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.
@@ -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(