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

Commit 4548a03c authored by Christian Frank's avatar Christian Frank Committed by Automerger Merge Worker
Browse files

Merge "Improve permission enforcement in SoundTriggerService" into sc-dev am: f07d729c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14055979

Change-Id: Id9befdc043bee50c281e65983f894dd8086064f1
parents 2d28bdf1 f07d729c
Loading
Loading
Loading
Loading
+404 −369
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.media.permission.ClearCallingIdentityContext;
import android.media.permission.Identity;
import android.media.permission.IdentityContext;
import android.media.permission.PermissionUtil;
@@ -242,7 +243,7 @@ public class SoundTriggerService extends SystemService {
                @NonNull IBinder client) {
            try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
                    originatorIdentity)) {
                return new SoundTriggerSessionStub(newSoundTriggerHelper(), client);
                return new SoundTriggerSessionStub(client);
            }
        }

@@ -253,7 +254,7 @@ public class SoundTriggerService extends SystemService {
            try (SafeCloseable ignored = PermissionUtil.establishIdentityIndirect(mContext,
                    SOUNDTRIGGER_DELEGATE_IDENTITY, middlemanIdentity,
                    originatorIdentity)) {
                return new SoundTriggerSessionStub(newSoundTriggerHelper(), client);
                return new SoundTriggerSessionStub(client);
            }
        }
    }
@@ -262,14 +263,15 @@ public class SoundTriggerService extends SystemService {
        private final SoundTriggerHelper mSoundTriggerHelper;
        // Used to detect client death.
        private final IBinder mClient;
        private final Identity mOriginatorIdentity;
        private final TreeMap<UUID, SoundModel> mLoadedModels = new TreeMap<>();
        private final Object mCallbacksLock = new Object();
        private final TreeMap<UUID, IRecognitionStatusCallback> mCallbacks = new TreeMap<>();

        SoundTriggerSessionStub(
                SoundTriggerHelper soundTriggerHelper, @NonNull IBinder client) {
            mSoundTriggerHelper = soundTriggerHelper;
        SoundTriggerSessionStub(@NonNull IBinder client) {
            mSoundTriggerHelper = newSoundTriggerHelper();
            mClient = client;
            mOriginatorIdentity = IdentityContext.getNonNull();
            try {
                mClient.linkToDeath(() -> {
                    clientDied();
@@ -297,10 +299,12 @@ public class SoundTriggerService extends SystemService {
        @Override
        public int startRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback,
                RecognitionConfig config, boolean runInBatterySaverMode) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (runInBatterySaverMode) {
                    enforceCallingPermission(Manifest.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER);
                }

                if (DEBUG) {
                    Slog.i(TAG, "startRecognition(): Uuid : " + parcelUuid);
                }
@@ -325,9 +329,11 @@ public class SoundTriggerService extends SystemService {
                }
                return ret;
            }
        }

        @Override
        public int stopRecognition(ParcelUuid parcelUuid, IRecognitionStatusCallback callback) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "stopRecognition(): Uuid : " + parcelUuid);
@@ -336,15 +342,18 @@ public class SoundTriggerService extends SystemService {
                sEventLogger.log(new SoundTriggerLogger.StringEvent("stopRecognition(): Uuid : "
                        + parcelUuid));

            int ret = mSoundTriggerHelper.stopGenericRecognition(parcelUuid.getUuid(), callback);
                int ret = mSoundTriggerHelper.stopGenericRecognition(parcelUuid.getUuid(),
                        callback);
                if (ret == STATUS_OK) {
                    mSoundModelStatTracker.onStop(parcelUuid.getUuid());
                }
                return ret;
            }
        }

        @Override
        public SoundTrigger.GenericSoundModel getSoundModel(ParcelUuid soundModelId) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "getSoundModel(): id = " + soundModelId);
@@ -357,9 +366,11 @@ public class SoundTriggerService extends SystemService {
                        soundModelId.getUuid());
                return model;
            }
        }

        @Override
        public void updateSoundModel(SoundTrigger.GenericSoundModel soundModel) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "updateSoundModel(): model = " + soundModel);
@@ -370,9 +381,11 @@ public class SoundTriggerService extends SystemService {

                mDbHelper.updateGenericSoundModel(soundModel);
            }
        }

        @Override
        public void deleteSoundModel(ParcelUuid soundModelId) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "deleteSoundModel(): id = " + soundModelId);
@@ -389,9 +402,11 @@ public class SoundTriggerService extends SystemService {

                mDbHelper.deleteGenericSoundModel(soundModelId.getUuid());
            }
        }

        @Override
        public int loadGenericSoundModel(GenericSoundModel soundModel) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (soundModel == null || soundModel.getUuid() == null) {
                    Slog.e(TAG, "Invalid sound model");
@@ -423,9 +438,11 @@ public class SoundTriggerService extends SystemService {
                }
                return STATUS_OK;
            }
        }

        @Override
        public int loadKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (soundModel == null || soundModel.getUuid() == null) {
                    Slog.e(TAG, "Invalid sound model");
@@ -448,7 +465,8 @@ public class SoundTriggerService extends SystemService {
                    Slog.i(TAG, "loadKeyphraseSoundModel(): id = " + soundModel.getUuid());
                }

            sEventLogger.log(new SoundTriggerLogger.StringEvent("loadKeyphraseSoundModel(): id = "
                sEventLogger.log(
                        new SoundTriggerLogger.StringEvent("loadKeyphraseSoundModel(): id = "
                                + soundModel.getUuid()));

                synchronized (mLock) {
@@ -467,10 +485,12 @@ public class SoundTriggerService extends SystemService {
                }
                return STATUS_OK;
            }
        }

        @Override
        public int startRecognitionForService(ParcelUuid soundModelId, Bundle params,
            ComponentName detectionService, SoundTrigger.RecognitionConfig config) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                Objects.requireNonNull(soundModelId);
                Objects.requireNonNull(detectionService);
                Objects.requireNonNull(config);
@@ -544,9 +564,11 @@ public class SoundTriggerService extends SystemService {
                }
                return STATUS_OK;
            }
        }

        @Override
        public int stopRecognitionForService(ParcelUuid soundModelId) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "stopRecognition(): id = " + soundModelId);
