LightsOut has its own controller
Apps can request a low profile mode where status bar and navigation icons dim. In this mode, a notification dot appears where the notification icons would appear if they would be there outside of this mode. This CL moves the logic for this dot to its own controller Test: manual (ie: NY times app) Test: atest LightsOutNotifControllerTest Change-Id: I46dfab2c7f83cc26c25c257ee02d84058b127036
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -141,12 +141,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
|
||||
|
||||
@@ -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() + "]";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -184,17 +185,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
|
||||
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,
|
||||
@@ -333,7 +323,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
}
|
||||
}
|
||||
}
|
||||
mShadeController.updateAreThereNotifications();
|
||||
}
|
||||
|
||||
public boolean hasActiveNotifications() {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user