Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading services/core/java/com/android/server/policy/AppOpsPolicy.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +28 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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; } } Loading Loading @@ -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 = Loading Loading @@ -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()); } Loading Loading @@ -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)); Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +5 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
services/core/java/com/android/server/policy/AppOpsPolicy.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +28 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading @@ -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; } } Loading Loading @@ -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 = Loading Loading @@ -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()); } Loading Loading @@ -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)); Loading @@ -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; Loading @@ -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); Loading Loading @@ -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) { Loading