Merge "Adopt IVisualQueryRecognitionStatusListener for visual query detection." into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
fa4467c2d4
@@ -917,4 +917,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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
public void testAttentionChangedTriggersCondition() {
|
||||
final ArgumentCaptor<VisualQueryAttentionListener> argumentCaptor =
|
||||
ArgumentCaptor.forClass(VisualQueryAttentionListener.class);
|
||||
verify(mAssistManager).addVisualQueryAttentionListener(argumentCaptor.capture());
|
||||
|
||||
when(mDreamOverlayStateController.isDreamOverlayStatusBarVisible()).thenReturn(true);
|
||||
callbackCaptor.getValue().onStateChanged();
|
||||
|
||||
final ArgumentCaptor<IVisualQueryDetectionAttentionListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(IVisualQueryDetectionAttentionListener.class);
|
||||
verify(mAssistUtils).enableVisualQueryDetection(listenerCaptor.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));
|
||||
|
||||
Reference in New Issue
Block a user