Merge "Fix permission checking for a11y volume."

This commit is contained in:
Phil Weaver
2017-03-28 03:58:12 +00:00
committed by Android (Google) Code Review
5 changed files with 78 additions and 9 deletions

View File

@@ -2316,6 +2316,10 @@
<permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA"
android:protectionLevel="signature" />
<!-- @hide Allows an application to change the accessibility volume. -->
<permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME"
android:protectionLevel="signature" />
<!-- @hide Allows an application to collect frame statistics -->
<permission android:name="android.permission.FRAME_STATS"
android:protectionLevel="signature" />

View File

@@ -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,

View File

@@ -181,7 +181,7 @@
<uses-permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA" />
<!-- to control accessibility volume -->
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME" />
<application
android:name=".SystemUIApplication"

View File

@@ -52,6 +52,7 @@ import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.input.InputManager;
import android.media.AudioManagerInternal;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -75,6 +76,7 @@ import android.provider.SettingsStringUtil.ComponentNameSet;
import android.provider.SettingsStringUtil.SettingStringHelper;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -220,6 +222,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
new ArrayList<>();
private final IntArray mTempIntArray = new IntArray(0);
private final RemoteCallbackList<IAccessibilityManagerClient> 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);
}

View File

@@ -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();
}
}
}
}
}
//==========================================================================================