diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index db8a9f487b619..ce8a224a09956 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2316,6 +2316,10 @@ + + + diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java index b60dbd572b934..0a1de33b845b8 100644 --- a/media/java/android/media/AudioManagerInternal.java +++ b/media/java/android/media/AudioManagerInternal.java @@ -15,6 +15,7 @@ */ package android.media; +import android.util.IntArray; import com.android.server.LocalServices; /** @@ -43,6 +44,8 @@ public abstract class AudioManagerInternal { public abstract void updateRingerModeAffectedStreamsInternal(); + public abstract void setAccessibilityServiceUids(IntArray uids); + public interface RingerModeDelegate { /** Called when external ringer mode is evaluated, returns the new internal ringer mode */ int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index e4d71b65ed6a6..1147f16f5522e 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -181,7 +181,7 @@ - + mTempAccessibilityServiceInfoList = new ArrayList<>(); + private final IntArray mTempIntArray = new IntArray(0); + private final RemoteCallbackList mGlobalClients = new RemoteCallbackList<>(); @@ -1558,6 +1562,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + final int count = userState.mBoundServices.size(); + mTempIntArray.clear(); + for (int i = 0; i < count; i++) { + final ResolveInfo resolveInfo = + userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo(); + if (resolveInfo != null) { + mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid); + } + } + // Calling out with lock held, but to a lower-level service + final AudioManagerInternal audioManager = + LocalServices.getService(AudioManagerInternal.class); + if (audioManager != null) { + audioManager.setAccessibilityServiceUids(mTempIntArray); + } updateAccessibilityEnabledSetting(userState); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c139fa85bf3b1..49d1521e378f2 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -106,6 +106,7 @@ import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.IntArray; import android.util.Log; import android.util.MathUtils; import android.util.Slog; @@ -126,6 +127,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -575,6 +577,10 @@ public class AudioService extends IAudioService.Stub private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT; private long mLoweredFromNormalToVibrateTime; + // Array of Uids of valid accessibility services to check if caller is one of them + private int[] mAccessibilityServiceUids; + private final Object mAccessibilityServiceUidsLock = new Object(); + // Intent "extra" data keys. public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName"; public static final String CONNECT_INTENT_KEY_STATE = "state"; @@ -1241,11 +1247,9 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#adjustStreamVolume(int, int, int) */ public void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage) { - if ( streamType == AudioManager.STREAM_ACCESSIBILITY - && (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( - android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE))) { + if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) { Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without" - + "BIND_ACCESSIBILITY_SERVICE / callingPackage=" + callingPackage); + + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage); return; } adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage, @@ -1559,17 +1563,33 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#setStreamVolume(int, int, int) */ public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { - if ( streamType == AudioManager.STREAM_ACCESSIBILITY - && (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( - android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE))) { + if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) { Log.w(TAG, "Trying to call setStreamVolume() for a11y without" - + " BIND_ACCESSIBILITY_SERVICE callingPackage=" + callingPackage); + + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage); return; } setStreamVolume(streamType, index, flags, callingPackage, callingPackage, Binder.getCallingUid()); } + private boolean canChangeAccessibilityVolume() { + synchronized (mAccessibilityServiceUidsLock) { + if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( + android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) { + return true; + } + if (mAccessibilityServiceUids != null) { + int callingUid = Binder.getCallingUid(); + for (int i = 0; i < mAccessibilityServiceUids.length; i++) { + if (mAccessibilityServiceUids[i] == callingUid) { + return true; + } + } + } + return false; + } + } + private void setStreamVolume(int streamType, int index, int flags, String callingPackage, String caller, int uid) { if (DEBUG_VOL) { @@ -6380,6 +6400,29 @@ public class AudioService extends IAudioService.Stub } } } + + @Override + public void setAccessibilityServiceUids(IntArray uids) { + synchronized (mAccessibilityServiceUidsLock) { + if (uids.size() == 0) { + mAccessibilityServiceUids = null; + } else { + boolean changed = (mAccessibilityServiceUids == null) + || (mAccessibilityServiceUids.length != uids.size()); + if (!changed) { + for (int i = 0; i < mAccessibilityServiceUids.length; i++) { + if (uids.get(i) != mAccessibilityServiceUids[i]) { + changed = true; + break; + } + } + } + if (changed) { + mAccessibilityServiceUids = uids.toArray(); + } + } + } + } } //==========================================================================================