diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index b7d97057a08b3a47f548f3f3e54fad1ce7667474..adc54f5b5a8c050c344b743a1064c91e3975ba69 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -94,7 +94,9 @@ public class VisualQueryDetector {
      */
     public void updateState(@Nullable PersistableBundle options,
             @Nullable SharedMemory sharedMemory) {
-        mInitializationDelegate.updateState(options, sharedMemory);
+        synchronized (mInitializationDelegate.getLock()) {
+            mInitializationDelegate.updateState(options, sharedMemory);
+        }
     }
 
 
@@ -116,18 +118,21 @@ public class VisualQueryDetector {
         if (DEBUG) {
             Slog.i(TAG, "#startRecognition");
         }
-        // check if the detector is active with the initialization delegate
-        mInitializationDelegate.startRecognition();
-
-        try {
-            mManagerService.startPerceiving(new BinderCallback(mExecutor, mCallback));
-        } catch (SecurityException e) {
-            Slog.e(TAG, "startRecognition failed: " + e);
-            return false;
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+        synchronized (mInitializationDelegate.getLock()) {
+            // check if the detector is active with the initialization delegate
+            mInitializationDelegate.startRecognition();
+
+            try {
+                mManagerService.startPerceiving(new BinderCallback(
+                        mExecutor, mCallback, mInitializationDelegate.getLock()));
+            } catch (SecurityException e) {
+                Slog.e(TAG, "startRecognition failed: " + e);
+                return false;
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+            return true;
         }
-        return true;
     }
 
     /**
@@ -140,15 +145,17 @@ public class VisualQueryDetector {
         if (DEBUG) {
             Slog.i(TAG, "#stopRecognition");
         }
-        // check if the detector is active with the initialization delegate
-        mInitializationDelegate.startRecognition();
-
-        try {
-            mManagerService.stopPerceiving();
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+        synchronized (mInitializationDelegate.getLock()) {
+            // check if the detector is active with the initialization delegate
+            mInitializationDelegate.stopRecognition();
+
+            try {
+                mManagerService.stopPerceiving();
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+            return true;
         }
-        return true;
     }
 
     /**
@@ -160,12 +167,16 @@ public class VisualQueryDetector {
         if (DEBUG) {
             Slog.i(TAG, "#destroy");
         }
-        mInitializationDelegate.destroy();
+        synchronized (mInitializationDelegate.getLock()) {
+            mInitializationDelegate.destroy();
+        }
     }
 
     /** @hide */
     public void dump(String prefix, PrintWriter pw) {
-        // TODO: implement this
+        synchronized (mInitializationDelegate.getLock()) {
+            mInitializationDelegate.dump(prefix, pw);
+        }
     }
 
     /** @hide */
@@ -175,7 +186,9 @@ public class VisualQueryDetector {
 
     /** @hide */
     void registerOnDestroyListener(Consumer<AbstractDetector> onDestroyListener) {
-        mInitializationDelegate.registerOnDestroyListener(onDestroyListener);
+        synchronized (mInitializationDelegate.getLock()) {
+            mInitializationDelegate.registerOnDestroyListener(onDestroyListener);
+        }
     }
 
     /**
@@ -282,6 +295,15 @@ public class VisualQueryDetector {
         public boolean isUsingSandboxedDetectionService() {
             return true;
         }
+
+        @Override
+        public void dump(String prefix, PrintWriter pw) {
+            // No-op
+        }
+
+        private Object getLock() {
+            return mLock;
+        }
     }
 
     private static class BinderCallback
@@ -289,31 +311,43 @@ public class VisualQueryDetector {
         private final Executor mExecutor;
         private final VisualQueryDetector.Callback mCallback;
 
-        BinderCallback(Executor executor, VisualQueryDetector.Callback callback) {
+        private final Object mLock;
+
+        BinderCallback(Executor executor, VisualQueryDetector.Callback callback, Object lock) {
             this.mExecutor = executor;
             this.mCallback = callback;
+            this.mLock = lock;
         }
 
         /** Called when the detected result is valid. */
         @Override
         public void onQueryDetected(@NonNull String partialQuery) {
             Slog.v(TAG, "BinderCallback#onQueryDetected");
-            Binder.withCleanCallingIdentity(() -> mExecutor.execute(
-                    () -> mCallback.onQueryDetected(partialQuery)));
+            Binder.withCleanCallingIdentity(() -> {
+                synchronized (mLock) {
+                    mCallback.onQueryDetected(partialQuery);
+                }
+            });
         }
 
         @Override
         public void onQueryFinished() {
             Slog.v(TAG, "BinderCallback#onQueryFinished");
-            Binder.withCleanCallingIdentity(() -> mExecutor.execute(
-                    () -> mCallback.onQueryFinished()));
+            Binder.withCleanCallingIdentity(() -> {
+                synchronized (mLock) {
+                    mCallback.onQueryFinished();
+                }
+            });
         }
 
         @Override
         public void onQueryRejected() {
             Slog.v(TAG, "BinderCallback#onQueryRejected");
-            Binder.withCleanCallingIdentity(() -> mExecutor.execute(
-                    () -> mCallback.onQueryRejected()));
+            Binder.withCleanCallingIdentity(() -> {
+                synchronized (mLock) {
+                    mCallback.onQueryRejected();
+                }
+            });
         }
 
         /** Called when the detection fails due to an error. */
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
index 4720d279a676ded4849434bec2fc6152ef16e251..f9fa9b7a95241c1ddbb0b6b2a8506c9c3417ad80 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
@@ -106,96 +106,104 @@ final class VisualQueryDetectorSession extends DetectorSession {
             @Override
             public void onAttentionGained() {
                 Slog.v(TAG, "BinderCallback#onAttentionGained");
-                mEgressingData = true;
-                if (mAttentionListener == null) {
-                    return;
-                }
-                try {
-                    mAttentionListener.onAttentionGained();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error delivering attention gained event.", e);
+                synchronized (mLock) {
+                    mEgressingData = true;
+                    if (mAttentionListener == null) {
+                        return;
+                    }
                     try {
-                        callback.onVisualQueryDetectionServiceFailure(
-                                new VisualQueryDetectionServiceFailure(
-                                        ERROR_CODE_ILLEGAL_ATTENTION_STATE,
-                                        "Attention listener failed to switch to GAINED state."));
-                    } catch (RemoteException ex) {
-                        Slog.v(TAG, "Fail to call onVisualQueryDetectionServiceFailure");
+                        mAttentionListener.onAttentionGained();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error delivering attention gained event.", e);
+                        try {
+                            callback.onVisualQueryDetectionServiceFailure(
+                                    new VisualQueryDetectionServiceFailure(
+                                            ERROR_CODE_ILLEGAL_ATTENTION_STATE,
+                                            "Attention listener fails to switch to GAINED state."));
+                        } catch (RemoteException ex) {
+                            Slog.v(TAG, "Fail to call onVisualQueryDetectionServiceFailure");
+                        }
                     }
-                    return;
                 }
             }
 
             @Override
             public void onAttentionLost() {
                 Slog.v(TAG, "BinderCallback#onAttentionLost");
-                mEgressingData = false;
-                if (mAttentionListener == null) {
-                    return;
-                }
-                try {
-                    mAttentionListener.onAttentionLost();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error delivering attention lost event.", e);
+                synchronized (mLock) {
+                    mEgressingData = false;
+                    if (mAttentionListener == null) {
+                        return;
+                    }
                     try {
-                        callback.onVisualQueryDetectionServiceFailure(
-                                new VisualQueryDetectionServiceFailure(
-                                        ERROR_CODE_ILLEGAL_ATTENTION_STATE,
-                                        "Attention listener failed to switch to LOST state."));
-                    } catch (RemoteException ex) {
-                        Slog.v(TAG, "Fail to call onVisualQueryDetectionServiceFailure");
+                        mAttentionListener.onAttentionLost();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Error delivering attention lost event.", e);
+                        try {
+                            callback.onVisualQueryDetectionServiceFailure(
+                                    new VisualQueryDetectionServiceFailure(
+                                            ERROR_CODE_ILLEGAL_ATTENTION_STATE,
+                                            "Attention listener fails to switch to LOST state."));
+                        } catch (RemoteException ex) {
+                            Slog.v(TAG, "Fail to call onVisualQueryDetectionServiceFailure");
+                        }
                     }
-                    return;
                 }
             }
 
             @Override
             public void onQueryDetected(@NonNull String partialQuery) throws RemoteException {
-                Objects.requireNonNull(partialQuery);
                 Slog.v(TAG, "BinderCallback#onQueryDetected");
-                if (!mEgressingData) {
-                    Slog.v(TAG, "Query should not be egressed within the unattention state.");
-                    callback.onVisualQueryDetectionServiceFailure(
-                            new VisualQueryDetectionServiceFailure(
-                                    ERROR_CODE_ILLEGAL_STREAMING_STATE,
-                                    "Cannot stream queries without attention signals."));
-                    return;
+                synchronized (mLock) {
+                    Objects.requireNonNull(partialQuery);
+                    if (!mEgressingData) {
+                        Slog.v(TAG, "Query should not be egressed within the unattention state.");
+                        callback.onVisualQueryDetectionServiceFailure(
+                                new VisualQueryDetectionServiceFailure(
+                                        ERROR_CODE_ILLEGAL_STREAMING_STATE,
+                                        "Cannot stream queries without attention signals."));
+                        return;
+                    }
+                    mQueryStreaming = true;
+                    callback.onQueryDetected(partialQuery);
+                    Slog.i(TAG, "Egressed from visual query detection process.");
                 }
-                mQueryStreaming = true;
-                callback.onQueryDetected(partialQuery);
-                Slog.i(TAG, "Egressed from visual query detection process.");
             }
 
             @Override
             public void onQueryFinished() throws RemoteException {
                 Slog.v(TAG, "BinderCallback#onQueryFinished");
-                if (!mQueryStreaming) {
-                    Slog.v(TAG, "Query streaming state signal FINISHED is block since there is"
-                            + " no active query being streamed.");
-                    callback.onVisualQueryDetectionServiceFailure(
-                            new VisualQueryDetectionServiceFailure(
-                                    ERROR_CODE_ILLEGAL_STREAMING_STATE,
-                                    "Cannot send FINISHED signal with no query streamed."));
-                    return;
+                synchronized (mLock) {
+                    if (!mQueryStreaming) {
+                        Slog.v(TAG, "Query streaming state signal FINISHED is block since there is"
+                                + " no active query being streamed.");
+                        callback.onVisualQueryDetectionServiceFailure(
+                                new VisualQueryDetectionServiceFailure(
+                                        ERROR_CODE_ILLEGAL_STREAMING_STATE,
+                                        "Cannot send FINISHED signal with no query streamed."));
+                        return;
+                    }
+                    callback.onQueryFinished();
+                    mQueryStreaming = false;
                 }
-                callback.onQueryFinished();
-                mQueryStreaming = false;
             }
 
             @Override
             public void onQueryRejected() throws RemoteException {
                 Slog.v(TAG, "BinderCallback#onQueryRejected");
-                if (!mQueryStreaming) {
-                    Slog.v(TAG, "Query streaming state signal REJECTED is block since there is"
-                            + " no active query being streamed.");
-                    callback.onVisualQueryDetectionServiceFailure(
-                            new VisualQueryDetectionServiceFailure(
-                                    ERROR_CODE_ILLEGAL_STREAMING_STATE,
-                                    "Cannot send REJECTED signal with no query streamed."));
-                    return;
+                synchronized (mLock) {
+                    if (!mQueryStreaming) {
+                        Slog.v(TAG, "Query streaming state signal REJECTED is block since there is"
+                                + " no active query being streamed.");
+                        callback.onVisualQueryDetectionServiceFailure(
+                                new VisualQueryDetectionServiceFailure(
+                                        ERROR_CODE_ILLEGAL_STREAMING_STATE,
+                                        "Cannot send REJECTED signal with no query streamed."));
+                        return;
+                    }
+                    callback.onQueryRejected();
+                    mQueryStreaming = false;
                 }
-                callback.onQueryRejected();
-                mQueryStreaming = false;
             }
         };
         return mRemoteDetectionService.run(