diff options
| -rw-r--r-- | services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index e80dc827c3fd..3ff719ce465e 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -92,6 +92,7 @@ final class HotwordDetectionConnection { private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); + private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; private final @NonNull ServiceConnectionFactory mServiceConnectionFactory; final Object mLock; @@ -113,6 +114,7 @@ final class HotwordDetectionConnection { @GuardedBy("mLock") private boolean mPerformingSoftwareHotwordDetection; private @NonNull ServiceConnection mRemoteHotwordDetectionService; + private IBinder mAudioFlinger; HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid, ComponentName serviceName, int userId, boolean bindInstantServiceAllowed, @@ -125,10 +127,11 @@ final class HotwordDetectionConnection { mUser = userId; final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE); intent.setComponent(mDetectionComponentName); + initAudioFlingerLocked(); mServiceConnectionFactory = new ServiceConnectionFactory(intent, bindInstantServiceAllowed); - mRemoteHotwordDetectionService = mServiceConnectionFactory.create(); + mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked(); if (callback == null) { updateStateLocked(options, sharedMemory); @@ -152,6 +155,37 @@ final class HotwordDetectionConnection { }, 30, 30, TimeUnit.MINUTES); } + private void initAudioFlingerLocked() { + if (DEBUG) { + Slog.d(TAG, "initAudioFlingerLocked"); + } + mAudioFlinger = ServiceManager.waitForService("media.audio_flinger"); + if (mAudioFlinger == null) { + throw new IllegalStateException("Service media.audio_flinger wasn't found."); + } + if (DEBUG) { + Slog.d(TAG, "Obtained audio_flinger binder."); + } + try { + mAudioFlinger.linkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); + } catch (RemoteException e) { + Slog.w(TAG, "Audio server died before we registered a DeathRecipient; retrying init.", + e); + initAudioFlingerLocked(); + } + } + + private void audioServerDied() { + Slog.w(TAG, "Audio server died; restarting the HotwordDetectionService."); + synchronized (mLock) { + // TODO: Check if this needs to be scheduled on a different thread. + initAudioFlingerLocked(); + // We restart the process instead of simply sending over the new binder, to avoid race + // conditions with audio reading in the service. + restartProcessLocked(); + } + } + private void updateStateAfterProcessStart( PersistableBundle options, SharedMemory sharedMemory) { if (DEBUG) { @@ -230,6 +264,9 @@ final class HotwordDetectionConnection { mIdentity = null; } mCancellationTaskFuture.cancel(/* may interrupt */ true); + if (mAudioFlinger != null) { + mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); + } } void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) { @@ -479,7 +516,7 @@ final class HotwordDetectionConnection { mLastRestartInstant = Instant.now(); // Recreate connection to reset the cache. - mRemoteHotwordDetectionService = mServiceConnectionFactory.create(); + mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked(); if (DEBUG) { Slog.i(TAG, "Started the new process, issuing #onProcessRestarted"); @@ -663,13 +700,13 @@ final class HotwordDetectionConnection { mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0; } - ServiceConnection create() { + ServiceConnection createLocked() { ServiceConnection connection = new ServiceConnection(mContext, mIntent, mBindingFlags, mUser, IHotwordDetectionService.Stub::asInterface, ++mRestartCount); connection.connect(); - updateAudioFlinger(connection); + updateAudioFlinger(connection, mAudioFlinger); updateContentCaptureManager(connection); updateServiceIdentity(connection); return connection; @@ -779,12 +816,8 @@ final class HotwordDetectionConnection { return Pair.create(fileDescriptors[0], fileDescriptors[1]); } - private static void updateAudioFlinger(ServiceConnection connection) { + private static void updateAudioFlinger(ServiceConnection connection, IBinder audioFlinger) { // TODO: Consider using a proxy that limits the exposed API surface. - IBinder audioFlinger = ServiceManager.getService("media.audio_flinger"); - if (audioFlinger == null) { - throw new IllegalStateException("Service media.audio_flinger wasn't found."); - } connection.run(service -> service.updateAudioFlinger(audioFlinger)); } |