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

Commit 2a383b6e authored by Atneya Nair's avatar Atneya Nair
Browse files

[hotword] Fix async updateServiceIdentity

The callback used to updated the HDS identity is oneway, which means it
doesn't execute sync with respect to the other connection startup tasks,
and the service can be marked as ready before the identity is updated.

This can lead to some races with permission checks for HDS. Switch the
binder callback to non-oneway, and enqueue all the tasks on a dedicated
handler thread to avoid clogging the main thread.

Test: manual assistant enable/disable and functionality
Test: atest AlwaysOnHotwordDetectorTest
Bug: 384399959
Flag: EXEMPT bugfix
Change-Id: Ib527e28a1b0a0b2f7521a7ef505705db547eca9c
parent c82f67a6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -230,8 +230,8 @@ public abstract class HotwordDetectionService extends Service
        }

        @Override
        public void ping(IRemoteCallback callback) throws RemoteException {
            callback.sendResult(null);
        public void ping(IPingMe callback) throws RemoteException {
            callback.onPing();
        }

        @Override
+5 −1
Original line number Diff line number Diff line
@@ -65,11 +65,15 @@ oneway interface ISandboxedDetectionService {
    void updateRecognitionServiceManager(
        in IRecognitionServiceManager recognitionServiceManager);

    interface IPingMe {
        void onPing();
    }

    /**
     * Simply requests the service to trigger the callback, so that the system can check its
     * identity.
     */
    void ping(in IRemoteCallback callback);
    void ping(in IPingMe callback);

    void stopDetection();

+2 −2
Original line number Diff line number Diff line
@@ -122,8 +122,8 @@ public abstract class VisualQueryDetectionService extends Service
        }

        @Override
        public void ping(IRemoteCallback callback) throws RemoteException {
            callback.sendResult(null);
        public void ping(IPingMe callback) throws RemoteException {
            callback.onPing();
        }

        @Override
+17 −5
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ import android.media.AudioManagerInternal;
import android.media.permission.Identity;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
@@ -837,6 +839,13 @@ final class HotwordDetectionConnection {
        private final int mBindingFlags;
        private final int mInstanceNumber;

        private static final HandlerThread mHandler;

        static {
            mHandler = new HandlerThread("Sandbox detection connector");
            mHandler.start();
        }

        private boolean mRespectServiceConnectionStatusChanged = true;
        private boolean mIsBound = false;
        private boolean mIsLoggedFirstConnect = false;
@@ -883,6 +892,11 @@ final class HotwordDetectionConnection {
            }
        }

        @Override // from ServiceConnector.Impl
        protected Handler getJobHandler() {
            return mHandler.getThreadHandler();
        }

        @Override
        protected long getAutoDisconnectTimeoutMs() {
            return -1;
@@ -1151,14 +1165,12 @@ final class HotwordDetectionConnection {
    }

    private void updateServiceIdentity(ServiceConnection connection) {
        connection.run(service -> service.ping(new IRemoteCallback.Stub() {
        connection.run(service -> service.ping(new ISandboxedDetectionService.IPingMe.Stub() {
            @Override
            public void sendResult(Bundle bundle) throws RemoteException {
            public void onPing() throws RemoteException {
                // TODO: Exit if the service has been unbound already (though there's a very low
                // chance this happens).
                if (DEBUG) {
                Slog.d(TAG, "updating hotword UID " + Binder.getCallingUid());
                }
                // TODO: Have the provider point to the current state stored in
                // VoiceInteractionManagerServiceImpl.
                final int uid = Binder.getCallingUid();