Merge "Re-init HotwordDetectionSrvc when audioserver dies" into sc-dev

This commit is contained in:
Ahaan Ugale
2021-07-03 08:50:06 +00:00
committed by Android (Google) Code Review

View File

@@ -92,6 +92,7 @@ final class HotwordDetectionConnection {
private final ScheduledExecutorService mScheduledExecutorService = private final ScheduledExecutorService mScheduledExecutorService =
Executors.newSingleThreadScheduledExecutor(); Executors.newSingleThreadScheduledExecutor();
private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
private final @NonNull ServiceConnectionFactory mServiceConnectionFactory; private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
final Object mLock; final Object mLock;
@@ -113,6 +114,7 @@ final class HotwordDetectionConnection {
@GuardedBy("mLock") @GuardedBy("mLock")
private boolean mPerformingSoftwareHotwordDetection; private boolean mPerformingSoftwareHotwordDetection;
private @NonNull ServiceConnection mRemoteHotwordDetectionService; private @NonNull ServiceConnection mRemoteHotwordDetectionService;
private IBinder mAudioFlinger;
HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid, HotwordDetectionConnection(Object lock, Context context, int voiceInteractionServiceUid,
ComponentName serviceName, int userId, boolean bindInstantServiceAllowed, ComponentName serviceName, int userId, boolean bindInstantServiceAllowed,
@@ -125,10 +127,11 @@ final class HotwordDetectionConnection {
mUser = userId; mUser = userId;
final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE); final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE);
intent.setComponent(mDetectionComponentName); intent.setComponent(mDetectionComponentName);
initAudioFlingerLocked();
mServiceConnectionFactory = new ServiceConnectionFactory(intent, bindInstantServiceAllowed); mServiceConnectionFactory = new ServiceConnectionFactory(intent, bindInstantServiceAllowed);
mRemoteHotwordDetectionService = mServiceConnectionFactory.create(); mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked();
if (callback == null) { if (callback == null) {
updateStateLocked(options, sharedMemory); updateStateLocked(options, sharedMemory);
@@ -152,6 +155,37 @@ final class HotwordDetectionConnection {
}, 30, 30, TimeUnit.MINUTES); }, 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( private void updateStateAfterProcessStart(
PersistableBundle options, SharedMemory sharedMemory) { PersistableBundle options, SharedMemory sharedMemory) {
if (DEBUG) { if (DEBUG) {
@@ -230,6 +264,9 @@ final class HotwordDetectionConnection {
mIdentity = null; mIdentity = null;
} }
mCancellationTaskFuture.cancel(/* may interrupt */ true); mCancellationTaskFuture.cancel(/* may interrupt */ true);
if (mAudioFlinger != null) {
mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
}
} }
void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) { void updateStateLocked(PersistableBundle options, SharedMemory sharedMemory) {
@@ -491,7 +528,7 @@ final class HotwordDetectionConnection {
mLastRestartInstant = Instant.now(); mLastRestartInstant = Instant.now();
// Recreate connection to reset the cache. // Recreate connection to reset the cache.
mRemoteHotwordDetectionService = mServiceConnectionFactory.create(); mRemoteHotwordDetectionService = mServiceConnectionFactory.createLocked();
if (DEBUG) { if (DEBUG) {
Slog.i(TAG, "Started the new process, issuing #onProcessRestarted"); Slog.i(TAG, "Started the new process, issuing #onProcessRestarted");
@@ -679,13 +716,13 @@ final class HotwordDetectionConnection {
mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0; mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
} }
ServiceConnection create() { ServiceConnection createLocked() {
ServiceConnection connection = ServiceConnection connection =
new ServiceConnection(mContext, mIntent, mBindingFlags, mUser, new ServiceConnection(mContext, mIntent, mBindingFlags, mUser,
IHotwordDetectionService.Stub::asInterface, ++mRestartCount); IHotwordDetectionService.Stub::asInterface, ++mRestartCount);
connection.connect(); connection.connect();
updateAudioFlinger(connection); updateAudioFlinger(connection, mAudioFlinger);
updateContentCaptureManager(connection); updateContentCaptureManager(connection);
updateServiceIdentity(connection); updateServiceIdentity(connection);
return connection; return connection;
@@ -795,12 +832,8 @@ final class HotwordDetectionConnection {
return Pair.create(fileDescriptors[0], fileDescriptors[1]); 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. // 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)); connection.run(service -> service.updateAudioFlinger(audioFlinger));
} }