Merge "Add date(+weather)(+alarm+dnd) view to lockscreen if decoupling enabled." into tm-qpr-dev am: 2bde1bdcce am: 00960fae4c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21132365 Change-Id: Ic20467b2af7e04839d054233559261c242f85640 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -91,6 +91,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
private ViewGroup mStatusArea;
|
||||
|
||||
// If the SMARTSPACE flag is set, keyguard_slice_view is replaced by the following views.
|
||||
private ViewGroup mDateWeatherView;
|
||||
private View mWeatherView;
|
||||
private View mSmartspaceView;
|
||||
|
||||
@@ -201,7 +202,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
// TODO(b/261757708): add content observer for the Settings toggle and add/remove
|
||||
// weather according to the Settings.
|
||||
if (mSmartspaceController.isDateWeatherDecoupled()) {
|
||||
addWeatherView(viewIndex);
|
||||
addDateWeatherView(viewIndex);
|
||||
viewIndex += 1;
|
||||
}
|
||||
|
||||
@@ -239,6 +240,14 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
|
||||
void onLocaleListChanged() {
|
||||
if (mSmartspaceController.isEnabled()) {
|
||||
if (mSmartspaceController.isDateWeatherDecoupled()) {
|
||||
mDateWeatherView.removeView(mWeatherView);
|
||||
int index = mStatusArea.indexOfChild(mDateWeatherView);
|
||||
if (index >= 0) {
|
||||
mStatusArea.removeView(mDateWeatherView);
|
||||
addDateWeatherView(index);
|
||||
}
|
||||
}
|
||||
int index = mStatusArea.indexOfChild(mSmartspaceView);
|
||||
if (index >= 0) {
|
||||
mStatusArea.removeView(mSmartspaceView);
|
||||
@@ -247,16 +256,28 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
|
||||
}
|
||||
}
|
||||
|
||||
private void addWeatherView(int index) {
|
||||
mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
|
||||
private void addDateWeatherView(int index) {
|
||||
mDateWeatherView = (ViewGroup) mSmartspaceController.buildAndConnectDateView(mView);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
MATCH_PARENT, WRAP_CONTENT);
|
||||
mStatusArea.addView(mWeatherView, index, lp);
|
||||
mStatusArea.addView(mDateWeatherView, index, lp);
|
||||
int startPadding = getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.below_clock_padding_start);
|
||||
int endPadding = getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.below_clock_padding_end);
|
||||
mWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
|
||||
mDateWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
|
||||
|
||||
addWeatherView();
|
||||
}
|
||||
|
||||
private void addWeatherView() {
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
WRAP_CONTENT, WRAP_CONTENT);
|
||||
mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
|
||||
// Place weather right after the date, before the extras
|
||||
final int index = mDateWeatherView.getChildCount() == 0 ? 0 : 1;
|
||||
mDateWeatherView.addView(mWeatherView, index, lp);
|
||||
mWeatherView.setPaddingRelative(0, 0, 4, 0);
|
||||
}
|
||||
|
||||
private void addSmartspaceView(int index) {
|
||||
|
||||
@@ -217,6 +217,10 @@ public abstract class SystemUIModule {
|
||||
@BindsOptionalOf
|
||||
abstract BcSmartspaceConfigPlugin optionalBcSmartspaceConfigPlugin();
|
||||
|
||||
@BindsOptionalOf
|
||||
@Named(SmartspaceModule.DATE_SMARTSPACE_DATA_PLUGIN)
|
||||
abstract BcSmartspaceDataPlugin optionalDateSmartspaceConfigPlugin();
|
||||
|
||||
@BindsOptionalOf
|
||||
@Named(SmartspaceModule.WEATHER_SMARTSPACE_DATA_PLUGIN)
|
||||
abstract BcSmartspaceDataPlugin optionalWeatherSmartspaceConfigPlugin();
|
||||
|
||||
@@ -43,6 +43,11 @@ abstract class SmartspaceModule {
|
||||
*/
|
||||
const val DREAM_SMARTSPACE_PRECONDITION = "dream_smartspace_precondition"
|
||||
|
||||
/**
|
||||
* The BcSmartspaceDataPlugin for the standalone date (+alarm+dnd).
|
||||
*/
|
||||
const val DATE_SMARTSPACE_DATA_PLUGIN = "date_smartspace_data_plugin"
|
||||
|
||||
/**
|
||||
* The BcSmartspaceDataPlugin for the standalone weather.
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.regionsampling.RegionSampler
|
||||
import com.android.systemui.shared.regionsampling.UpdateColorCallback
|
||||
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
|
||||
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
@@ -84,6 +85,8 @@ constructor(
|
||||
@Main private val uiExecutor: Executor,
|
||||
@Background private val bgExecutor: Executor,
|
||||
@Main private val handler: Handler,
|
||||
@Named(DATE_SMARTSPACE_DATA_PLUGIN)
|
||||
optionalDatePlugin: Optional<BcSmartspaceDataPlugin>,
|
||||
@Named(WEATHER_SMARTSPACE_DATA_PLUGIN)
|
||||
optionalWeatherPlugin: Optional<BcSmartspaceDataPlugin>,
|
||||
optionalPlugin: Optional<BcSmartspaceDataPlugin>,
|
||||
@@ -94,6 +97,7 @@ constructor(
|
||||
}
|
||||
|
||||
private var session: SmartspaceSession? = null
|
||||
private val datePlugin: BcSmartspaceDataPlugin? = optionalDatePlugin.orElse(null)
|
||||
private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null)
|
||||
private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
|
||||
private val configPlugin: BcSmartspaceConfigPlugin? = optionalConfigPlugin.orElse(null)
|
||||
@@ -223,7 +227,7 @@ constructor(
|
||||
execution.assertIsMainThread()
|
||||
|
||||
return featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED) &&
|
||||
weatherPlugin != null
|
||||
datePlugin != null && weatherPlugin != null
|
||||
}
|
||||
|
||||
private fun updateBypassEnabled() {
|
||||
@@ -231,6 +235,25 @@ constructor(
|
||||
smartspaceViews.forEach { it.setKeyguardBypassEnabled(bypassEnabled) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the date view and connects it to the smartspace service.
|
||||
*/
|
||||
fun buildAndConnectDateView(parent: ViewGroup): View? {
|
||||
execution.assertIsMainThread()
|
||||
|
||||
if (!isEnabled()) {
|
||||
throw RuntimeException("Cannot build view when not enabled")
|
||||
}
|
||||
if (!isDateWeatherDecoupled()) {
|
||||
throw RuntimeException("Cannot build date view when not decoupled")
|
||||
}
|
||||
|
||||
val view = buildView(parent, datePlugin)
|
||||
connectSession()
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the weather view and connects it to the smartspace service.
|
||||
*/
|
||||
@@ -309,7 +332,7 @@ constructor(
|
||||
}
|
||||
|
||||
private fun connectSession() {
|
||||
if (weatherPlugin == null && plugin == null) return
|
||||
if (datePlugin == null && weatherPlugin == null && plugin == null) return
|
||||
if (session != null || smartspaceViews.isEmpty()) {
|
||||
return
|
||||
}
|
||||
@@ -347,6 +370,7 @@ constructor(
|
||||
statusBarStateController.addCallback(statusBarStateListener)
|
||||
bypassController.registerOnBypassStateChangedListener(bypassStateChangedListener)
|
||||
|
||||
datePlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
|
||||
weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
|
||||
plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
|
||||
|
||||
@@ -384,6 +408,8 @@ constructor(
|
||||
bypassController.unregisterOnBypassStateChangedListener(bypassStateChangedListener)
|
||||
session = null
|
||||
|
||||
datePlugin?.registerSmartspaceEventNotifier(null)
|
||||
|
||||
weatherPlugin?.registerSmartspaceEventNotifier(null)
|
||||
weatherPlugin?.onTargetsAvailable(emptyList())
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
@@ -118,6 +119,11 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private LogBuffer mLogBuffer;
|
||||
|
||||
private final View mFakeDateView = (View) (new ViewGroup(mContext) {
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {}
|
||||
});
|
||||
private final View mFakeWeatherView = new View(mContext);
|
||||
private final View mFakeSmartspaceView = new View(mContext);
|
||||
|
||||
private KeyguardClockSwitchController mController;
|
||||
@@ -145,6 +151,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
when(mLargeClockView.getContext()).thenReturn(getContext());
|
||||
|
||||
when(mView.isAttachedToWindow()).thenReturn(true);
|
||||
when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView);
|
||||
when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView);
|
||||
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
|
||||
mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
mController = new KeyguardClockSwitchController(
|
||||
@@ -251,6 +259,19 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
|
||||
verify(mSmartspaceController, times(2)).buildAndConnectView(mView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onLocaleListChanged_rebuildsSmartspaceViews_whenDecouplingEnabled() {
|
||||
when(mSmartspaceController.isEnabled()).thenReturn(true);
|
||||
when(mSmartspaceController.isDateWeatherDecoupled()).thenReturn(true);
|
||||
mController.init();
|
||||
|
||||
mController.onLocaleListChanged();
|
||||
// Should be called once on initial setup, then once again for locale change
|
||||
verify(mSmartspaceController, times(2)).buildAndConnectDateView(mView);
|
||||
verify(mSmartspaceController, times(2)).buildAndConnectWeatherView(mView);
|
||||
verify(mSmartspaceController, times(2)).buildAndConnectView(mView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmartspaceDisabledShowsKeyguardStatusArea() {
|
||||
when(mSmartspaceController.isEnabled()).thenReturn(false);
|
||||
|
||||
@@ -112,6 +112,9 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var handler: Handler
|
||||
|
||||
@Mock
|
||||
private lateinit var datePlugin: BcSmartspaceDataPlugin
|
||||
|
||||
@Mock
|
||||
private lateinit var weatherPlugin: BcSmartspaceDataPlugin
|
||||
|
||||
@@ -155,6 +158,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
KeyguardBypassController.OnBypassStateChangedListener
|
||||
private lateinit var deviceProvisionedListener: DeviceProvisionedListener
|
||||
|
||||
private lateinit var dateSmartspaceView: SmartspaceView
|
||||
private lateinit var weatherSmartspaceView: SmartspaceView
|
||||
private lateinit var smartspaceView: SmartspaceView
|
||||
|
||||
@@ -190,6 +194,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
`when`(secureSettings.getUriFor(NOTIF_ON_LOCKSCREEN_SETTING))
|
||||
.thenReturn(fakeNotifOnLockscreenSettingUri)
|
||||
`when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(smartspaceSession)
|
||||
`when`(datePlugin.getView(any())).thenReturn(
|
||||
createDateSmartspaceView(), createDateSmartspaceView())
|
||||
`when`(weatherPlugin.getView(any())).thenReturn(
|
||||
createWeatherSmartspaceView(), createWeatherSmartspaceView())
|
||||
`when`(plugin.getView(any())).thenReturn(createSmartspaceView(), createSmartspaceView())
|
||||
@@ -221,6 +227,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
executor,
|
||||
bgExecutor,
|
||||
handler,
|
||||
Optional.of(datePlugin),
|
||||
Optional.of(weatherPlugin),
|
||||
Optional.of(plugin),
|
||||
Optional.of(configPlugin),
|
||||
@@ -275,7 +282,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
|
||||
// THEN the listener is registered to the underlying plugin
|
||||
verify(plugin).registerListener(controllerListener)
|
||||
// The listener is registered only for the plugin, not the weather plugin.
|
||||
// The listener is registered only for the plugin, not the date, or weather plugin.
|
||||
verify(datePlugin, never()).registerListener(any())
|
||||
verify(weatherPlugin, never()).registerListener(any())
|
||||
}
|
||||
|
||||
@@ -289,7 +297,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
|
||||
// THEN the listener is subsequently registered
|
||||
verify(plugin).registerListener(controllerListener)
|
||||
// The listener is registered only for the plugin, not the weather plugin.
|
||||
// The listener is registered only for the plugin, not the date, or the weather plugin.
|
||||
verify(datePlugin, never()).registerListener(any())
|
||||
verify(weatherPlugin, never()).registerListener(any())
|
||||
}
|
||||
|
||||
@@ -308,6 +317,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
verify(plugin).registerSmartspaceEventNotifier(null)
|
||||
verify(weatherPlugin).onTargetsAvailable(emptyList())
|
||||
verify(weatherPlugin).registerSmartspaceEventNotifier(null)
|
||||
verify(datePlugin).registerSmartspaceEventNotifier(null)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -357,6 +367,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
configChangeListener.onThemeChanged()
|
||||
|
||||
// We update the new text color to match the wallpaper color
|
||||
verify(dateSmartspaceView).setPrimaryTextColor(anyInt())
|
||||
verify(weatherSmartspaceView).setPrimaryTextColor(anyInt())
|
||||
verify(smartspaceView).setPrimaryTextColor(anyInt())
|
||||
}
|
||||
@@ -384,6 +395,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
statusBarStateListener.onDozeAmountChanged(0.1f, 0.7f)
|
||||
|
||||
// We pass that along to the view
|
||||
verify(dateSmartspaceView).setDozeAmount(0.7f)
|
||||
verify(weatherSmartspaceView).setDozeAmount(0.7f)
|
||||
verify(smartspaceView).setDozeAmount(0.7f)
|
||||
}
|
||||
@@ -502,6 +514,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
verify(plugin).onTargetsAvailable(eq(listOf(targets[0], targets[1], targets[2])))
|
||||
// No filtering is applied for the weather plugin
|
||||
verify(weatherPlugin).onTargetsAvailable(eq(targets))
|
||||
// No targets needed for the date plugin
|
||||
verify(datePlugin, never()).onTargetsAvailable(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -633,6 +647,18 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
|
||||
private fun connectSession() {
|
||||
if (controller.isDateWeatherDecoupled()) {
|
||||
val dateView = controller.buildAndConnectDateView(fakeParent)
|
||||
dateSmartspaceView = dateView as SmartspaceView
|
||||
fakeParent.addView(dateView)
|
||||
controller.stateChangeListener.onViewAttachedToWindow(dateView)
|
||||
|
||||
verify(dateSmartspaceView).setUiSurface(
|
||||
BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
|
||||
verify(dateSmartspaceView).registerDataProvider(datePlugin)
|
||||
|
||||
verify(dateSmartspaceView).setPrimaryTextColor(anyInt())
|
||||
verify(dateSmartspaceView).setDozeAmount(0.5f)
|
||||
|
||||
val weatherView = controller.buildAndConnectWeatherView(fakeParent)
|
||||
weatherSmartspaceView = weatherView as SmartspaceView
|
||||
fakeParent.addView(weatherView)
|
||||
@@ -686,6 +712,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
verify(smartspaceView).setDozeAmount(0.5f)
|
||||
|
||||
if (controller.isDateWeatherDecoupled()) {
|
||||
clearInvocations(dateSmartspaceView)
|
||||
clearInvocations(weatherSmartspaceView)
|
||||
}
|
||||
clearInvocations(smartspaceView)
|
||||
@@ -734,7 +761,38 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
).thenReturn(if (value) 1 else 0)
|
||||
}
|
||||
|
||||
// Separate function for the weather view, which doesn't implement all functions in interface.
|
||||
// Separate function for the date view, which implements a specific subset of all functions.
|
||||
private fun createDateSmartspaceView(): SmartspaceView {
|
||||
return spy(object : View(context), SmartspaceView {
|
||||
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
|
||||
}
|
||||
|
||||
override fun setPrimaryTextColor(color: Int) {
|
||||
}
|
||||
|
||||
override fun setIsDreaming(isDreaming: Boolean) {
|
||||
}
|
||||
|
||||
override fun setUiSurface(uiSurface: String) {
|
||||
}
|
||||
|
||||
override fun setDozeAmount(amount: Float) {
|
||||
}
|
||||
|
||||
override fun setIntentStarter(intentStarter: BcSmartspaceDataPlugin.IntentStarter?) {
|
||||
}
|
||||
|
||||
override fun setFalsingManager(falsingManager: FalsingManager?) {
|
||||
}
|
||||
|
||||
override fun setDnd(image: Drawable?, description: String?) {
|
||||
}
|
||||
|
||||
override fun setNextAlarm(image: Drawable?, description: String?) {
|
||||
}
|
||||
})
|
||||
}
|
||||
// Separate function for the weather view, which implements a specific subset of all functions.
|
||||
private fun createWeatherSmartspaceView(): SmartspaceView {
|
||||
return spy(object : View(context), SmartspaceView {
|
||||
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
|
||||
|
||||
Reference in New Issue
Block a user