diff options
4 files changed, 103 insertions, 88 deletions
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index b6ef5947bcaf..d43f9f766b2c 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -914,4 +914,7 @@ "$packageName" part that will be replaced by the code with the package name of the target app. --> <string name="config_appStoreAppLinkTemplate" translatable="false"></string> + + <!-- Flag controlling whether visual query attention detection has been enabled. --> + <bool name="config_enableVisualQueryAttentionDetection">false</bool> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 2b83e6b05bbc..590056f2f8c2 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -23,6 +23,8 @@ import android.service.voice.VoiceInteractionSession; import android.util.Log; import com.android.internal.app.AssistUtils; +import com.android.internal.app.IVisualQueryDetectionAttentionListener; +import com.android.internal.app.IVisualQueryRecognitionStatusListener; import com.android.internal.app.IVoiceInteractionSessionListener; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -39,10 +41,13 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.settings.SecureSettings; -import javax.inject.Inject; - import dagger.Lazy; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + /** * Class to manage everything related to assist in SystemUI. */ @@ -78,6 +83,18 @@ public class AssistManager { void hide(); } + /** + * An interface for a listener that receives notification that visual query attention has + * either been gained or lost. + */ + public interface VisualQueryAttentionListener { + /** Called when visual query attention has been gained. */ + void onAttentionGained(); + + /** Called when visual query attention has been lost. */ + void onAttentionLost(); + } + private static final String TAG = "AssistManager"; // Note that VERBOSE logging may leak PII (e.g. transcription contents). @@ -127,6 +144,23 @@ public class AssistManager { private final SecureSettings mSecureSettings; private final DeviceProvisionedController mDeviceProvisionedController; + + private final List<VisualQueryAttentionListener> mVisualQueryAttentionListeners = + new ArrayList<>(); + + private final IVisualQueryDetectionAttentionListener mVisualQueryDetectionAttentionListener = + new IVisualQueryDetectionAttentionListener.Stub() { + @Override + public void onAttentionGained() { + mVisualQueryAttentionListeners.forEach(VisualQueryAttentionListener::onAttentionGained); + } + + @Override + public void onAttentionLost() { + mVisualQueryAttentionListeners.forEach(VisualQueryAttentionListener::onAttentionLost); + } + }; + private final CommandQueue mCommandQueue; protected final AssistUtils mAssistUtils; @@ -157,6 +191,7 @@ public class AssistManager { mSecureSettings = secureSettings; registerVoiceInteractionSessionListener(); + registerVisualQueryRecognitionStatusListener(); mUiController = defaultUiController; @@ -266,6 +301,24 @@ public class AssistManager { mAssistUtils.hideCurrentSession(); } + /** + * Add the given {@link VisualQueryAttentionListener} to the list of listeners awaiting + * notification of gaining/losing visual query attention. + */ + public void addVisualQueryAttentionListener(VisualQueryAttentionListener listener) { + if (!mVisualQueryAttentionListeners.contains(listener)) { + mVisualQueryAttentionListeners.add(listener); + } + } + + /** + * Remove the given {@link VisualQueryAttentionListener} from the list of listeners awaiting + * notification of gaining/losing visual query attention. + */ + public void removeVisualQueryAttentionListener(VisualQueryAttentionListener listener) { + mVisualQueryAttentionListeners.remove(listener); + } + private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent, boolean isService) { if (isService) { @@ -326,6 +379,27 @@ public class AssistManager { null, null); } + private void registerVisualQueryRecognitionStatusListener() { + if (!mContext.getResources() + .getBoolean(R.bool.config_enableVisualQueryAttentionDetection)) { + return; + } + + mAssistUtils.subscribeVisualQueryRecognitionStatus( + new IVisualQueryRecognitionStatusListener.Stub() { + @Override + public void onStartPerceiving() { + mAssistUtils.enableVisualQueryDetection( + mVisualQueryDetectionAttentionListener); + } + + @Override + public void onStopPerceiving() { + mAssistUtils.disableVisualQueryDetection(); + } + }); + } + public void launchVoiceAssistFromKeyguard() { mAssistUtils.launchVoiceAssistFromKeyguard(); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java index c889ac214cda..4dd97d557b30 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java @@ -16,10 +16,9 @@ package com.android.systemui.dreams.conditions; -import com.android.internal.app.AssistUtils; -import com.android.internal.app.IVisualQueryDetectionAttentionListener; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.assist.AssistManager.VisualQueryAttentionListener; import com.android.systemui.dagger.qualifiers.Application; -import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.shared.condition.Condition; import javax.inject.Inject; @@ -30,12 +29,10 @@ import kotlinx.coroutines.CoroutineScope; * {@link AssistantAttentionCondition} provides a signal when assistant has the user's attention. */ public class AssistantAttentionCondition extends Condition { - private final DreamOverlayStateController mDreamOverlayStateController; - private final AssistUtils mAssistUtils; - private boolean mEnabled; + private final AssistManager mAssistManager; - private final IVisualQueryDetectionAttentionListener mVisualQueryDetectionAttentionListener = - new IVisualQueryDetectionAttentionListener.Stub() { + private final VisualQueryAttentionListener mVisualQueryAttentionListener = + new VisualQueryAttentionListener() { @Override public void onAttentionGained() { updateCondition(true); @@ -47,59 +44,26 @@ public class AssistantAttentionCondition extends Condition { } }; - private final DreamOverlayStateController.Callback mCallback = - new DreamOverlayStateController.Callback() { - @Override - public void onStateChanged() { - if (mDreamOverlayStateController.isDreamOverlayStatusBarVisible()) { - enableVisualQueryDetection(); - } else { - disableVisualQueryDetection(); - } - } - }; - @Inject public AssistantAttentionCondition( @Application CoroutineScope scope, - DreamOverlayStateController dreamOverlayStateController, - AssistUtils assistUtils) { + AssistManager assistManager) { super(scope); - mDreamOverlayStateController = dreamOverlayStateController; - mAssistUtils = assistUtils; + mAssistManager = assistManager; } @Override protected void start() { - mDreamOverlayStateController.addCallback(mCallback); + mAssistManager.addVisualQueryAttentionListener(mVisualQueryAttentionListener); } @Override protected void stop() { - disableVisualQueryDetection(); - mDreamOverlayStateController.removeCallback(mCallback); + mAssistManager.removeVisualQueryAttentionListener(mVisualQueryAttentionListener); } @Override protected int getStartStrategy() { return START_EAGERLY; } - - private void enableVisualQueryDetection() { - if (mEnabled) { - return; - } - mEnabled = true; - mAssistUtils.enableVisualQueryDetection(mVisualQueryDetectionAttentionListener); - } - - private void disableVisualQueryDetection() { - if (!mEnabled) { - return; - } - mEnabled = false; - mAssistUtils.disableVisualQueryDetection(); - // Make sure the condition is set to false as well. - updateCondition(false); - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java index 07cb5d88a515..6a178895839b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java @@ -22,17 +22,14 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import android.os.RemoteException; import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; -import com.android.internal.app.AssistUtils; -import com.android.internal.app.IVisualQueryDetectionAttentionListener; import com.android.systemui.SysuiTestCase; -import com.android.systemui.dreams.DreamOverlayStateController; +import com.android.systemui.assist.AssistManager; +import com.android.systemui.assist.AssistManager.VisualQueryAttentionListener; import com.android.systemui.shared.condition.Condition; import org.junit.Before; @@ -50,9 +47,7 @@ public class AssistantAttentionConditionTest extends SysuiTestCase { @Mock Condition.Callback mCallback; @Mock - AssistUtils mAssistUtils; - @Mock - DreamOverlayStateController mDreamOverlayStateController; + AssistManager mAssistManager; @Mock CoroutineScope mScope; @@ -62,55 +57,34 @@ public class AssistantAttentionConditionTest extends SysuiTestCase { public void setup() { MockitoAnnotations.initMocks(this); - mAssistantAttentionCondition = - new AssistantAttentionCondition(mScope, mDreamOverlayStateController, mAssistUtils); + mAssistantAttentionCondition = new AssistantAttentionCondition(mScope, mAssistManager); // Adding a callback also starts the condition. mAssistantAttentionCondition.addCallback(mCallback); } @Test public void testEnableVisualQueryDetection() { - final ArgumentCaptor<DreamOverlayStateController.Callback> argumentCaptor = - ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); - verify(mDreamOverlayStateController).addCallback(argumentCaptor.capture()); - - when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true); - argumentCaptor.getValue().onStateChanged(); - - verify(mAssistUtils).enableVisualQueryDetection(any()); + verify(mAssistManager).addVisualQueryAttentionListener( + any(VisualQueryAttentionListener.class)); } @Test public void testDisableVisualQueryDetection() { - final ArgumentCaptor<DreamOverlayStateController.Callback> argumentCaptor = - ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); - verify(mDreamOverlayStateController).addCallback(argumentCaptor.capture()); - - when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true); - argumentCaptor.getValue().onStateChanged(); - when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(false); - argumentCaptor.getValue().onStateChanged(); - - verify(mAssistUtils).disableVisualQueryDetection(); + mAssistantAttentionCondition.stop(); + verify(mAssistManager).removeVisualQueryAttentionListener( + any(VisualQueryAttentionListener.class)); } @Test - public void testAttentionChangedTriggersCondition() throws RemoteException { - final ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor = - ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class); - verify(mDreamOverlayStateController).addCallback(callbackCaptor.capture()); - - when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true); - callbackCaptor.getValue().onStateChanged(); - - final ArgumentCaptor<IVisualQueryDetectionAttentionListener> listenerCaptor = - ArgumentCaptor.forClass(IVisualQueryDetectionAttentionListener.class); - verify(mAssistUtils).enableVisualQueryDetection(listenerCaptor.capture()); + public void testAttentionChangedTriggersCondition() { + final ArgumentCaptor<VisualQueryAttentionListener> argumentCaptor = + ArgumentCaptor.forClass(VisualQueryAttentionListener.class); + verify(mAssistManager).addVisualQueryAttentionListener(argumentCaptor.capture()); - listenerCaptor.getValue().onAttentionGained(); + argumentCaptor.getValue().onAttentionGained(); assertThat(mAssistantAttentionCondition.isConditionMet()).isTrue(); - listenerCaptor.getValue().onAttentionLost(); + argumentCaptor.getValue().onAttentionLost(); assertThat(mAssistantAttentionCondition.isConditionMet()).isFalse(); verify(mCallback, times(2)).onConditionChanged(eq(mAssistantAttentionCondition)); |