diff options
4 files changed, 117 insertions, 14 deletions
diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java index f3d4809a19a8..0384454bb69c 100644 --- a/core/java/android/service/voice/HotwordDetectionService.java +++ b/core/java/android/service/voice/HotwordDetectionService.java @@ -194,6 +194,12 @@ public abstract class HotwordDetectionService extends Service } @Override + public void detectWithVisualSignals( + IDetectorSessionVisualQueryDetectionCallback callback) { + throw new UnsupportedOperationException("Not supported by HotwordDetectionService"); + } + + @Override public void updateAudioFlinger(IBinder audioFlinger) { AudioSystem.setAudioFlingerBinder(audioFlinger); } @@ -382,7 +388,7 @@ public abstract class HotwordDetectionService extends Service */ @SystemApi public static final class Callback { - // TODO: need to make sure we don't store remote references, but not a high priority. + // TODO: consider making the constructor a test api for testing purpose private final IDspHotwordDetectionCallback mRemoteCallback; private Callback(IDspHotwordDetectionCallback remoteCallback) { diff --git a/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl b/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl new file mode 100644 index 000000000000..22172ed36f2f --- /dev/null +++ b/core/java/android/service/voice/IDetectorSessionVisualQueryDetectionCallback.aidl @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.voice; + +/** + * Callback for returning the detected result from the {@link VisualQueryDetectionService}. + * + * The {@link VisualQueryDetectorSession} will overrides this interface to reach query egression + * control within each callback methods. + * + * @hide + */ +oneway interface IDetectorSessionVisualQueryDetectionCallback { + + /** + * Called when the user attention is gained and intent to show the assistant icon in SysUI. + */ + void onAttentionGained(); + + /** + * Called when the user attention is lost and intent to hide the assistant icon in SysUI. + */ + void onAttentionLost(); + + /** + * Called when the detected query is streamed. + */ + void onQueryDetected(in String partialQuery); + + /** + * Called when the detected result is valid. + */ + void onQueryFinished(); + + /** + * Called when the detected result is invalid. + */ + void onQueryRejected(); +} diff --git a/core/java/android/service/voice/ISandboxedDetectionService.aidl b/core/java/android/service/voice/ISandboxedDetectionService.aidl index 5537fd1df26e..098536dfeb64 100644 --- a/core/java/android/service/voice/ISandboxedDetectionService.aidl +++ b/core/java/android/service/voice/ISandboxedDetectionService.aidl @@ -24,6 +24,7 @@ import android.os.IRemoteCallback; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.SharedMemory; +import android.service.voice.IDetectorSessionVisualQueryDetectionCallback; import android.service.voice.IDspHotwordDetectionCallback; import android.view.contentcapture.IContentCaptureManager; import android.speech.IRecognitionServiceManager; @@ -47,6 +48,8 @@ oneway interface ISandboxedDetectionService { in PersistableBundle options, in IDspHotwordDetectionCallback callback); + void detectWithVisualSignals(in IDetectorSessionVisualQueryDetectionCallback callback); + void updateState( in PersistableBundle options, in SharedMemory sharedMemory, diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java index 792690160159..fde0afbefa6f 100644 --- a/core/java/android/service/voice/VisualQueryDetectionService.java +++ b/core/java/android/service/voice/VisualQueryDetectionService.java @@ -36,6 +36,7 @@ import android.speech.IRecognitionServiceManager; import android.util.Log; import android.view.contentcapture.IContentCaptureManager; +import java.util.Objects; import java.util.function.IntConsumer; /** @@ -80,6 +81,19 @@ public abstract class VisualQueryDetectionService extends Service private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() { @Override + public void detectWithVisualSignals( + IDetectorSessionVisualQueryDetectionCallback callback) { + Log.v(TAG, "#detectWithVisualSignals"); + VisualQueryDetectionService.this.onStartDetection(new Callback(callback)); + } + + @Override + public void stopDetection() { + Log.v(TAG, "#stopDetection"); + VisualQueryDetectionService.this.onStopDetection(); + } + + @Override public void updateState(PersistableBundle options, SharedMemory sharedMemory, IRemoteCallback callback) throws RemoteException { Log.v(TAG, "#updateState" + (callback != null ? " with callback" : "")); @@ -128,11 +142,6 @@ public abstract class VisualQueryDetectionService extends Service public void updateRecognitionServiceManager(IRecognitionServiceManager manager) { Log.v(TAG, "Ignore #updateRecognitionServiceManager"); } - - @Override - public void stopDetection() { - throw new UnsupportedOperationException("Not supported by VisualQueryDetectionService"); - } }; /** @@ -216,18 +225,37 @@ public abstract class VisualQueryDetectionService extends Service */ public static final class Callback { + // TODO: consider making the constructor a test api for testing purpose + public Callback() { + mRemoteCallback = null; + } + + private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback; + + private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) { + mRemoteCallback = remoteCallback; + } + /** * Informs attention listener that the user attention is gained. */ public void onAttentionGained() { - //TODO(b/265345361): call internal callbacks to send signal to the interactor + try { + mRemoteCallback.onAttentionGained(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** * Informs attention listener that the user attention is lost. */ public void onAttentionLost() { - //TODO(b/265345361): call internal callbacks to send signal to the interactor + try { + mRemoteCallback.onAttentionLost(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -241,8 +269,13 @@ public abstract class VisualQueryDetectionService extends Service * @throws IllegalStateException if method called without attention gained. */ public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException { - //TODO(b/265345361): call internal callbacks to send signal to the interactor - //TODO(b/265381651): convert callback exceptions and throw IllegalStateException. + Objects.requireNonNull(partialQuery); + try { + mRemoteCallback.onQueryDetected(partialQuery); + } catch (RemoteException e) { + throw new IllegalStateException("#onQueryDetected must be only be triggered after " + + "calling #onAttentionGained to be in the attention gained state."); + } } /** @@ -254,8 +287,12 @@ public abstract class VisualQueryDetectionService extends Service * @throws IllegalStateException if method called without query streamed. */ public void onQueryRejected() throws IllegalStateException { - //TODO(b/265345361): call internal callbacks to send signal to the interactor - //TODO(b/265381651): convert callback exceptions and throw IllegalStateException. + try { + mRemoteCallback.onQueryRejected(); + } catch (RemoteException e) { + throw new IllegalStateException("#onQueryRejected must be only be triggered after " + + "calling #onQueryDetected to be in the query streaming state."); + } } /** @@ -267,8 +304,12 @@ public abstract class VisualQueryDetectionService extends Service * @throws IllegalStateException if method called without query streamed. */ public void onQueryFinished() throws IllegalStateException { - //TODO(b/265345361): call internal callbacks to send signal to the interactor - //TODO(b/265381651): convert callback exceptions and throw IllegalStateException. + try { + mRemoteCallback.onQueryFinished(); + } catch (RemoteException e) { + throw new IllegalStateException("#onQueryFinished must be only be triggered after " + + "calling #onQueryDetected to be in the query streaming state."); + } } } |