diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java index b7d97057a08b..adc54f5b5a8c 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(); + synchronized (mInitializationDelegate.getLock()) { + // 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(); + 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(); + synchronized (mInitializationDelegate.getLock()) { + // check if the detector is active with the initialization delegate + mInitializationDelegate.stopRecognition(); - try { - mManagerService.stopPerceiving(); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); + 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 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 4720d279a676..f9fa9b7a9524 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); - 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"); + synchronized (mLock) { + mEgressingData = true; + if (mAttentionListener == null) { + return; + } + try { + 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); - 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"); + synchronized (mLock) { + mEgressingData = false; + if (mAttentionListener == null) { + return; + } + try { + 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(