diff options
| author | 2021-04-28 16:40:35 +0000 | |
|---|---|---|
| committer | 2021-04-28 16:40:35 +0000 | |
| commit | 16f253446d7407bec65c90396b48c86dcf2bc1c6 (patch) | |
| tree | dfd94a6c26c8ef44324958b470e1f4c60f1a52e2 | |
| parent | 056452001fdc3c5f1b3becafb8ddca3414b77d62 (diff) | |
| parent | b20628a54b3d98447508797b609111373f9b2c19 (diff) | |
Merge "Use ActivityRecord for URI permissions in autofill" into sc-dev
5 files changed, 56 insertions, 179 deletions
| diff --git a/services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java b/services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java index 801be5e48d8b..51e023d545fa 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java +++ b/services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java @@ -20,6 +20,8 @@ import static android.content.ContentResolver.SCHEME_CONTENT;  import static com.android.server.autofill.Helper.sVerbose; +import static java.lang.Integer.toHexString; +  import android.annotation.NonNull;  import android.annotation.UserIdInt;  import android.app.IUriGrantsManager; @@ -33,32 +35,16 @@ import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException;  import android.os.UserHandle; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Pair;  import android.util.Slog; -import com.android.internal.annotations.GuardedBy;  import com.android.server.LocalServices; -import com.android.server.uri.UriGrantsManagerInternal; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Set; +import com.android.server.wm.ActivityTaskManagerInternal;  /** - * Grants and revokes URI permissions for content-based autofill suggestions. + * Grants URI permissions for content-based autofill suggestions.   * - * <p>Note that the system cannot just hand out grants directly; it must always do so on behalf of - * an owner (see {@link com.android.server.uri.UriGrantsManagerService}). For autofill, the owner - * is the autofill service provider that creates a given autofill suggestion containing a content - * URI. Therefore, this manager class must be instantiated with the service uid of the provider for - * which it will manage URI grants. - * - * <p>To dump the state of this class, use {@code adb shell dumpsys autofill}. + * <p>URI permissions granted by this class are tied to the activity being filled. When the + * activity finishes, its URI grants are automatically revoked.   *   * <p>To dump all active URI permissions, use {@code adb shell dumpsys activity permissions}.   */ @@ -69,26 +55,10 @@ final class AutofillUriGrantsManager {      @UserIdInt      private final int mSourceUserId;      @NonNull -    private final IBinder mPermissionOwner; -    @NonNull -    private final UriGrantsManagerInternal mUgmInternal; +    private final ActivityTaskManagerInternal mActivityTaskMgrInternal;      @NonNull      private final IUriGrantsManager mUgm; -    // We use a local lock here for simplicity, since the synchronized code does not depend on -    // any other resources (the "hold and wait" condition required for deadlock is not present). -    // If this changes in the future, instead of using a local lock this should be updated to -    // use the shared lock from AutofillManagerServiceImpl. -    @NonNull -    private final Object mLock; - -    // Tracks the URIs that have been granted to each package. For each URI, the map stores the -    // activities that triggered the grant. This allows revoking permissions only once all -    // activities that triggered the grant are finished. -    @NonNull -    @GuardedBy("mLock") -    private final ArrayMap<String, List<Pair<Uri, String>>> mActiveGrantsByPackage; -      /**       * Creates a new instance of the manager.       * @@ -99,159 +69,60 @@ final class AutofillUriGrantsManager {      AutofillUriGrantsManager(int serviceUid) {          mSourceUid = serviceUid;          mSourceUserId = UserHandle.getUserId(mSourceUid); -        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class); -        mPermissionOwner = mUgmInternal.newUriPermissionOwner("autofill-" + serviceUid); +        mActivityTaskMgrInternal = LocalServices.getService(ActivityTaskManagerInternal.class);          mUgm = UriGrantsManager.getService(); -        mLock = new Object(); -        mActiveGrantsByPackage = new ArrayMap<>(0);      }      public void grantUriPermissions(@NonNull ComponentName targetActivity, -            @UserIdInt int targetUserId, @NonNull ClipData clip) { -        String targetPkg = targetActivity.getPackageName(); +            @NonNull IBinder targetActivityToken, @UserIdInt int targetUserId, +            @NonNull ClipData clip) { +        final String targetPkg = targetActivity.getPackageName(); +        final IBinder permissionOwner = +                mActivityTaskMgrInternal.getUriPermissionOwnerForActivity(targetActivityToken); +        if (permissionOwner == null) { +            Slog.w(TAG, "Can't grant URI permissions, because the target activity token is invalid:" +                    + " clip=" + clip +                    + ", targetActivity=" + targetActivity + ", targetUserId=" + targetUserId +                    + ", targetActivityToken=" + toHexString(targetActivityToken.hashCode())); +            return; +        }          for (int i = 0; i < clip.getItemCount(); i++) {              ClipData.Item item = clip.getItemAt(i);              Uri uri = item.getUri();              if (uri == null || !SCHEME_CONTENT.equals(uri.getScheme())) {                  continue;              } -            if (grantUriPermissions(targetPkg, targetUserId, uri)) { -                addToActiveGrants(uri, targetActivity); -            } -        } -    } - -    public void revokeUriPermissions(@NonNull ComponentName targetActivity, -            @UserIdInt int targetUserId) { -        String targetPkg = targetActivity.getPackageName(); -        Set<Uri> urisWhoseGrantsShouldBeRevoked = removeFromActiveGrants(targetActivity); -        for (Uri uri : urisWhoseGrantsShouldBeRevoked) { -            revokeUriPermissions(targetPkg, targetUserId, uri); +            grantUriPermissions(uri, targetPkg, targetUserId, permissionOwner);          }      } -    private boolean grantUriPermissions(@NonNull String targetPkg, @UserIdInt int targetUserId, -            @NonNull Uri uri) { +    private void grantUriPermissions(@NonNull Uri uri, @NonNull String targetPkg, +            @UserIdInt int targetUserId, @NonNull IBinder permissionOwner) {          final int sourceUserId = ContentProvider.getUserIdFromUri(uri, mSourceUserId);          if (sVerbose) {              Slog.v(TAG, "Granting URI permissions: uri=" + uri                      + ", sourceUid=" + mSourceUid + ", sourceUserId=" + sourceUserId -                    + ", targetPkg=" + targetPkg + ", targetUserId=" + targetUserId); +                    + ", targetPkg=" + targetPkg + ", targetUserId=" + targetUserId +                    + ", permissionOwner=" + toHexString(permissionOwner.hashCode()));          }          final Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(uri);          final long ident = Binder.clearCallingIdentity();          try {              mUgm.grantUriPermissionFromOwner( -                    mPermissionOwner, +                    permissionOwner,                      mSourceUid,                      targetPkg,                      uriWithoutUserId,                      Intent.FLAG_GRANT_READ_URI_PERMISSION,                      sourceUserId,                      targetUserId); -            return true;          } catch (RemoteException e) {              Slog.e(TAG, "Granting URI permissions failed: uri=" + uri                      + ", sourceUid=" + mSourceUid + ", sourceUserId=" + sourceUserId -                    + ", targetPkg=" + targetPkg + ", targetUserId=" + targetUserId, e); -            return false; -        } finally { -            Binder.restoreCallingIdentity(ident); -        } -    } - -    private void revokeUriPermissions(@NonNull String targetPkg, @UserIdInt int targetUserId, -            @NonNull Uri uri) { -        final int sourceUserId = ContentProvider.getUserIdFromUri(uri, mSourceUserId); -        if (sVerbose) { -            Slog.v(TAG, "Revoking URI permissions: uri=" + uri -                    + ", sourceUid=" + mSourceUid + ", sourceUserId=" + sourceUserId -                    + ", target=" + targetPkg + ", targetUserId=" + targetUserId); -        } -        final Uri uriWithoutUserId = ContentProvider.getUriWithoutUserId(uri); -        final long ident = Binder.clearCallingIdentity(); -        try { -            mUgmInternal.revokeUriPermissionFromOwner( -                    mPermissionOwner, -                    uriWithoutUserId, -                    Intent.FLAG_GRANT_READ_URI_PERMISSION, -                    sourceUserId, -                    targetPkg, -                    targetUserId); +                    + ", targetPkg=" + targetPkg + ", targetUserId=" + targetUserId +                    + ", permissionOwner=" + toHexString(permissionOwner.hashCode()), e);          } finally {              Binder.restoreCallingIdentity(ident);          }      } - -    private void addToActiveGrants(@NonNull Uri uri, @NonNull ComponentName targetActivity) { -        synchronized (mLock) { -            String packageName = targetActivity.getPackageName(); -            List<Pair<Uri, String>> uris = mActiveGrantsByPackage.computeIfAbsent(packageName, -                    k -> new ArrayList<>(1)); -            uris.add(Pair.create(uri, targetActivity.getClassName())); -        } -    } - -    private Set<Uri> removeFromActiveGrants(@NonNull ComponentName targetActivity) { -        synchronized (mLock) { -            String targetPackageName = targetActivity.getPackageName(); -            List<Pair<Uri, String>> uris = mActiveGrantsByPackage.get(targetPackageName); -            if (uris == null || uris.isEmpty()) { -                return Collections.emptySet(); -            } - -            // Collect all URIs whose grant was triggered by the target activity. -            String targetActivityClassName = targetActivity.getClassName(); -            Set<Uri> urisWhoseGrantsShouldBeRevoked = new ArraySet<>(1); -            for (Iterator<Pair<Uri, String>> iter = uris.iterator(); iter.hasNext(); ) { -                Pair<Uri, String> uriAndActivity = iter.next(); -                if (uriAndActivity.second.equals(targetActivityClassName)) { -                    urisWhoseGrantsShouldBeRevoked.add(uriAndActivity.first); -                    iter.remove(); -                } -            } - -            // A URI grant may have been triggered by more than one activity for the same package. -            // We should not revoke a grant if it was triggered by multiple activities and one or -            // more of those activities is still alive. Therefore we do a second pass and prune -            // the set of URIs to be revoked if an additional activity that triggered its grant -            // is still present. -            for (Pair<Uri, String> uriAndActivity : uris) { -                urisWhoseGrantsShouldBeRevoked.remove(uriAndActivity.first); -            } - -            // If there are no remaining URIs granted to the package, drop the entry from the map. -            if (uris.isEmpty()) { -                mActiveGrantsByPackage.remove(targetPackageName); -            } -            return urisWhoseGrantsShouldBeRevoked; -        } -    } - -    /** -     * Dump the active URI grants. -     */ -    public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { -        synchronized (mLock) { -            if (mActiveGrantsByPackage.isEmpty()) { -                pw.print(prefix); pw.println("URI grants: none"); -                return; -            } -            pw.print(prefix); pw.println("URI grants:"); -            final String prefix2 = prefix + "  "; -            final String prefix3 = prefix2 + "  "; -            for (int i = mActiveGrantsByPackage.size() - 1; i >= 0; i--) { -                String packageName = mActiveGrantsByPackage.keyAt(i); -                pw.print(prefix2); pw.println(packageName); -                List<Pair<Uri, String>> uris = mActiveGrantsByPackage.valueAt(i); -                if (uris == null || uris.isEmpty())  { -                    continue; -                } -                for (Pair<Uri, String> uriAndActivity : uris) { -                    pw.print(prefix3); -                    pw.println(uriAndActivity.first + ": " + uriAndActivity.second); -                } -            } -        } -    }  } diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java index db5bc4d5d4b0..8525e3634e3a 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java @@ -57,7 +57,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;  import com.android.internal.os.IResultReceiver;  import com.android.server.autofill.ui.InlineFillUi; -import java.io.PrintWriter;  import java.util.ArrayList;  import java.util.List;  import java.util.concurrent.CancellationException; @@ -152,8 +151,8 @@ final class RemoteAugmentedAutofillService       * Called by {@link Session} to request augmented autofill.       */      public void onRequestAutofillLocked(int sessionId, @NonNull IAutoFillManagerClient client, -            int taskId, @NonNull ComponentName activityComponent, @NonNull AutofillId focusedId, -            @Nullable AutofillValue focusedValue, +            int taskId, @NonNull ComponentName activityComponent, @NonNull IBinder activityToken, +            @NonNull AutofillId focusedId, @Nullable AutofillValue focusedValue,              @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,              @Nullable Function<InlineFillUi, Boolean> inlineSuggestionsCallback,              @NonNull Runnable onErrorCallback, @@ -181,7 +180,8 @@ final class RemoteAugmentedAutofillService                                              inlineSuggestionsRequest, inlineSuggestionsData,                                              clientState, focusedId, focusedValue,                                              inlineSuggestionsCallback, client, onErrorCallback, -                                            remoteRenderService, userId, activityComponent); +                                            remoteRenderService, userId, +                                            activityComponent, activityToken);                                      if (!showingFillWindow) {                                          requestAutofill.complete(null);                                      } @@ -253,7 +253,7 @@ final class RemoteAugmentedAutofillService              @NonNull IAutoFillManagerClient client, @NonNull Runnable onErrorCallback,              @Nullable RemoteInlineSuggestionRenderService remoteRenderService,              int userId, -            @NonNull ComponentName targetActivity) { +            @NonNull ComponentName targetActivity, @NonNull IBinder targetActivityToken) {          if (inlineSuggestionsData == null || inlineSuggestionsData.isEmpty()                  || inlineSuggestionsCallback == null || request == null                  || remoteRenderService == null) { @@ -307,8 +307,8 @@ final class RemoteAugmentedAutofillService                                      final ArrayList<AutofillId> fieldIds = dataset.getFieldIds();                                      final ClipData content = dataset.getFieldContent();                                      if (content != null) { -                                        mUriGrantsManager.grantUriPermissions( -                                                targetActivity, userId, content); +                                        mUriGrantsManager.grantUriPermissions(targetActivity, +                                                targetActivityToken, userId, content);                                          final AutofillId fieldId = fieldIds.get(0);                                          if (sDebug) {                                              Slog.d(TAG, "Calling client autofillContent(): " @@ -368,12 +368,6 @@ final class RemoteAugmentedAutofillService                  + ComponentName.flattenToShortString(mComponentName) + "]";      } -    @Override -    public void dump(@NonNull String prefix, @NonNull PrintWriter pw) { -        super.dump(prefix, pw); -        mUriGrantsManager.dump(prefix, pw); -    } -      /**       * Called by {@link Session} when it's time to destroy all augmented autofill requests.       */ diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index f1dcdffe1397..042631d05186 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -1689,7 +1689,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState          if (content != null) {              final AutofillUriGrantsManager autofillUgm =                      remoteAugmentedAutofillService.getAutofillUriGrantsManager(); -            autofillUgm.grantUriPermissions(mComponentName, userId, content); +            autofillUgm.grantUriPermissions(mComponentName, mActivityToken, userId, content);          }          // Fill the value into the field. @@ -3537,7 +3537,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState                      synchronized (mLock) {                          logAugmentedAutofillRequestLocked(mode, remoteService.getComponentName(),                                  focusedId, isWhitelisted, inlineSuggestionsRequest != null); -                        remoteService.onRequestAutofillLocked(id, mClient, taskId, mComponentName, +                        remoteService.onRequestAutofillLocked(id, mClient, +                                taskId, mComponentName, mActivityToken,                                  AutofillId.withoutSession(focusedId), currentValue,                                  inlineSuggestionsRequest, inlineSuggestionsResponseCallback,                                  /*onErrorCallback=*/ () -> { @@ -4167,13 +4168,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState          if (remoteRenderService != null) {              remoteRenderService.destroySuggestionViews(userId, id);          } -        final RemoteAugmentedAutofillService remoteAugmentedAutofillService = -                mService.getRemoteAugmentedAutofillServiceIfCreatedLocked(); -        if (remoteAugmentedAutofillService != null) { -            final AutofillUriGrantsManager autofillUgm = -                    remoteAugmentedAutofillService.getAutofillUriGrantsManager(); -            autofillUgm.revokeUriPermissions(mComponentName, userId); -        }          mDestroyed = true; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index aa993bfeaf2e..9178a8d16d16 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -561,6 +561,14 @@ public abstract class ActivityTaskManagerInternal {      public abstract ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry();      /** +     * Returns the URI permission owner associated with the given activity (see +     * {@link ActivityRecord#getUriPermissionsLocked()}). If the passed-in activity token is +     * invalid, returns null. +     */ +    @Nullable +    public abstract IBinder getUriPermissionOwnerForActivity(@NonNull IBinder activityToken); + +    /**       * Gets bitmap snapshot of the provided task id.       *       * <p>Warning! this may restore the snapshot from disk so can block, don't call in a latency diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 0570f6cdfa77..65965ad6dbf6 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6256,6 +6256,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {              }          } +        @Nullable +        @Override +        public IBinder getUriPermissionOwnerForActivity(@NonNull IBinder activityToken) { +            ActivityTaskManagerService.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity"); +            synchronized (mGlobalLock) { +                ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken); +                return (r == null) ? null : r.getUriPermissionsLocked().getExternalToken(); +            } +        } +          @Override          public TaskSnapshot getTaskSnapshotBlocking(                  int taskId, boolean isLowResolution) { |