Merge "Implement ComplicationTypesUpdater."
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 4696eed..4dacf65 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -31,10 +31,8 @@
import com.android.internal.policy.PhoneWindow;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.complication.Complication;
-import com.android.systemui.dreams.complication.ComplicationUtils;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
@@ -59,7 +57,6 @@
// content area).
private final DreamOverlayContainerViewController mDreamOverlayContainerViewController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private final DreamBackend mDreamBackend;
// A reference to the {@link Window} used to hold the dream overlay.
private Window mWindow;
@@ -112,7 +109,6 @@
setCurrentState(Lifecycle.State.CREATED);
mLifecycleRegistry = component.getLifecycleRegistry();
mDreamOverlayTouchMonitor = component.getDreamOverlayTouchMonitor();
- mDreamBackend = component.getDreamBackend();
mDreamOverlayTouchMonitor.init();
}
@@ -136,9 +132,6 @@
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
setCurrentState(Lifecycle.State.STARTED);
mExecutor.execute(() -> {
- mStateController.setAvailableComplicationTypes(
- ComplicationUtils.convertComplicationTypes(
- mDreamBackend.getEnabledComplications()));
addOverlayWindowLocked(layoutParams);
setCurrentState(Lifecycle.State.RESUMED);
mStateController.setOverlayActive(true);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java
new file mode 100644
index 0000000..83249aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationTypesUpdater.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.util.settings.SecureSettings;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * {@link ComplicationTypesUpdater} observes the state of available complication types set by the
+ * user, and pushes updates to {@link DreamOverlayStateController}.
+ */
+@SysUISingleton
+public class ComplicationTypesUpdater extends CoreStartable {
+ private final DreamBackend mDreamBackend;
+ private final Executor mExecutor;
+ private final SecureSettings mSecureSettings;
+
+ private final DreamOverlayStateController mDreamOverlayStateController;
+
+ @Inject
+ ComplicationTypesUpdater(Context context,
+ DreamBackend dreamBackend,
+ @Main Executor executor,
+ SecureSettings secureSettings,
+ DreamOverlayStateController dreamOverlayStateController) {
+ super(context);
+
+ mDreamBackend = dreamBackend;
+ mExecutor = executor;
+ mSecureSettings = secureSettings;
+ mDreamOverlayStateController = dreamOverlayStateController;
+ }
+
+ @Override
+ public void start() {
+ final ContentObserver settingsObserver = new ContentObserver(null /*handler*/) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mExecutor.execute(() -> mDreamOverlayStateController.setAvailableComplicationTypes(
+ getAvailableComplicationTypes()));
+ }
+ };
+
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS,
+ settingsObserver,
+ UserHandle.myUserId());
+ settingsObserver.onChange(false);
+ }
+
+ /**
+ * Returns complication types that are currently available by user setting.
+ */
+ @Complication.ComplicationType
+ private int getAvailableComplicationTypes() {
+ return ComplicationUtils.convertComplicationTypes(mDreamBackend.getEnabledComplications());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index d8af9e5..c61f796 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -16,10 +16,14 @@
package com.android.systemui.dreams.dagger;
+import android.content.Context;
+
+import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
import com.android.systemui.dreams.touch.dagger.DreamTouchModule;
import dagger.Module;
+import dagger.Provides;
/**
* Dagger Module providing Communal-related functionality.
@@ -32,4 +36,11 @@
DreamOverlayComponent.class,
})
public interface DreamModule {
+ /**
+ * Provides an instance of the dream backend.
+ */
+ @Provides
+ static DreamBackend providesDreamBackend(Context context) {
+ return DreamBackend.getInstance(context);
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
index 60278a9..05ab901 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayComponent.java
@@ -22,7 +22,6 @@
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.ViewModelStore;
-import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.dreams.DreamOverlayContainerViewController;
import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.complication.dagger.ComplicationModule;
@@ -69,7 +68,4 @@
/** Builds a {@link DreamOverlayTouchMonitor} */
DreamOverlayTouchMonitor getDreamOverlayTouchMonitor();
-
- /** Builds a ${@link DreamBackend} */
- DreamBackend getDreamBackend();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index efa063f..4eb5cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -17,7 +17,6 @@
package com.android.systemui.dreams.dagger;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.view.LayoutInflater;
@@ -28,7 +27,6 @@
import androidx.lifecycle.LifecycleRegistry;
import com.android.internal.util.Preconditions;
-import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.battery.BatteryMeterViewController;
@@ -149,10 +147,4 @@
static Lifecycle providesLifecycle(LifecycleOwner lifecycleOwner) {
return lifecycleOwner.getLifecycle();
}
-
- @Provides
- @DreamOverlayComponent.DreamOverlayScope
- static DreamBackend providesDreamBackend(Context context) {
- return DreamBackend.getInstance(context);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 529a163..58ffbfa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -37,9 +37,7 @@
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dreams.complication.Complication;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.touch.DreamOverlayTouchMonitor;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -53,10 +51,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamOverlayServiceTest extends SysuiTestCase {
@@ -101,9 +95,6 @@
@Mock
DreamOverlayStateController mStateController;
- @Mock
- DreamBackend mDreamBackend;
-
DreamOverlayService mService;
@Before
@@ -119,8 +110,6 @@
.thenReturn(mLifecycleRegistry);
when(mDreamOverlayComponent.getDreamOverlayTouchMonitor())
.thenReturn(mDreamOverlayTouchMonitor);
- when(mDreamOverlayComponent.getDreamBackend())
- .thenReturn(mDreamBackend);
when(mDreamOverlayComponentFactory
.create(any(), any()))
.thenReturn(mDreamOverlayComponent);
@@ -174,26 +163,6 @@
}
@Test
- public void testSetAvailableComplicationTypes() throws Exception {
- final Set<Integer> enabledComplications = new HashSet<>(
- Arrays.asList(DreamBackend.COMPLICATION_TYPE_TIME,
- DreamBackend.COMPLICATION_TYPE_DATE,
- DreamBackend.COMPLICATION_TYPE_WEATHER));
- when(mDreamBackend.getEnabledComplications()).thenReturn(enabledComplications);
-
- final IBinder proxy = mService.onBind(new Intent());
- final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
-
- overlay.startDream(mWindowParams, mDreamOverlayCallback);
- mMainExecutor.runAllReady();
-
- final int expectedTypes =
- Complication.COMPLICATION_TYPE_TIME | Complication.COMPLICATION_TYPE_DATE
- | Complication.COMPLICATION_TYPE_WEATHER;
- verify(mStateController).setAvailableComplicationTypes(expectedTypes);
- }
-
- @Test
public void testDestroy() {
mService.onDestroy();
mMainExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java
new file mode 100644
index 0000000..09976e0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationTypesUpdaterTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ComplicationTypesUpdaterTest extends SysuiTestCase {
+ @Mock
+ private Context mContext;
+ @Mock
+ private DreamBackend mDreamBackend;
+ @Mock
+ private SecureSettings mSecureSettings;
+ @Mock
+ private DreamOverlayStateController mDreamOverlayStateController;
+ @Captor
+ private ArgumentCaptor<ContentObserver> mSettingsObserverCaptor;
+
+ private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
+ private ComplicationTypesUpdater mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mDreamBackend.getEnabledComplications()).thenReturn(new HashSet<>());
+
+ mController = new ComplicationTypesUpdater(mContext, mDreamBackend, mExecutor,
+ mSecureSettings, mDreamOverlayStateController);
+ }
+
+ @Test
+ public void testPushUpdateToDreamOverlayStateControllerImmediatelyOnStart() {
+ // DreamOverlayStateController shouldn't be updated before start().
+ verify(mDreamOverlayStateController, never()).setAvailableComplicationTypes(anyInt());
+
+ mController.start();
+ mExecutor.runAllReady();
+
+ // DreamOverlayStateController updated immediately on start().
+ verify(mDreamOverlayStateController).setAvailableComplicationTypes(anyInt());
+ }
+
+ @Test
+ public void testPushUpdateToDreamOverlayStateControllerOnChange() {
+ mController.start();
+ mExecutor.runAllReady();
+
+ when(mDreamBackend.getEnabledComplications()).thenReturn(new HashSet<>(Arrays.asList(
+ DreamBackend.COMPLICATION_TYPE_TIME, DreamBackend.COMPLICATION_TYPE_WEATHER,
+ DreamBackend.COMPLICATION_TYPE_AIR_QUALITY)));
+ final ContentObserver settingsObserver = captureSettingsObserver();
+ settingsObserver.onChange(false);
+ mExecutor.runAllReady();
+
+ verify(mDreamOverlayStateController).setAvailableComplicationTypes(
+ Complication.COMPLICATION_TYPE_TIME | Complication.COMPLICATION_TYPE_WEATHER
+ | Complication.COMPLICATION_TYPE_AIR_QUALITY);
+ }
+
+ private ContentObserver captureSettingsObserver() {
+ verify(mSecureSettings).registerContentObserverForUser(
+ eq(Settings.Secure.SCREENSAVER_ENABLED_COMPLICATIONS),
+ mSettingsObserverCaptor.capture(), eq(UserHandle.myUserId()));
+ return mSettingsObserverCaptor.getValue();
+ }
+}