Merge "Re-init HotwordDetectionSrvc when audioserver dies" into sc-dev
This commit is contained in:
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user