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

Commit 14c3ff69 authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Share process between SandboxedDetectionServices"

parents 5c85be46 086031e1
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.pm.permission;

import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
import static android.Manifest.permission.CAPTURE_AUDIO_OUTPUT;
import static android.Manifest.permission.RECORD_AUDIO;
@@ -1379,14 +1380,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
                    uid) == PackageManager.PERMISSION_GRANTED;

            // Override certain permissions checks for the HotwordDetectionService. This service is
            // an isolated service, which ordinarily cannot hold permissions.
            // Override certain permissions checks for the shared isolated process for both
            // HotwordDetectionService and VisualQueryDetectionService, which ordinarily cannot hold
            // any permissions.
            // There's probably a cleaner, more generalizable way to do this. For now, this is
            // the only use case for this, so simply override here.
            if (!permissionGranted
                    && Process.isIsolated(uid) // simple check which fails-fast for the common case
                    && (permission.equals(RECORD_AUDIO) || permission.equals(CAPTURE_AUDIO_HOTWORD)
                    || permission.equals(CAPTURE_AUDIO_OUTPUT))) {
                    || permission.equals(CAPTURE_AUDIO_OUTPUT) || permission.equals(CAMERA))) {
                HotwordDetectionServiceProvider hotwordServiceProvider =
                        permissionManagerServiceInt.getHotwordDetectionServiceProvider();
                permissionGranted = hotwordServiceProvider != null
+2 −1
Original line number Diff line number Diff line
@@ -447,7 +447,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
        // package, so we don't need to modify it.
        if (Process.isIsolated(uid) // simple check which fails-fast for the common case
                && (code == AppOpsManager.OP_RECORD_AUDIO
                || code == AppOpsManager.OP_RECORD_AUDIO_HOTWORD)) {
                || code == AppOpsManager.OP_RECORD_AUDIO_HOTWORD
                || code == AppOpsManager.OP_CAMERA)) {
            final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
                    mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
            if (hotwordDetectionServiceIdentity != null
+28 −17
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ final class HotwordDetectionConnection {
    final int mUser;
    final Context mContext;
    volatile HotwordDetectionServiceIdentity mIdentity;
    //TODO: add similar identity for visual query service for the use of content capturing
    //TODO: Consider rename this to SandboxedDetectionIdentity
    private Instant mLastRestartInstant;

    private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
@@ -117,6 +117,7 @@ final class HotwordDetectionConnection {
    @GuardedBy("mLock")
    @Nullable
    private final Identity mVoiceInteractorIdentity;
    private int mRestartCount = 0;
    @NonNull private ServiceConnection mRemoteHotwordDetectionService;
    @NonNull private ServiceConnection mRemoteVisualQueryDetectionService;
    private IBinder mAudioFlinger;
@@ -234,10 +235,6 @@ final class HotwordDetectionConnection {
        mDebugHotwordLogging = false;
        unbindVisualQueryDetectionService();
        unbindHotwordDetectionService();
        if (mIdentity != null) {
            removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
        }
        mIdentity = null;
        if (mCancellationTaskFuture != null) {
            mCancellationTaskFuture.cancel(/* mayInterruptIfRunning= */ true);
        }
@@ -246,18 +243,34 @@ final class HotwordDetectionConnection {
        }
    }

    @SuppressWarnings("GuardedBy")
    private void unbindVisualQueryDetectionService() {
        if (mRemoteVisualQueryDetectionService != null) {
            mRemoteVisualQueryDetectionService.unbind();
            //TODO: Set visual query detection service provider to null
            mRemoteVisualQueryDetectionService = null;
        }
        resetDetectionProcessIdentityIfEmptyLocked();
    }

    @SuppressWarnings("GuardedBy")
    private void unbindHotwordDetectionService() {
        if (mRemoteHotwordDetectionService != null) {
            mRemoteHotwordDetectionService.unbind();
            mRemoteHotwordDetectionService = null;
        }
        resetDetectionProcessIdentityIfEmptyLocked();
    }

    // TODO(b/266669849): Clean up SuppressWarnings for calling methods.
    @GuardedBy("mLock")
    private void resetDetectionProcessIdentityIfEmptyLocked() {
        if (mRemoteHotwordDetectionService == null && mRemoteVisualQueryDetectionService == null) {
            LocalServices.getService(PermissionManagerServiceInternal.class)
                .setHotwordDetectionServiceProvider(null);
            if (mIdentity != null) {
                removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
            }
            mIdentity = null;
        }
    }

@@ -427,10 +440,10 @@ final class HotwordDetectionConnection {
        ServiceConnection oldHotwordConnection = mRemoteHotwordDetectionService;
        ServiceConnection oldVisualQueryDetectionConnection = mRemoteVisualQueryDetectionService;
        HotwordDetectionServiceIdentity previousIdentity = mIdentity;
        //TODO: Add previousIdentity for visual query detection service

        mLastRestartInstant = Instant.now();
        // Recreate connection to reset the cache.
        mRestartCount++;

        mRemoteHotwordDetectionService = mHotwordDetectionServiceConnectionFactory.createLocked();
        mRemoteVisualQueryDetectionService =
@@ -458,6 +471,9 @@ final class HotwordDetectionConnection {
            oldVisualQueryDetectionConnection.unbind();
        }

        // TODO(b/266670431): Handles identity resetting for the new process to make sure the
        // correct identity is provided.

        if (previousIdentity != null) {
            removeServiceUidForAudioPolicy(previousIdentity.getIsolatedUid());
        }
@@ -531,8 +547,7 @@ final class HotwordDetectionConnection {
                    && mRemoteHotwordDetectionService != null
                    && mRemoteHotwordDetectionService.isBound());
            pw.print(prefix); pw.print("mRestartCount=");
            pw.println(mHotwordDetectionServiceConnectionFactory.mRestartCount);
            pw.println(mVisualQueryDetectionServiceConnectionFactory.mRestartCount);
            pw.println(mRestartCount);
            pw.print(prefix); pw.print("mLastRestartInstant="); pw.println(mLastRestartInstant);
            pw.print(prefix); pw.print("mDetectorType=");
            pw.println(HotwordDetector.detectorTypeToString(mDetectorType));
@@ -547,8 +562,6 @@ final class HotwordDetectionConnection {
        private final Intent mIntent;
        private final int mBindingFlags;

        private int mRestartCount = 0;

        ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed) {
            mIntent = intent;
            mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
@@ -558,7 +571,7 @@ final class HotwordDetectionConnection {
            ServiceConnection connection =
                    new ServiceConnection(mContext, mIntent, mBindingFlags, mUser,
                            ISandboxedDetectionService.Stub::asInterface,
                            mRestartCount++ % MAX_ISOLATED_PROCESS_NUMBER);
                            mRestartCount % MAX_ISOLATED_PROCESS_NUMBER);
            connection.connect();

            updateAudioFlinger(connection, mAudioFlinger);
@@ -660,13 +673,11 @@ final class HotwordDetectionConnection {
                            HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE,
                            mVoiceInteractionServiceUid);
                }
                String instancePrefix =
                        mIntent.getAction().equals(HotwordDetectionService.SERVICE_INTERFACE)
                                ? "hotword_detector_" : "visual_query_detector_";
                boolean bindResult = mContext.bindIsolatedService(
                        mIntent,
                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
                        instancePrefix + mInstanceNumber,
                        Context.BIND_SHARED_ISOLATED_PROCESS | Context.BIND_AUTO_CREATE
                                | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
                        "hotword_detector_" + mInstanceNumber,
                        mExecutor,
                        serviceConnection);
                if (!bindResult) {