Loading core/java/android/service/voice/AbstractHotwordDetector.java→core/java/android/service/voice/AbstractDetector.java +14 −6 Original line number Diff line number Diff line Loading @@ -41,9 +41,17 @@ import com.android.internal.app.IVoiceInteractionManagerService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; /** Base implementation of {@link HotwordDetector}. */ abstract class AbstractHotwordDetector implements HotwordDetector { private static final String TAG = AbstractHotwordDetector.class.getSimpleName(); /** Base implementation of {@link HotwordDetector}. * * This class provides methods to manage the detector lifecycle for both * {@link HotwordDetectionService} and {@link VisualQueryDetectionService}. We keep the name of the * interface {@link HotwordDetector} since {@link VisualQueryDetectionService} can be logically * treated as a visual activation hotword detection and also because of the existing public * interface. To avoid confusion on the naming between the trusted hotword framework and the actual * isolated {@link HotwordDetectionService}, the hotword from the names is removed. */ abstract class AbstractDetector implements HotwordDetector { private static final String TAG = AbstractDetector.class.getSimpleName(); private static final boolean DEBUG = false; protected final Object mLock = new Object(); Loading @@ -51,14 +59,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { private final IVoiceInteractionManagerService mManagerService; private final Handler mHandler; private final HotwordDetector.Callback mCallback; private Consumer<AbstractHotwordDetector> mOnDestroyListener; private Consumer<AbstractDetector> mOnDestroyListener; private final AtomicBoolean mIsDetectorActive; /** * A token which is used by voice interaction system service to identify different detectors. */ private final IBinder mToken = new Binder(); AbstractHotwordDetector( AbstractDetector( IVoiceInteractionManagerService managerService, HotwordDetector.Callback callback) { mManagerService = managerService; Loading Loading @@ -139,7 +147,7 @@ abstract class AbstractHotwordDetector implements HotwordDetector { } } void registerOnDestroyListener(Consumer<AbstractHotwordDetector> onDestroyListener) { void registerOnDestroyListener(Consumer<AbstractDetector> onDestroyListener) { synchronized (mLock) { if (mOnDestroyListener != null) { throw new IllegalStateException("only one destroy listener can be registered"); Loading core/java/android/service/voice/AlwaysOnHotwordDetector.java +1 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ import java.util.Set; * mark and track it as such. */ @SystemApi public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { public class AlwaysOnHotwordDetector extends AbstractDetector { //---- States of Keyphrase availability. Return codes for onAvailabilityChanged() ----// /** * Indicates that this hotword detector is no longer valid for any recognition Loading core/java/android/service/voice/SoftwareHotwordDetector.java +1 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ import java.io.PrintWriter; * * @hide **/ class SoftwareHotwordDetector extends AbstractHotwordDetector { class SoftwareHotwordDetector extends AbstractDetector { private static final String TAG = SoftwareHotwordDetector.class.getSimpleName(); private static final boolean DEBUG = false; Loading core/java/android/service/voice/VoiceInteractionService.java +14 −14 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class VoiceInteractionService extends Service { private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; private final Set<HotwordDetector> mActiveHotwordDetectors = new ArraySet<>(); private final Set<HotwordDetector> mActiveDetectors = new ArraySet<>(); /** * Called when a user has activated an affordance to launch voice assist from the Keyguard. Loading Loading @@ -319,7 +319,7 @@ public class VoiceInteractionService extends Service { private void onSoundModelsChangedInternal() { synchronized (this) { // TODO: Stop recognition if a sound model that was being recognized gets deleted. mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { if (detector instanceof AlwaysOnHotwordDetector) { ((AlwaysOnHotwordDetector) detector).onSoundModelsChanged(); } Loading Loading @@ -429,7 +429,7 @@ public class VoiceInteractionService extends Service { // Allow only one concurrent recognition via the APIs. safelyShutdownAllHotwordDetectors(); } else { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (detector.isUsingSandboxedDetectionService() != supportHotwordDetectionService) { throw new IllegalStateException( Loading @@ -447,13 +447,13 @@ public class VoiceInteractionService extends Service { callback, mKeyphraseEnrollmentInfo, mSystemService, getApplicationContext().getApplicationInfo().targetSdkVersion, supportHotwordDetectionService); mActiveHotwordDetectors.add(dspDetector); mActiveDetectors.add(dspDetector); try { dspDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed); dspDetector.initialize(options, sharedMemory); } catch (Exception e) { mActiveHotwordDetectors.remove(dspDetector); mActiveDetectors.remove(dspDetector); dspDetector.destroy(); throw e; } Loading Loading @@ -512,7 +512,7 @@ public class VoiceInteractionService extends Service { // Allow only one concurrent recognition via the APIs. safelyShutdownAllHotwordDetectors(); } else { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (!detector.isUsingSandboxedDetectionService()) { throw new IllegalStateException( "It disallows to create trusted and non-trusted detectors " Loading @@ -528,14 +528,14 @@ public class VoiceInteractionService extends Service { SoftwareHotwordDetector softwareHotwordDetector = new SoftwareHotwordDetector( mSystemService, null, callback); mActiveHotwordDetectors.add(softwareHotwordDetector); mActiveDetectors.add(softwareHotwordDetector); try { softwareHotwordDetector.registerOnDestroyListener( this::onHotwordDetectorDestroyed); softwareHotwordDetector.initialize(options, sharedMemory); } catch (Exception e) { mActiveHotwordDetectors.remove(softwareHotwordDetector); mActiveDetectors.remove(softwareHotwordDetector); softwareHotwordDetector.destroy(); throw e; } Loading Loading @@ -586,7 +586,7 @@ public class VoiceInteractionService extends Service { private void safelyShutdownAllHotwordDetectors() { synchronized (mLock) { mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { try { detector.destroy(); } catch (Exception ex) { Loading @@ -598,13 +598,13 @@ public class VoiceInteractionService extends Service { private void onHotwordDetectorDestroyed(@NonNull HotwordDetector detector) { synchronized (mLock) { mActiveHotwordDetectors.remove(detector); mActiveDetectors.remove(detector); shutdownHotwordDetectionServiceIfRequiredLocked(); } } private void shutdownHotwordDetectionServiceIfRequiredLocked() { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (detector.isUsingSandboxedDetectionService()) { return; } Loading Loading @@ -638,11 +638,11 @@ public class VoiceInteractionService extends Service { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("VOICE INTERACTION"); synchronized (mLock) { pw.println(" HotwordDetector(s)"); if (mActiveHotwordDetectors.size() == 0) { pw.println(" Sandboxed Detector(s)"); if (mActiveDetectors.size() == 0) { pw.println(" NULL"); } else { mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { detector.dump(" ", pw); pw.println(); }); Loading Loading
core/java/android/service/voice/AbstractHotwordDetector.java→core/java/android/service/voice/AbstractDetector.java +14 −6 Original line number Diff line number Diff line Loading @@ -41,9 +41,17 @@ import com.android.internal.app.IVoiceInteractionManagerService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; /** Base implementation of {@link HotwordDetector}. */ abstract class AbstractHotwordDetector implements HotwordDetector { private static final String TAG = AbstractHotwordDetector.class.getSimpleName(); /** Base implementation of {@link HotwordDetector}. * * This class provides methods to manage the detector lifecycle for both * {@link HotwordDetectionService} and {@link VisualQueryDetectionService}. We keep the name of the * interface {@link HotwordDetector} since {@link VisualQueryDetectionService} can be logically * treated as a visual activation hotword detection and also because of the existing public * interface. To avoid confusion on the naming between the trusted hotword framework and the actual * isolated {@link HotwordDetectionService}, the hotword from the names is removed. */ abstract class AbstractDetector implements HotwordDetector { private static final String TAG = AbstractDetector.class.getSimpleName(); private static final boolean DEBUG = false; protected final Object mLock = new Object(); Loading @@ -51,14 +59,14 @@ abstract class AbstractHotwordDetector implements HotwordDetector { private final IVoiceInteractionManagerService mManagerService; private final Handler mHandler; private final HotwordDetector.Callback mCallback; private Consumer<AbstractHotwordDetector> mOnDestroyListener; private Consumer<AbstractDetector> mOnDestroyListener; private final AtomicBoolean mIsDetectorActive; /** * A token which is used by voice interaction system service to identify different detectors. */ private final IBinder mToken = new Binder(); AbstractHotwordDetector( AbstractDetector( IVoiceInteractionManagerService managerService, HotwordDetector.Callback callback) { mManagerService = managerService; Loading Loading @@ -139,7 +147,7 @@ abstract class AbstractHotwordDetector implements HotwordDetector { } } void registerOnDestroyListener(Consumer<AbstractHotwordDetector> onDestroyListener) { void registerOnDestroyListener(Consumer<AbstractDetector> onDestroyListener) { synchronized (mLock) { if (mOnDestroyListener != null) { throw new IllegalStateException("only one destroy listener can be registered"); Loading
core/java/android/service/voice/AlwaysOnHotwordDetector.java +1 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ import java.util.Set; * mark and track it as such. */ @SystemApi public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { public class AlwaysOnHotwordDetector extends AbstractDetector { //---- States of Keyphrase availability. Return codes for onAvailabilityChanged() ----// /** * Indicates that this hotword detector is no longer valid for any recognition Loading
core/java/android/service/voice/SoftwareHotwordDetector.java +1 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ import java.io.PrintWriter; * * @hide **/ class SoftwareHotwordDetector extends AbstractHotwordDetector { class SoftwareHotwordDetector extends AbstractDetector { private static final String TAG = SoftwareHotwordDetector.class.getSimpleName(); private static final boolean DEBUG = false; Loading
core/java/android/service/voice/VoiceInteractionService.java +14 −14 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class VoiceInteractionService extends Service { private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; private final Set<HotwordDetector> mActiveHotwordDetectors = new ArraySet<>(); private final Set<HotwordDetector> mActiveDetectors = new ArraySet<>(); /** * Called when a user has activated an affordance to launch voice assist from the Keyguard. Loading Loading @@ -319,7 +319,7 @@ public class VoiceInteractionService extends Service { private void onSoundModelsChangedInternal() { synchronized (this) { // TODO: Stop recognition if a sound model that was being recognized gets deleted. mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { if (detector instanceof AlwaysOnHotwordDetector) { ((AlwaysOnHotwordDetector) detector).onSoundModelsChanged(); } Loading Loading @@ -429,7 +429,7 @@ public class VoiceInteractionService extends Service { // Allow only one concurrent recognition via the APIs. safelyShutdownAllHotwordDetectors(); } else { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (detector.isUsingSandboxedDetectionService() != supportHotwordDetectionService) { throw new IllegalStateException( Loading @@ -447,13 +447,13 @@ public class VoiceInteractionService extends Service { callback, mKeyphraseEnrollmentInfo, mSystemService, getApplicationContext().getApplicationInfo().targetSdkVersion, supportHotwordDetectionService); mActiveHotwordDetectors.add(dspDetector); mActiveDetectors.add(dspDetector); try { dspDetector.registerOnDestroyListener(this::onHotwordDetectorDestroyed); dspDetector.initialize(options, sharedMemory); } catch (Exception e) { mActiveHotwordDetectors.remove(dspDetector); mActiveDetectors.remove(dspDetector); dspDetector.destroy(); throw e; } Loading Loading @@ -512,7 +512,7 @@ public class VoiceInteractionService extends Service { // Allow only one concurrent recognition via the APIs. safelyShutdownAllHotwordDetectors(); } else { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (!detector.isUsingSandboxedDetectionService()) { throw new IllegalStateException( "It disallows to create trusted and non-trusted detectors " Loading @@ -528,14 +528,14 @@ public class VoiceInteractionService extends Service { SoftwareHotwordDetector softwareHotwordDetector = new SoftwareHotwordDetector( mSystemService, null, callback); mActiveHotwordDetectors.add(softwareHotwordDetector); mActiveDetectors.add(softwareHotwordDetector); try { softwareHotwordDetector.registerOnDestroyListener( this::onHotwordDetectorDestroyed); softwareHotwordDetector.initialize(options, sharedMemory); } catch (Exception e) { mActiveHotwordDetectors.remove(softwareHotwordDetector); mActiveDetectors.remove(softwareHotwordDetector); softwareHotwordDetector.destroy(); throw e; } Loading Loading @@ -586,7 +586,7 @@ public class VoiceInteractionService extends Service { private void safelyShutdownAllHotwordDetectors() { synchronized (mLock) { mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { try { detector.destroy(); } catch (Exception ex) { Loading @@ -598,13 +598,13 @@ public class VoiceInteractionService extends Service { private void onHotwordDetectorDestroyed(@NonNull HotwordDetector detector) { synchronized (mLock) { mActiveHotwordDetectors.remove(detector); mActiveDetectors.remove(detector); shutdownHotwordDetectionServiceIfRequiredLocked(); } } private void shutdownHotwordDetectionServiceIfRequiredLocked() { for (HotwordDetector detector : mActiveHotwordDetectors) { for (HotwordDetector detector : mActiveDetectors) { if (detector.isUsingSandboxedDetectionService()) { return; } Loading Loading @@ -638,11 +638,11 @@ public class VoiceInteractionService extends Service { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("VOICE INTERACTION"); synchronized (mLock) { pw.println(" HotwordDetector(s)"); if (mActiveHotwordDetectors.size() == 0) { pw.println(" Sandboxed Detector(s)"); if (mActiveDetectors.size() == 0) { pw.println(" NULL"); } else { mActiveHotwordDetectors.forEach(detector -> { mActiveDetectors.forEach(detector -> { detector.dump(" ", pw); pw.println(); }); Loading