@@ -610,9 +632,11 @@ public class SoundTriggerService extends SystemService {
                }
                return STATUS_OK;
            }
        }

        @Override
        public int unloadSoundModel(ParcelUuid soundModelId) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "unloadSoundModel(): id = " + soundModelId);
@@ -660,9 +684,11 @@ public class SoundTriggerService extends SystemService {
                    return STATUS_OK;
                }
            }
        }

        @Override
        public boolean isRecognitionActive(ParcelUuid parcelUuid) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                synchronized (mCallbacksLock) {
                    IRecognitionStatusCallback callback = mCallbacks.get(parcelUuid.getUuid());
@@ -672,9 +698,11 @@ public class SoundTriggerService extends SystemService {
                }
                return mSoundTriggerHelper.isRecognitionRequested(parcelUuid.getUuid());
            }
        }

        @Override
        public int getModelState(ParcelUuid soundModelId) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                int ret = STATUS_ERROR;
                if (DEBUG) {
@@ -710,10 +738,12 @@ public class SoundTriggerService extends SystemService {
                    return ret;
                }
            }
        }

        @Override
        @Nullable
        public ModuleProperties getModuleProperties() {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.i(TAG, "getModuleProperties()");
@@ -726,10 +756,12 @@ public class SoundTriggerService extends SystemService {
                    return properties;
                }
            }
        }

        @Override
        public int setParameter(ParcelUuid soundModelId,
                @ModelParams int modelParam, int value) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.d(TAG, "setParameter(): id=" + soundModelId
@@ -754,7 +786,9 @@ public class SoundTriggerService extends SystemService {
                        return STATUS_BAD_VALUE;
                    }

                return mSoundTriggerHelper.setParameter(soundModel.getUuid(), modelParam, value);
                    return mSoundTriggerHelper.setParameter(soundModel.getUuid(), modelParam,
                            value);
                }
            }
        }

@@ -762,6 +796,7 @@ public class SoundTriggerService extends SystemService {
        public int getParameter(@NonNull ParcelUuid soundModelId,
                @ModelParams int modelParam)
                throws UnsupportedOperationException, IllegalArgumentException {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.d(TAG, "getParameter(): id=" + soundModelId
@@ -786,11 +821,13 @@ public class SoundTriggerService extends SystemService {
                    return mSoundTriggerHelper.getParameter(soundModel.getUuid(), modelParam);
                }
            }
        }

        @Override
        @Nullable
        public ModelParamRange queryParameter(@NonNull ParcelUuid soundModelId,
                @ModelParams int modelParam) {
            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
                enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
                if (DEBUG) {
                    Slog.d(TAG, "queryParameter(): id=" + soundModelId
@@ -816,6 +853,7 @@ public class SoundTriggerService extends SystemService {
                    return mSoundTriggerHelper.queryParameter(soundModel.getUuid(), modelParam);
                }
            }
        }

        private void clientDied() {
            Slog.w(TAG, "Client died, cleaning up session.");
@@ -824,6 +862,20 @@ public class SoundTriggerService extends SystemService {
            mSoundTriggerHelper.detach();
        }

        private void enforceCallingPermission(String permission) {
            PermissionUtil.checkPermissionForPreflight(mContext, mOriginatorIdentity, permission);
        }

        private void enforceDetectionPermissions(ComponentName detectionService) {
            PackageManager packageManager = mContext.getPackageManager();
            String packageName = detectionService.getPackageName();
            if (packageManager.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
                    != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException(detectionService.getPackageName() + " does not have"
                        + " permission " + Manifest.permission.CAPTURE_AUDIO_HOTWORD);
            }
        }

        /**
         * Local end for a {@link SoundTriggerDetectionService}. Operations are queued up and
         * executed when the service connects.
@@ -1577,23 +1629,6 @@ public class SoundTriggerService extends SystemService {
        }
    }

    private void enforceCallingPermission(String permission) {
        if (mContext.checkCallingOrSelfPermission(permission)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Caller does not hold the permission " + permission);
        }
    }

    private void enforceDetectionPermissions(ComponentName detectionService) {
        PackageManager packageManager = mContext.getPackageManager();
        String packageName = detectionService.getPackageName();
        if (packageManager.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException(detectionService.getPackageName() + " does not have"
                    + " permission " + Manifest.permission.CAPTURE_AUDIO_HOTWORD);
        }
    }

    //=================================================================
    // For logging