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

Commit 0e5e8dbd authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge "Re-add partial hotword indicator exemption" into main

parents a9fdbf38 22198594
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPH
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__SERVICE_CRASH;

import android.app.AppOpsManager;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.ChangeId;
@@ -548,13 +549,15 @@ final class HotwordDetectionConnection {
    static final class SoundTriggerCallback extends IRecognitionStatusCallback.Stub {
        private final HotwordDetectionConnection mHotwordDetectionConnection;
        private final IHotwordRecognitionStatusCallback mExternalCallback;
        private final int mVoiceInteractionServiceUid;
        private final Identity mVoiceInteractorIdentity;
        private final Context mContext;

        SoundTriggerCallback(IHotwordRecognitionStatusCallback callback,
                HotwordDetectionConnection connection, int uid) {
        SoundTriggerCallback(Context context, IHotwordRecognitionStatusCallback callback,
                HotwordDetectionConnection connection, Identity voiceInteractorIdentity) {
            mContext = context;
            mHotwordDetectionConnection = connection;
            mExternalCallback = callback;
            mVoiceInteractionServiceUid = uid;
            mVoiceInteractorIdentity = voiceInteractorIdentity;
        }

        @Override
@@ -568,17 +571,32 @@ final class HotwordDetectionConnection {
                HotwordMetricsLogger.writeKeyphraseTriggerEvent(
                        HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP,
                        HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER,
                        mVoiceInteractionServiceUid);
                        mVoiceInteractorIdentity.uid);
                mHotwordDetectionConnection.detectFromDspSource(
                        recognitionEvent, mExternalCallback);
            } else {
                // We have to attribute ops here, since we configure all st clients as trusted to
                // enable a partial exemption.
                // TODO (b/292012931) remove once trusted uniformly required.
                int result = mContext.getSystemService(AppOpsManager.class)
                        .noteOpNoThrow(AppOpsManager.OP_RECORD_AUDIO_HOTWORD,
                            mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
                            mVoiceInteractorIdentity.attributionTag,
                            "Non-HDS keyphrase recognition to VoiceInteractionService");

                if (result != AppOpsManager.MODE_ALLOWED) {
                    Slog.w(TAG, "onKeyphraseDetected suppressed, permission check returned: "
                            + result);
                    mExternalCallback.onRecognitionPaused();
                } else {
                    HotwordMetricsLogger.writeKeyphraseTriggerEvent(
                            HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR,
                            HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER,
                        mVoiceInteractionServiceUid);
                            mVoiceInteractorIdentity.uid);
                    mExternalCallback.onKeyphraseDetected(recognitionEvent, null);
                }
            }
        }

        @Override
        public void onGenericSoundTriggerDetected(
+24 −6
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.permission.LegacyPermissionManagerInternal;
import com.android.server.policy.AppOpsPolicy;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -336,6 +337,9 @@ public class VoiceInteractionManagerService extends SystemService {
        /** The start value of showSessionId */
        private static final int SHOW_SESSION_START_ID = 0;

        private final boolean IS_HDS_REQUIRED = AppOpsPolicy.isHotwordDetectionServiceRequired(
                mContext.getPackageManager());

        @GuardedBy("this")
        private int mShowSessionId = SHOW_SESSION_START_ID;

@@ -393,8 +397,14 @@ public class VoiceInteractionManagerService extends SystemService {
            }
            try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
                    originatorIdentity)) {
                if (!IS_HDS_REQUIRED) {
                    // For devices which still have hotword exemption, any client (not just HDS
                    // clients) are trusted.
                    // TODO (b/292012931) remove once trusted uniformly required.
                    forHotwordDetectionService = true;
                }
                return new SoundTriggerSession(mSoundTriggerInternal.attach(client,
                            moduleProperties, forHotwordDetectionService));
                            moduleProperties, forHotwordDetectionService), originatorIdentity);
            }
        }

@@ -1674,10 +1684,13 @@ public class VoiceInteractionManagerService extends SystemService {
            final SoundTriggerInternal.Session mSession;
            private IHotwordRecognitionStatusCallback mSessionExternalCallback;
            private IRecognitionStatusCallback mSessionInternalCallback;
            private final Identity mVoiceInteractorIdentity;

            SoundTriggerSession(
                    SoundTriggerInternal.Session session) {
                    SoundTriggerInternal.Session session,
                    Identity voiceInteractorIdentity) {
                mSession = session;
                mVoiceInteractorIdentity = voiceInteractorIdentity;
            }

            @Override
@@ -1731,7 +1744,8 @@ public class VoiceInteractionManagerService extends SystemService {
                        if (mSessionExternalCallback == null
                                || mSessionInternalCallback == null
                                || callback.asBinder() != mSessionExternalCallback.asBinder()) {
                            mSessionInternalCallback = createSoundTriggerCallbackLocked(callback);
                            mSessionInternalCallback = createSoundTriggerCallbackLocked(callback,
                                    mVoiceInteractorIdentity);
                            mSessionExternalCallback = callback;
                        }
                    }
@@ -1752,7 +1766,8 @@ public class VoiceInteractionManagerService extends SystemService {
                    if (mSessionExternalCallback == null
                            || mSessionInternalCallback == null
                            || callback.asBinder() != mSessionExternalCallback.asBinder()) {
                        soundTriggerCallback = createSoundTriggerCallbackLocked(callback);
                        soundTriggerCallback = createSoundTriggerCallbackLocked(callback,
                                mVoiceInteractorIdentity);
                        Slog.w(TAG, "stopRecognition() called with a different callback than"
                                + "startRecognition()");
                    } else {
@@ -2090,6 +2105,7 @@ public class VoiceInteractionManagerService extends SystemService {
                pw.println("  mTemporarilyDisabled: " + mTemporarilyDisabled);
                pw.println("  mCurUser: " + mCurUser);
                pw.println("  mCurUserSupported: " + mCurUserSupported);
                pw.println("  mIsHdsRequired: " + IS_HDS_REQUIRED);
                dumpSupportedUsers(pw, "  ");
                mDbHelper.dump(pw);
                if (mImpl == null) {
@@ -2165,11 +2181,13 @@ public class VoiceInteractionManagerService extends SystemService {
        }

        private IRecognitionStatusCallback createSoundTriggerCallbackLocked(
                IHotwordRecognitionStatusCallback callback) {
                IHotwordRecognitionStatusCallback callback,
                Identity voiceInteractorIdentity) {
            if (mImpl == null) {
                return null;
            }
            return mImpl.createSoundTriggerCallbackLocked(callback);
            return mImpl.createSoundTriggerCallbackLocked(mContext, callback,
                    voiceInteractorIdentity);
        }

        class RoleObserver implements OnRoleHoldersChangedListener {
+4 −3
Original line number Diff line number Diff line
@@ -877,12 +877,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
    }

    public IRecognitionStatusCallback createSoundTriggerCallbackLocked(
            IHotwordRecognitionStatusCallback callback) {
            Context context, IHotwordRecognitionStatusCallback callback,
            Identity voiceInteractorIdentity) {
        if (DEBUG) {
            Slog.d(TAG, "createSoundTriggerCallbackLocked");
        }
        return new HotwordDetectionConnection.SoundTriggerCallback(callback,
                mHotwordDetectionConnection, mInfo.getServiceInfo().applicationInfo.uid);
        return new HotwordDetectionConnection.SoundTriggerCallback(context, callback,
                mHotwordDetectionConnection, voiceInteractorIdentity);
    }

    private static ServiceInfo getServiceInfoLocked(@NonNull ComponentName componentName,