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

Commit 11aca08c authored by Ahaan Ugale's avatar Ahaan Ugale Committed by Automerger Merge Worker
Browse files

Merge "Re-init HotwordDetectionSrvc when audioserver dies" into sc-dev am: 8fd0ab20

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15187469

Change-Id: Iedd4ac42c63e3920ad519504b8d335e10041ccb8
parents ace2b664 8fd0ab20
Loading
Loading
Loading
Loading
+42 −9
Original line number Diff line number Diff line
@@ -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) {
@@ -491,7 +528,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");
@@ -679,13 +716,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;
@@ -795,12 +832,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));
    }