Merge "Add unfiltered access to the dream smartspace targets, in order to extract weather data." into tm-qpr-dev

This commit is contained in:
Lucas Silva
2022-06-13 21:52:06 +00:00
committed by Android (Google) Code Review
3 changed files with 59 additions and 28 deletions

View File

@@ -33,9 +33,9 @@ import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -73,7 +73,6 @@ public class DreamWeatherComplication implements Complication {
* {@link CoreStartable} for registering {@link DreamWeatherComplication} with SystemUI.
*/
public static class Registrant extends CoreStartable {
private final LockscreenSmartspaceController mSmartSpaceController;
private final DreamOverlayStateController mDreamOverlayStateController;
private final DreamWeatherComplication mComplication;
@@ -82,20 +81,16 @@ public class DreamWeatherComplication implements Complication {
*/
@Inject
public Registrant(Context context,
LockscreenSmartspaceController smartspaceController,
DreamOverlayStateController dreamOverlayStateController,
DreamWeatherComplication dreamWeatherComplication) {
super(context);
mSmartSpaceController = smartspaceController;
mDreamOverlayStateController = dreamOverlayStateController;
mComplication = dreamWeatherComplication;
}
@Override
public void start() {
if (mSmartSpaceController.isEnabled()) {
mDreamOverlayStateController.addComplication(mComplication);
}
mDreamOverlayStateController.addComplication(mComplication);
}
}
@@ -134,7 +129,7 @@ public class DreamWeatherComplication implements Complication {
* ViewController to contain value/logic associated with a Weather Complication View.
*/
static class DreamWeatherViewController extends ViewController<TextView> {
private final LockscreenSmartspaceController mSmartSpaceController;
private final DreamSmartspaceController mSmartSpaceController;
private final ActivityStarter mActivityStarter;
private final String mSmartspaceTrampolineActivityComponent;
private SmartspaceTargetListener mSmartspaceTargetListener;
@@ -144,7 +139,7 @@ public class DreamWeatherComplication implements Complication {
@Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view,
@Named(SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT) String smartspaceTrampoline,
ActivityStarter activityStarter,
LockscreenSmartspaceController smartspaceController
DreamSmartspaceController smartspaceController
) {
super(view);
mActivityStarter = activityStarter;
@@ -192,12 +187,14 @@ public class DreamWeatherComplication implements Complication {
});
}
});
mSmartSpaceController.addListener(mSmartspaceTargetListener);
// We need to use an unfiltered listener here since weather is filtered from showing
// in the dream smartspace.
mSmartSpaceController.addUnfilteredListener(mSmartspaceTargetListener);
}
@Override
protected void onViewDetached() {
mSmartSpaceController.removeListener(mSmartspaceTargetListener);
mSmartSpaceController.removeUnfilteredListener(mSmartspaceTargetListener);
}
}
}

View File

