Merge "Add unfiltered access to the dream smartspace targets, in order to extract weather data." into tm-qpr-dev
This commit is contained in:
@@ -33,9 +33,9 @@ import com.android.systemui.CoreStartable;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||||
import com.android.systemui.dreams.complication.dagger.DreamWeatherComplicationComponent;
|
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.ActivityStarter;
|
||||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener;
|
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener;
|
||||||
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
|
|
||||||
import com.android.systemui.util.ViewController;
|
import com.android.systemui.util.ViewController;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -73,7 +73,6 @@ public class DreamWeatherComplication implements Complication {
|
|||||||
* {@link CoreStartable} for registering {@link DreamWeatherComplication} with SystemUI.
|
* {@link CoreStartable} for registering {@link DreamWeatherComplication} with SystemUI.
|
||||||
*/
|
*/
|
||||||
public static class Registrant extends CoreStartable {
|
public static class Registrant extends CoreStartable {
|
||||||
private final LockscreenSmartspaceController mSmartSpaceController;
|
|
||||||
private final DreamOverlayStateController mDreamOverlayStateController;
|
private final DreamOverlayStateController mDreamOverlayStateController;
|
||||||
private final DreamWeatherComplication mComplication;
|
private final DreamWeatherComplication mComplication;
|
||||||
|
|
||||||
@@ -82,22 +81,18 @@ public class DreamWeatherComplication implements Complication {
|
|||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public Registrant(Context context,
|
public Registrant(Context context,
|
||||||
LockscreenSmartspaceController smartspaceController,
|
|
||||||
DreamOverlayStateController dreamOverlayStateController,
|
DreamOverlayStateController dreamOverlayStateController,
|
||||||
DreamWeatherComplication dreamWeatherComplication) {
|
DreamWeatherComplication dreamWeatherComplication) {
|
||||||
super(context);
|
super(context);
|
||||||
mSmartSpaceController = smartspaceController;
|
|
||||||
mDreamOverlayStateController = dreamOverlayStateController;
|
mDreamOverlayStateController = dreamOverlayStateController;
|
||||||
mComplication = dreamWeatherComplication;
|
mComplication = dreamWeatherComplication;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
if (mSmartSpaceController.isEnabled()) {
|
|
||||||
mDreamOverlayStateController.addComplication(mComplication);
|
mDreamOverlayStateController.addComplication(mComplication);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewHolder to contain value/logic associated with a Weather Complication View.
|
* ViewHolder to contain value/logic associated with a Weather Complication View.
|
||||||
@@ -134,7 +129,7 @@ public class DreamWeatherComplication implements Complication {
|
|||||||
* ViewController to contain value/logic associated with a Weather Complication View.
|
* ViewController to contain value/logic associated with a Weather Complication View.
|
||||||
*/
|
*/
|
||||||
static class DreamWeatherViewController extends ViewController<TextView> {
|
static class DreamWeatherViewController extends ViewController<TextView> {
|
||||||
private final LockscreenSmartspaceController mSmartSpaceController;
|
private final DreamSmartspaceController mSmartSpaceController;
|
||||||
private final ActivityStarter mActivityStarter;
|
private final ActivityStarter mActivityStarter;
|
||||||
private final String mSmartspaceTrampolineActivityComponent;
|
private final String mSmartspaceTrampolineActivityComponent;
|
||||||
private SmartspaceTargetListener mSmartspaceTargetListener;
|
private SmartspaceTargetListener mSmartspaceTargetListener;
|
||||||
@@ -144,7 +139,7 @@ public class DreamWeatherComplication implements Complication {
|
|||||||
@Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view,
|
@Named(DREAM_WEATHER_COMPLICATION_VIEW) TextView view,
|
||||||
@Named(SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT) String smartspaceTrampoline,
|
@Named(SMARTSPACE_TRAMPOLINE_ACTIVITY_COMPONENT) String smartspaceTrampoline,
|
||||||
ActivityStarter activityStarter,
|
ActivityStarter activityStarter,
|
||||||
LockscreenSmartspaceController smartspaceController
|
DreamSmartspaceController smartspaceController
|
||||||
) {
|
) {
|
||||||
super(view);
|
super(view);
|
||||||
mActivityStarter = activityStarter;
|
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
|
@Override
|
||||||
protected void onViewDetached() {
|
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.SmartspaceConfig
|
||||||
import android.app.smartspace.SmartspaceManager
|
import android.app.smartspace.SmartspaceManager
|
||||||
import android.app.smartspace.SmartspaceSession
|
import android.app.smartspace.SmartspaceSession
|
||||||
|
import android.app.smartspace.SmartspaceTarget
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@@ -66,7 +67,9 @@ class DreamSmartspaceController @Inject constructor(
|
|||||||
private var targetFilter: SmartspaceTargetFilter? = optionalTargetFilter.orElse(null)
|
private var targetFilter: SmartspaceTargetFilter? = optionalTargetFilter.orElse(null)
|
||||||
|
|
||||||
// A shadow copy of listeners is maintained to track whether the session should remain open.
|
// 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
|
// Smartspace can be used on multiple displays, such as when the user casts their screen
|
||||||
private var smartspaceViews = mutableSetOf<SmartspaceView>()
|
private var smartspaceViews = mutableSetOf<SmartspaceView>()
|
||||||
@@ -113,6 +116,7 @@ class DreamSmartspaceController @Inject constructor(
|
|||||||
private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
|
private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
|
||||||
execution.assertIsMainThread()
|
execution.assertIsMainThread()
|
||||||
|
|
||||||
|
onTargetsAvailableUnfiltered(targets)
|
||||||
val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true }
|
val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true }
|
||||||
plugin?.onTargetsAvailable(filteredTargets)
|
plugin?.onTargetsAvailable(filteredTargets)
|
||||||
}
|
}
|
||||||
@@ -151,7 +155,8 @@ class DreamSmartspaceController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun hasActiveSessionListeners(): Boolean {
|
private fun hasActiveSessionListeners(): Boolean {
|
||||||
return smartspaceViews.isNotEmpty() || listeners.isNotEmpty()
|
return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() ||
|
||||||
|
unfilteredListeners.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun connectSession() {
|
private fun connectSession() {
|
||||||
@@ -164,13 +169,15 @@ class DreamSmartspaceController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val newSession = smartspaceManager.createSmartspaceSession(
|
val newSession = smartspaceManager.createSmartspaceSession(
|
||||||
SmartspaceConfig.Builder(context, "dream").build())
|
SmartspaceConfig.Builder(context, "dream").build()
|
||||||
|
)
|
||||||
Log.d(TAG, "Starting smartspace session for dream")
|
Log.d(TAG, "Starting smartspace session for dream")
|
||||||
newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
|
newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener)
|
||||||
this.session = newSession
|
this.session = newSession
|
||||||
|
|
||||||
plugin.registerSmartspaceEventNotifier {
|
plugin.registerSmartspaceEventNotifier {
|
||||||
e -> session?.notifySmartspaceEvent(e)
|
e ->
|
||||||
|
session?.notifySmartspaceEvent(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadSmartspace()
|
reloadSmartspace()
|
||||||
@@ -218,4 +225,22 @@ class DreamSmartspaceController @Inject constructor(
|
|||||||
private fun reloadSmartspace() {
|
private fun reloadSmartspace() {
|
||||||
session?.requestSmartspaceUpdate()
|
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.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
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.verify;
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.dreams.DreamOverlayStateController;
|
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.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -39,12 +40,14 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
public class DreamWeatherComplicationTest extends SysuiTestCase {
|
public class DreamWeatherComplicationTest extends SysuiTestCase {
|
||||||
|
private static final String TRAMPOLINE_COMPONENT = "TestComponent";
|
||||||
|
|
||||||
@SuppressWarnings("HidingField")
|
@SuppressWarnings("HidingField")
|
||||||
@Mock
|
@Mock
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private LockscreenSmartspaceController mSmartspaceController;
|
private DreamSmartspaceController mDreamSmartspaceController;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private DreamOverlayStateController mDreamOverlayStateController;
|
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
|
@Test
|
||||||
public void testComplicationAvailability() {
|
public void testComplicationRegistered() {
|
||||||
when(mSmartspaceController.isEnabled()).thenReturn(false);
|
|
||||||
final DreamWeatherComplication.Registrant registrant =
|
final DreamWeatherComplication.Registrant registrant =
|
||||||
new DreamWeatherComplication.Registrant(
|
new DreamWeatherComplication.Registrant(
|
||||||
mContext,
|
mContext,
|
||||||
mSmartspaceController,
|
|
||||||
mDreamOverlayStateController,
|
mDreamOverlayStateController,
|
||||||
mComplication);
|
mComplication);
|
||||||
registrant.start();
|
registrant.start();
|
||||||
verify(mDreamOverlayStateController, never()).addComplication(any());
|
|
||||||
|
|
||||||
when(mSmartspaceController.isEnabled()).thenReturn(true);
|
|
||||||
registrant.start();
|
|
||||||
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
|
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