From 27871db61e61e6b034bbef9bafb0323f7828bb42 Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Wed, 11 Jan 2023 03:07:01 +0000 Subject: [PATCH] Create SampleVisualQueryDetectionService Create SampleVisualQueryDetectionService for the Sample VoiceInteractor devlopment app. The service currently only has the no functionalities. Only the creation and initialization is integrated. Test: Manual Bug: 261517532 Change-Id: Ia5354b24e21854fb5e53857f9a6db7c8b80d3f5a --- .../AndroidManifest.xml | 12 +++- samples/VoiceInteractionService/README.md | 2 + .../res/xml/voice_interaction.xml | 3 +- .../android/voiceinteractor/MainActivity.java | 4 +- .../SampleVisualQueryDetectionService.java | 40 ++++++++++++ .../SampleVoiceInteractionService.java | 61 +++++++++++++++---- 6 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVisualQueryDetectionService.java diff --git a/samples/VoiceInteractionService/AndroidManifest.xml b/samples/VoiceInteractionService/AndroidManifest.xml index 56c959081..bc8ac2779 100755 --- a/samples/VoiceInteractionService/AndroidManifest.xml +++ b/samples/VoiceInteractionService/AndroidManifest.xml @@ -3,7 +3,8 @@ - + @@ -12,7 +13,8 @@ + android:permission="android.permission.BIND_VOICE_INTERACTION" + android:exported="true"> @@ -26,6 +28,12 @@ android:isolatedProcess="true" android:exported="true"> + + diff --git a/samples/VoiceInteractionService/README.md b/samples/VoiceInteractionService/README.md index 6ac92d17a..92a12cfed 100644 --- a/samples/VoiceInteractionService/README.md +++ b/samples/VoiceInteractionService/README.md @@ -1,4 +1,6 @@ setup: + +(If a log error "VisualQueryDetector is only available if multiple detectors are allowed" , set target_sdk_version: "10000" in Android.bp for now.) 1. Set the KEYPHRASE constant in SampleVoiceInteractionService.java to something the device's default assistant supports. 2. m -j SampleVoiceInteractor diff --git a/samples/VoiceInteractionService/res/xml/voice_interaction.xml b/samples/VoiceInteractionService/res/xml/voice_interaction.xml index 8445652a2..2c4a5d9a0 100644 --- a/samples/VoiceInteractionService/res/xml/voice_interaction.xml +++ b/samples/VoiceInteractionService/res/xml/voice_interaction.xml @@ -17,7 +17,8 @@ + android:supportsLocalInteraction="true" /> \ No newline at end of file diff --git a/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/MainActivity.java b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/MainActivity.java index deda4f42f..7272531ef 100644 --- a/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/MainActivity.java +++ b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/MainActivity.java @@ -54,7 +54,7 @@ public class MainActivity extends Activity { return; } try { - mService.mDetector.startRecognition(); + mService.mHotwordDetector.startRecognition(); } catch (HotwordDetector.IllegalDetectorStateException e) { e.printStackTrace(); } @@ -66,7 +66,7 @@ public class MainActivity extends Activity { Log.e(TAG, "No service"); return; } - mService.mCallback.onDetected(mService.mLastPayload, true); + mService.mHotwordDetectorCallback.onDetected(mService.mLastPayload, true); }); } diff --git a/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVisualQueryDetectionService.java b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVisualQueryDetectionService.java new file mode 100644 index 000000000..bcd0b4639 --- /dev/null +++ b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVisualQueryDetectionService.java @@ -0,0 +1,40 @@ +/* + * 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 com.example.android.voiceinteractor; + +import android.os.PersistableBundle; +import android.os.SharedMemory; +import android.service.voice.VisualQueryDetectionService; +import android.util.Log; + +import androidx.annotation.Nullable; + +import java.util.function.IntConsumer; + +public class SampleVisualQueryDetectionService extends VisualQueryDetectionService { + static final String TAG = "SVisualQueryDetectionSrvc"; + + @Override + public void onUpdateState(@Nullable PersistableBundle options, + @Nullable SharedMemory sharedMemory, long callbackTimeoutMillis, + @Nullable IntConsumer statusCallback) { + Log.i(TAG, "onUpdateState"); + if (statusCallback != null) { + statusCallback.accept(0); + } + } +} \ No newline at end of file diff --git a/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVoiceInteractionService.java b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVoiceInteractionService.java index 73f91676d..7e19cb86e 100644 --- a/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVoiceInteractionService.java +++ b/samples/VoiceInteractionService/src/com/example/android/voiceinteractor/SampleVoiceInteractionService.java @@ -35,6 +35,7 @@ import android.service.voice.AlwaysOnHotwordDetector.EventPayload; import android.service.voice.HotwordDetector; import android.service.voice.HotwordDetector.IllegalDetectorStateException; import android.service.voice.HotwordRejectedResult; +import android.service.voice.VisualQueryDetector; import android.service.voice.VoiceInteractionService; import android.util.Log; @@ -42,6 +43,7 @@ import androidx.annotation.NonNull; import java.time.Duration; import java.util.Locale; +import java.util.concurrent.Executors; public class SampleVoiceInteractionService extends VoiceInteractionService { public static final String DSP_MODEL_KEYPHRASE = "X Google"; @@ -56,8 +58,10 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { private final IBinder binder = new LocalBinder(); - HotwordDetector mDetector; - Callback mCallback; + HotwordDetector mHotwordDetector; + VisualQueryDetector mVisualQueryDetector; + Callback mHotwordDetectorCallback; + VisualQueryDetector.Callback mVisualQueryDetectorCallback; Bundle mData = new Bundle(); AudioFormat mAudioFormat; EventPayload mLastPayload; @@ -94,9 +98,12 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { public void onReady() { super.onReady(); Log.i(TAG, "onReady"); - mCallback = new Callback(); - mDetector = createAlwaysOnHotwordDetector(DSP_MODEL_KEYPHRASE, DSP_MODEL_LOCALE, null, null, - mCallback); + mHotwordDetectorCallback = new Callback(); + mVisualQueryDetectorCallback = new VisualQueryDetectorCallback(); + mHotwordDetector = createAlwaysOnHotwordDetector(DSP_MODEL_KEYPHRASE, DSP_MODEL_LOCALE, null, null, + mHotwordDetectorCallback); + mVisualQueryDetector = createVisualQueryDetector(null, null, + Executors.newSingleThreadExecutor(), mVisualQueryDetectorCallback); } @Override @@ -112,6 +119,38 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { } } + static class VisualQueryDetectorCallback implements VisualQueryDetector.Callback { + @Override + public void onQueryDetected(@NonNull String partialQuery) { + Log.i(TAG, "VQD partial query detected: "+ partialQuery); + } + + @Override + public void onQueryRejected() { + Log.i(TAG, "VQD query rejected"); + } + + @Override + public void onQueryFinished() { + Log.i(TAG, "VQD query finished"); + } + + @Override + public void onVisualQueryDetectionServiceInitialized(int status) { + Log.i(TAG, "VQD init: "+ status); + } + + @Override + public void onVisualQueryDetectionServiceRestarted() { + Log.i(TAG, "VQD restarted"); + } + + @Override + public void onError() { + Log.i(TAG, "VQD error"); + } + }; + class Callback extends AlwaysOnHotwordDetector.Callback { private boolean mAvailable = false; @@ -131,7 +170,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { if (status == STATE_KEYPHRASE_UNENROLLED) { Intent enrollIntent = null; try { - enrollIntent = ((AlwaysOnHotwordDetector) mDetector).createEnrollIntent(); + enrollIntent = ((AlwaysOnHotwordDetector) mHotwordDetector).createEnrollIntent(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); } @@ -152,7 +191,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { @Override public void onRejected(@NonNull HotwordRejectedResult result) { try { - mDetector.startRecognition(); + mHotwordDetector.startRecognition(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); } @@ -198,7 +237,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { record.getState()); Log.e(TAG, "Failed to init first AudioRecord."); try { - mDetector.startRecognition(); + mHotwordDetector.startRecognition(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); } @@ -231,7 +270,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { mLastPayload = eventPayload; try { - mDetector.startRecognition(); + mHotwordDetector.startRecognition(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); } @@ -241,7 +280,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { public void onError() { Log.i(TAG, "onError"); try { - mDetector.startRecognition(); + mHotwordDetector.startRecognition(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); } @@ -263,7 +302,7 @@ public class SampleVoiceInteractionService extends VoiceInteractionService { + ". mAvailable=" + mAvailable); if (mAvailable) { try { - mDetector.startRecognition(); + mHotwordDetector.startRecognition(); } catch (IllegalDetectorStateException e) { e.printStackTrace(); }