@@ -19,6 +19,7 @@ package com.android.systemui.dreams.smartspace
import android.app.smartspace.SmartspaceConfig
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
import android.app.smartspace.SmartspaceTarget
import android.content.Context
import android.graphics.Color
import android.util.Log
@@ -66,7 +67,9 @@ class DreamSmartspaceController @Inject constructor(
private var targetFilter: SmartspaceTargetFilter? = optionalTargetFilter.orElse(null)
// A shadow copy of listeners is maintained to track whether the session should remain open.
private var listeners = mutableSetOf<BcSmartspaceDataPlugin.SmartspaceTargetListener>()
private var listeners = mutableSetOf<SmartspaceTargetListener>()
private var unfilteredListeners = mutableSetOf<SmartspaceTargetListener>()
// Smartspace can be used on multiple displays, such as when the user casts their screen
private var smartspaceViews = mutableSetOf<SmartspaceView>()
@@ -113,6 +116,7 @@ class DreamSmartspaceController @Inject constructor(
private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
execution.assertIsMainThread()
onTargetsAvailableUnfiltered(targets)
val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true }
plugin?.onTargetsAvailable(filteredTargets)
}
@@ -137,7 +141,7 @@ class DreamSmartspaceController @Inject constructor(
private fun buildView(parent: ViewGroup): View? {
return if (plugin != null) {
var view = smartspaceViewComponentFactory.create(parent, plugin, stateChangeListener)
.getView()
.getView()
if (view !is View) {
return null
}
@@ -151,7 +155,8 @@ class DreamSmartspaceController @Inject constructor(
}
private fun hasActiveSessionListeners(): Boolean {
return smartspaceViews.isNotEmpty() || listeners.isNotEmpty()
return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() ||
unfilteredListeners.isNotEmpty()
}
private fun connectSession() {
@@ -164,13 +169,15 @@ class DreamSmartspaceController @Inject constructor(
}
val newSession = smartspaceManager.createSmartspaceSession(
SmartspaceConfig.Builder(context, "dream").build())
SmartspaceConfig.Builder(context, "dream").build()
)
Log.d(TAG, "Starting smartspace session for dream")
newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
this.session = newSession
plugin.registerSmartspaceEventNotifier {
e -> session?.notifySmartspaceEvent(e)
e ->
session?.notifySmartspaceEvent(e)
}
reloadSmartspace()
@@ -218,4 +225,22 @@ class DreamSmartspaceController @Inject constructor(
private fun reloadSmartspace() {
session?.requestSmartspaceUpdate()
}
private fun onTargetsAvailableUnfiltered(targets: List<SmartspaceTarget>) {
unfilteredListeners.forEach { it.onSmartspaceTargetsUpdated(targets) }
}
/**
* Adds a listener for the raw, unfiltered list of smartspace targets. This should be used
* carefully, as it doesn't filter out targets which the user may not want shown.
*/
fun addUnfilteredListener(listener: SmartspaceTargetListener) {
unfilteredListeners.add(listener)
connectSession()
}
fun removeUnfilteredListener(listener: SmartspaceTargetListener) {
unfilteredListeners.remove(listener)
disconnect()
}
}

View File

@@ -17,18 +17,19 @@ package com.android.systemui.dreams.complication;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.testing.AndroidTestingRunner;
import android.widget.TextView;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
import com.android.systemui.plugins.ActivityStarter;
import org.junit.Before;
import org.junit.Test;
@@ -39,12 +40,14 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamWeatherComplicationTest extends SysuiTestCase {
private static final String TRAMPOLINE_COMPONENT = "TestComponent";
@SuppressWarnings("HidingField")
@Mock
private Context mContext;
@Mock
private LockscreenSmartspaceController mSmartspaceController;
private DreamSmartspaceController mDreamSmartspaceController;
@Mock
private DreamOverlayStateController mDreamOverlayStateController;
@@ -58,22 +61,28 @@ public class DreamWeatherComplicationTest extends SysuiTestCase {
}
/**
* Ensures {@link DreamWeatherComplication} is only registered when it is available.
* Ensures {@link DreamWeatherComplication} is registered.
*/
@Test
public void testComplicationAvailability() {
when(mSmartspaceController.isEnabled()).thenReturn(false);
public void testComplicationRegistered() {
final DreamWeatherComplication.Registrant registrant =
new DreamWeatherComplication.Registrant(
mContext,
mSmartspaceController,
mDreamOverlayStateController,
mComplication);
registrant.start();
verify(mDreamOverlayStateController, never()).addComplication(any());
when(mSmartspaceController.isEnabled()).thenReturn(true);
registrant.start();
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
@Test
public void testGetUnfilteredTargets() {
final DreamWeatherComplication.DreamWeatherViewController controller =
new DreamWeatherComplication.DreamWeatherViewController(mock(
TextView.class), TRAMPOLINE_COMPONENT, mock(ActivityStarter.class),
mDreamSmartspaceController);
controller.onViewAttached();
verify(mDreamSmartspaceController).addUnfilteredListener(any());
controller.onViewDetached();
verify(mDreamSmartspaceController).removeUnfilteredListener(any());
}
}