Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 668c3444 authored by Phil Weaver's avatar Phil Weaver Committed by Android (Google) Code Review
Browse files

Merge "Fix permission checking for a11y volume."

parents 9a8eb3db f1a9aff9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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" />
+3 −0
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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"
+19 −0
Original line number Diff line number Diff line
@@ -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);
    }

+51 −8
Original line number Diff line number Diff line
@@ -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();
                    }
                }
            }
        }
    }

    //==========================================================================================