diff options
| author | 2021-04-06 17:27:14 +0100 | |
|---|---|---|
| committer | 2021-04-07 15:26:05 +0100 | |
| commit | 19a613c3da75c7a87bfa221d78e6e3b3dce287b1 (patch) | |
| tree | ca4d221d53f06cca06340a7944f35d6d142849a5 | |
| parent | 20953edc6f3015c17ddb735e21ccf3df38399cc0 (diff) | |
Allow accessibility services to send Intent.ACSD
For targetSdk < S. For S, they can use the new
GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE action to dismiss the
notification shade.
Bug: 159334261
Test: Send Intent.ACSD from an a11y service and verify shade is
collapsed when targetSdk < S, and exception thrown when targetSdk
S+.
Change-Id: I0e4be3faef8efa53a0b8a08263e842e0c4b1553e
4 files changed, 35 insertions, 8 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2c77372d6345..2c1c67eb6a42 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -18,6 +18,7 @@ package android.content; import static android.content.ContentProvider.maybeAddUserId; +import android.accessibilityservice.AccessibilityService; import android.annotation.AnyRes; import android.annotation.BroadcastBehavior; import android.annotation.IntDef; @@ -2479,6 +2480,8 @@ public class Intent implements Parcelable, Cloneable { * (eg. tests) is still able to use the intent. The platform will automatically collapse * the proper system dialogs in the proper use-cases. For all others, the user is the one in * control of closing dialogs. + * + * @see AccessibilityService#GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @RequiresPermission(android.Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 8e803b3619fb..05d4ba539a98 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1882,12 +1882,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid); } } - // Calling out with lock held, but to a lower-level service + // Calling out with lock held, but to lower-level services final AudioManagerInternal audioManager = LocalServices.getService(AudioManagerInternal.class); if (audioManager != null) { audioManager.setAccessibilityServiceUids(mTempIntArray); } + mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray); updateAccessibilityEnabledSettingLocked(userState); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index c09136eac302..aa993bfeaf2e 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.service.voice.IVoiceInteractionSession; +import android.util.IntArray; import android.util.proto.ProtoOutputStream; import android.window.TaskSnapshot; @@ -222,6 +223,11 @@ public abstract class ActivityTaskManagerInternal { @Nullable BackgroundActivityStartCallback callback); /** + * Sets the list of UIDs that contain an active accessibility service. + */ + public abstract void setAccessibilityServiceUids(IntArray uids); + + /** * Start activity {@code intent} without calling user-id check. * * - DO NOT call it with the calling UID cleared. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index c8fa50c35baa..7ae42cc9396a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -214,6 +214,7 @@ import android.telecom.TelecomManager; import android.text.format.TimeMigrationUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -677,6 +678,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Nullable private BackgroundActivityStartCallback mBackgroundActivityStartCallback; + private int[] mAccessibilityServiceUids = new int[0]; + private int mDeviceOwnerUid = Process.INVALID_UID; private final class SettingObserver extends ContentObserver { @@ -2990,20 +2993,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return true; } } - // This covers the case where the app is displaying some UI on top of the notification shade - // and wants to start an activity. The app then sends the intent in order to move the - // notification shade out of the way and show the activity to the user. This is fine since - // the caller already has privilege to show a visible window on top of the notification - // shade, so it can already prevent the user from accessing the shade if it wants to. - // We only allow for targetSdk < S, for S+ we automatically collapse the shade on - // startActivity() for these apps. if (!CompatChanges.isChangeEnabled(LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) { synchronized (mGlobalLock) { + // This covers the case where the app is displaying some UI on top of the + // notification shade and wants to start an activity. The app then sends the intent + // in order to move the notification shade out of the way and show the activity to + // the user. This is fine since the caller already has privilege to show a visible + // window on top of the notification shade, so it can already prevent the user from + // accessing the shade if it wants to. We only allow for targetSdk < S, for S+ we + // automatically collapse the shade on startActivity() for these apps. // It's ok that the owner of the shade is not allowed *per this rule* because it has // BROADCAST_CLOSE_SYSTEM_DIALOGS (SystemUI), so it would fall into that rule. if (mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade(uid)) { return true; } + // Accessibility services are allowed to send the intent unless they are targeting + // S+, in which case they should use {@link AccessibilityService + // #GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE} to dismiss the notification shade. + if (ArrayUtils.contains(mAccessibilityServiceUids, uid)) { + return true; + } } } return false; @@ -5122,12 +5131,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mVisibleActivityProcessTracker.hasResumedActivity(uid); } + @Override public void setBackgroundActivityStartCallback( @Nullable BackgroundActivityStartCallback backgroundActivityStartCallback) { mBackgroundActivityStartCallback = backgroundActivityStartCallback; } @Override + public void setAccessibilityServiceUids(IntArray uids) { + synchronized (mGlobalLock) { + mAccessibilityServiceUids = uids.toArray(); + } + } + + @Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) { Objects.requireNonNull(intents, "intents"); |