Add unfiltered access to the dream smartspace targets, in order to
extract weather data. Weather data is filtered from showing in the dream smartspace view. However, we need to extract the weather card for the weather complication. Therefore we need unfiltered access to the weather data, which this change adds. Bug: 231973747 Test: locally on device Test: atest DreamWeatherComplicationTest Change-Id: Ic2f815720ad554091f7ca068845e421f0e0baf23
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user