summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java3
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java179
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java251
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java2
9 files changed, 448 insertions, 67 deletions
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index ab63b06cffa9..c1515fc30b60 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -116,6 +116,7 @@ import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -306,6 +307,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
RemoteInputUriController remoteInputUriController,
Optional<Divider> dividerOptional,
SuperStatusBarViewFactory superStatusBarViewFactory,
+ LightsOutNotifController lightsOutNotifController,
/* Car Settings injected components. */
CarNavigationBarController carNavigationBarController) {
super(
@@ -376,6 +378,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
pluginManager,
remoteInputUriController,
dividerOptional,
+ lightsOutNotifController,
superStatusBarViewFactory);
mScrimController = scrimController;
mCarNavigationBarController = carNavigationBarController;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index 7de2212eef4d..9b91843576ce 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -71,6 +71,7 @@ import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -175,6 +176,7 @@ public class CarStatusBarModule {
RemoteInputUriController remoteInputUriController,
Optional<Divider> dividerOptional,
SuperStatusBarViewFactory superStatusBarViewFactory,
+ LightsOutNotifController lightsOutNotifController,
CarNavigationBarController carNavigationBarController) {
return new CarStatusBar(
context,
@@ -244,6 +246,7 @@ public class CarStatusBarModule {
remoteInputUriController,
dividerOptional,
superStatusBarViewFactory,
+ lightsOutNotifController,
carNavigationBarController);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
new file mode 100644
index 000000000000..93887a6617f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 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.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+import android.view.View;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+import android.view.animation.AccelerateInterpolator;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Apps can request a low profile mode {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
+ * where status bar and navigation icons dim. In this mode, a notification dot appears
+ * where the notification icons would appear if they would be shown outside of this mode.
+ *
+ * This controller shows and hides the notification dot in the status bar to indicate
+ * whether there are notifications when the device is in {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}.
+ */
+@Singleton
+public class LightsOutNotifController {
+ private final CommandQueue mCommandQueue;
+ private final NotificationEntryManager mEntryManager;
+ private final WindowManager mWindowManager;
+
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ @VisibleForTesting @WindowInsetsController.Appearance int mAppearance;
+
+ private int mDisplayId;
+ private View mLightsOutNotifView;
+
+ @Inject
+ LightsOutNotifController(WindowManager windowManager,
+ NotificationEntryManager entryManager,
+ CommandQueue commandQueue) {
+ mWindowManager = windowManager;
+ mEntryManager = entryManager;
+ mCommandQueue = commandQueue;
+ }
+
+ /**
+ * Sets the notification dot view after it is created in the StatusBar.
+ * This is the view this controller will show and hide depending on whether:
+ * 1. there are active notifications
+ * 2. an app has requested {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
+ */
+ void setLightsOutNotifView(View lightsOutNotifView) {
+ destroy();
+ mLightsOutNotifView = lightsOutNotifView;
+
+ if (mLightsOutNotifView != null) {
+ mLightsOutNotifView.setVisibility(View.GONE);
+ mLightsOutNotifView.setAlpha(0f);
+ init();
+ }
+ }
+
+ private void destroy() {
+ mEntryManager.removeNotificationEntryListener(mEntryListener);
+ mCommandQueue.removeCallback(mCallback);
+ }
+
+ private void init() {
+ mDisplayId = mWindowManager.getDefaultDisplay().getDisplayId();
+ mEntryManager.addNotificationEntryListener(mEntryListener);
+ mCommandQueue.addCallback(mCallback);
+
+ updateLightsOutView();
+ }
+
+ private boolean hasActiveNotifications() {
+ return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+ }
+
+ @VisibleForTesting
+ void updateLightsOutView() {
+ if (mLightsOutNotifView == null) {
+ return;
+ }
+
+ final boolean showDot = shouldShowDot();
+ if (showDot != isShowingDot()) {
+ if (showDot) {
+ mLightsOutNotifView.setAlpha(0f);
+ mLightsOutNotifView.setVisibility(View.VISIBLE);
+ }
+
+ mLightsOutNotifView.animate()
+ .alpha(showDot ? 1 : 0)
+ .setDuration(showDot ? 750 : 250)
+ .setInterpolator(new AccelerateInterpolator(2.0f))
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator a) {
+ mLightsOutNotifView.setAlpha(showDot ? 1 : 0);
+ mLightsOutNotifView.setVisibility(showDot ? View.VISIBLE : View.GONE);
+ }
+ })
+ .start();
+ }
+ }
+
+ @VisibleForTesting
+ boolean isShowingDot() {
+ return mLightsOutNotifView.getVisibility() == View.VISIBLE
+ && mLightsOutNotifView.getAlpha() == 1.0f;
+ }
+
+ @VisibleForTesting
+ boolean shouldShowDot() {
+ return hasActiveNotifications() && areLightsOut();
+ }
+
+ @VisibleForTesting
+ boolean areLightsOut() {
+ return 0 != (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
+ }
+
+ private final CommandQueue.Callbacks mCallback = new CommandQueue.Callbacks() {
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId,
+ @WindowInsetsController.Appearance int appearance,
+ AppearanceRegion[] appearanceRegions,
+ boolean navbarColorManagedByIme) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ mAppearance = appearance;
+ updateLightsOutView();
+ }
+ };
+
+ private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
+ // Cares about notifications post-filtering
+ @Override
+ public void onNotificationAdded(NotificationEntry entry) {
+ updateLightsOutView();
+ }
+
+ @Override
+ public void onPostEntryUpdated(NotificationEntry entry) {
+ updateLightsOutView();
+ }
+
+ @Override
+ public void onEntryRemoved(@Nullable NotificationEntry entry,
+ NotificationVisibility visibility, boolean removedByUser) {
+ updateLightsOutView();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index 70cd43a5e17a..f359fe7cfec4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -142,12 +142,6 @@ public interface ShadeController {
void onLaunchAnimationCancelled();
/**
- * When notifications update, give the shade controller a chance to do thing in response to
- * the new data set
- */
- void updateAreThereNotifications();
-
- /**
* Callback to notify the shade controller that a {@link ActivatableNotificationView} has become
* inactive
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 57dcf77b9d6b..6be881669146 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -47,8 +47,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -117,7 +115,6 @@ import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateInterpolator;
import android.widget.DateTimeView;
import com.android.internal.annotations.VisibleForTesting;
@@ -399,6 +396,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final RemoteInputUriController mRemoteInputUriController;
private final Optional<Divider> mDividerOptional;
private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final LightsOutNotifController mLightsOutNotifController;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -704,6 +702,7 @@ public class StatusBar extends SystemUI implements DemoMode,
PluginManager pluginManager,
RemoteInputUriController remoteInputUriController,
Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
SuperStatusBarViewFactory superStatusBarViewFactory) {
super(context);
mFeatureFlags = featureFlags;
@@ -774,7 +773,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mDividerOptional = dividerOptional;
mSuperStatusBarViewFactory = superStatusBarViewFactory;
-
+ mLightsOutNotifController = lightsOutNotifController;
mBubbleExpandListener =
(isExpanding, key) -> {
mEntryManager.updateNotifications("onBubbleExpandChanged");
@@ -928,7 +927,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mConfigurationController.addCallback(this);
// set the initial view visibility
- Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
int disabledFlags1 = result.mDisabledFlags1;
int disabledFlags2 = result.mDisabledFlags2;
Dependency.get(InitController.class).addPostInitTask(
@@ -1057,8 +1055,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController, mKeyguardBypassController,
mKeyguardStateController, mWakeUpCoordinator, mCommandQueue);
mHeadsUpAppearanceController.readFrom(oldController);
+
+ mLightsOutNotifController.setLightsOutNotifView(
+ mStatusBarView.findViewById(R.id.notification_lights_out));
mStatusBarWindowViewController.setStatusBarView(mStatusBarView);
- updateAreThereNotifications();
checkBarModes();
}).getFragmentManager()
.beginTransaction()
@@ -1546,38 +1546,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- public void updateAreThereNotifications() {
- if (SPEW) {
- final boolean clearable = hasActiveNotifications() &&
- mNotificationPanel.hasActiveClearableNotifications();
- Log.d(TAG, "updateAreThereNotifications: N=" +
- mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" +
- hasActiveNotifications() + " clearable=" + clearable);
- }
-
- if (mStatusBarView != null) {
- final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
- final boolean showDot = hasActiveNotifications() && !areLightsOn();
- if (showDot != (nlo.getAlpha() == 1.0f)) {
- if (showDot) {
- nlo.setAlpha(0f);
- nlo.setVisibility(View.VISIBLE);
- }
- nlo.animate()
- .alpha(showDot ? 1 : 0)
- .setDuration(showDot ? 750 : 250)
- .setInterpolator(new AccelerateInterpolator(2.0f))
- .setListener(showDot ? null : new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- nlo.setVisibility(View.GONE);
- }
- })
- .start();
- }
- }
- }
-
private void updateReportRejectedTouchVisibility() {
if (mReportRejectedTouch == null) {
return;
@@ -2306,14 +2274,8 @@ public class StatusBar extends SystemUI implements DemoMode,
return;
}
boolean barModeChanged = false;
- final int diff = mAppearance ^ appearance;
if (mAppearance != appearance) {
mAppearance = appearance;
-
- // update low profile
- if ((diff & APPEARANCE_LOW_PROFILE_BARS) != 0) {
- updateAreThereNotifications();
- }
barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
}
mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
@@ -2494,10 +2456,6 @@ public class StatusBar extends SystemUI implements DemoMode,
return mAppImmersive;
}
- private boolean areLightsOn() {
- return 0 == (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
- }
-
public static String viewInfo(View v) {
return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
+ ") " + v.getWidth() + "x" + v.getHeight() + "]";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index 9e0eb3570b59..2364c336b7b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -161,6 +161,7 @@ public class StatusBarModule {
PluginManager pluginManager,
RemoteInputUriController remoteInputUriController,
Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
SuperStatusBarViewFactory superStatusBarViewFactory) {
return new StatusBar(
context,
@@ -230,6 +231,7 @@ public class StatusBarModule {
pluginManager,
remoteInputUriController,
dividerOptional,
+ lightsOutNotifController,
superStatusBarViewFactory);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 02e5ebfe5705..38ff86227733 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -79,7 +79,8 @@ import java.util.ArrayList;
public class StatusBarNotificationPresenter implements NotificationPresenter,
ConfigurationController.ConfigurationListener,
- NotificationRowBinderImpl.BindRowCallback {
+ NotificationRowBinderImpl.BindRowCallback,
+ CommandQueue.Callbacks {
private final LockscreenGestureLogger mLockscreenGestureLogger =
Dependency.get(LockscreenGestureLogger.class);
@@ -185,17 +186,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
Dependency.get(InitController.class).addPostInitTask(() -> {
NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
@Override
- public void onNotificationAdded(NotificationEntry entry) {
- // Recalculate the position of the sliding windows and the titles.
- mShadeController.updateAreThereNotifications();
- }
-
- @Override
- public void onPostEntryUpdated(NotificationEntry entry) {
- mShadeController.updateAreThereNotifications();
- }
-
- @Override
public void onEntryRemoved(
@Nullable NotificationEntry entry,
NotificationVisibility visibility,
@@ -333,7 +323,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
}
}
}
- mShadeController.updateAreThereNotifications();
}
public boolean hasActiveNotifications() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
new file mode 100644
index 000000000000..64c1b510cbf9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 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.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+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.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class LightsOutNotifControllerTest extends SysuiTestCase {
+ private static final int LIGHTS_ON = 0;
+ private static final int LIGHTS_OUT = APPEARANCE_LOW_PROFILE_BARS;
+
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private NotificationData mNotificationData;
+ @Mock private CommandQueue mCommandQueue;
+ @Mock private WindowManager mWindowManager;
+ @Mock private Display mDisplay;
+
+ @Captor private ArgumentCaptor<NotificationEntryListener> mListenerCaptor;
+ @Captor private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksCaptor;
+
+ private View mLightsOutView;
+ private LightsOutNotifController mLightsOutNotifController;
+ private ArrayList<NotificationEntry> mActiveNotifications = new ArrayList<>();
+ private int mDisplayId;
+ private NotificationEntryListener mEntryListener;
+ private CommandQueue.Callbacks mCallbacks;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mDisplayId = mContext.getDisplayId();
+ mLightsOutView = new View(mContext);
+ when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+ when(mNotificationData.getActiveNotifications()).thenReturn(mActiveNotifications);
+ when(mWindowManager.getDefaultDisplay()).thenReturn(mDisplay);
+ when(mDisplay.getDisplayId()).thenReturn(mDisplayId);
+
+ mLightsOutNotifController = new LightsOutNotifController(mWindowManager, mEntryManager,
+ mCommandQueue);
+ mLightsOutNotifController.setLightsOutNotifView(mLightsOutView);
+
+ // Capture the entry listener object so we can simulate events in tests below
+ verify(mEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
+ mEntryListener = checkNotNull(mListenerCaptor.getValue());
+
+ // Capture the callback object so we can simulate callback events in tests below
+ verify(mCommandQueue).addCallback(mCallbacksCaptor.capture());
+ mCallbacks = checkNotNull(mCallbacksCaptor.getValue());
+ }
+
+ @Test
+ public void testAreLightsOut_lightsOut() {
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+ assertTrue(mLightsOutNotifController.areLightsOut());
+ }
+
+ @Test
+ public void testAreLightsOut_lightsOn() {
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_ON /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+ assertFalse(mLightsOutNotifController.areLightsOut());
+ }
+
+ @Test
+ public void testIsShowingDot_visible() {
+ mLightsOutView.setVisibility(View.VISIBLE);
+ mLightsOutView.setAlpha(1.0f);
+ assertTrue(mLightsOutNotifController.isShowingDot());
+ }
+
+ @Test
+ public void testIsShowingDot_gone() {
+ mLightsOutView.setVisibility(View.GONE);
+ mLightsOutView.setAlpha(0f);
+ assertFalse(mLightsOutNotifController.isShowingDot());
+ }
+
+ @Test
+ public void testLightsOut_withNotifs_onSystemBarAppearanceChanged() {
+ // GIVEN active visible notifications
+ mActiveNotifications.add(mock(NotificationEntry.class));
+
+ // WHEN lights out
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we should show dot
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(true);
+ }
+
+ @Test
+ public void testLightsOut_withoutNotifs_onSystemBarAppearanceChanged() {
+ // GIVEN no active visible notifications
+ mActiveNotifications.clear();
+
+ // WHEN lights out
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we shouldn't show the dot
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testLightsOn_afterLightsOut_onSystemBarAppearanceChanged() {
+ // GIVEN active visible notifications
+ mActiveNotifications.add(mock(NotificationEntry.class));
+
+ // WHEN lights on
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_ON /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we shouldn't show the dot
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testEntryAdded() {
+ // GIVEN no visible notifications and lights out
+ mActiveNotifications.clear();
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(false);
+
+ // WHEN an active notification is added
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onNotificationAdded(mock(NotificationEntry.class));
+
+ // THEN we should see the dot view
+ assertIsShowingDot(true);
+ }
+
+ @Test
+ public void testEntryRemoved() {
+ // GIVEN a visible notification and lights out
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(true);
+
+ // WHEN all active notifications are removed
+ mActiveNotifications.clear();
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onEntryRemoved(mock(NotificationEntry.class), null, false);
+
+ // THEN we shouldn't see the dot view
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testEntryUpdated() {
+ // GIVEN no visible notifications and lights out
+ mActiveNotifications.clear();
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(false);
+
+ // WHEN an active notification is added
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onPostEntryUpdated(mock(NotificationEntry.class));
+
+ // THEN we should see the dot view
+ assertIsShowingDot(true);
+ }
+
+ private void assertIsShowingDot(boolean isShowing) {
+ // cancel the animation so we can check the end state
+ final ViewPropertyAnimator animation = mLightsOutView.animate();
+ if (animation != null) {
+ animation.cancel();
+ }
+
+ if (isShowing) {
+ assertTrue(mLightsOutNotifController.isShowingDot());
+ } else {
+ assertFalse(mLightsOutNotifController.isShowingDot());
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 1db926dfd196..7d6f006eb833 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -237,6 +237,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private PluginManager mPluginManager;
@Mock private Divider mDivider;
@Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock private LightsOutNotifController mLightsOutNotifController;
@Before
public void setup() throws Exception {
@@ -376,6 +377,7 @@ public class StatusBarTest extends SysuiTestCase {
mPluginManager,
mRemoteInputUriController,
Optional.of(mDivider),
+ mLightsOutNotifController,
mSuperStatusBarViewFactory);
when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(