Loading services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java +28 −157 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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}. */ Loading @@ -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. * Loading @@ -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); } } } } } services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java +7 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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); } Loading Loading @@ -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) { Loading Loading @@ -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(): " Loading Loading @@ -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. */ Loading services/autofill/java/com/android/server/autofill/Session.java +3 −9 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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=*/ () -> { Loading Loading @@ -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; Loading services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,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. * Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading
services/autofill/java/com/android/server/autofill/AutofillUriGrantsManager.java +28 −157 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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}. */ Loading @@ -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. * Loading @@ -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); } } } } }
services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java +7 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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); } Loading Loading @@ -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) { Loading Loading @@ -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(): " Loading Loading @@ -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. */ Loading
services/autofill/java/com/android/server/autofill/Session.java +3 −9 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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=*/ () -> { Loading Loading @@ -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; Loading
services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +8 −0 Original line number Diff line number Diff line Loading @@ -560,6 +560,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. * Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +10 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading