Merge "Allow HUNs to be shown over Overlay Window." into rvc-dev am: 4785a0669a

Change-Id: I8cd1bc2b48594667867e70d1e0d84071f2350a6e
This commit is contained in:
Abhijoy Saha
2020-05-07 00:32:06 +00:00
committed by Automerger Merge Worker
11 changed files with 646 additions and 203 deletions

View File

@@ -73,7 +73,7 @@ public class CarNavigationBarController {
} }
/** /**
* Hides all navigation bars. * Hides all system bars.
*/ */
public void hideBars() { public void hideBars() {
if (mTopView != null) { if (mTopView != null) {
@@ -85,7 +85,7 @@ public class CarNavigationBarController {
} }
/** /**
* Shows all navigation bars. * Shows all system bars.
*/ */
public void showBars() { public void showBars() {
if (mTopView != null) { if (mTopView != null) {

View File

@@ -29,41 +29,40 @@ import android.widget.FrameLayout;
import com.android.car.notification.R; import com.android.car.notification.R;
import com.android.car.notification.headsup.CarHeadsUpNotificationContainer; import com.android.car.notification.headsup.CarHeadsUpNotificationContainer;
import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Lazy;
/** /**
* A controller for SysUI's HUN display. * A controller for SysUI's HUN display.
*/ */
@Singleton @Singleton
public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotificationContainer { public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotificationContainer {
private final CarDeviceProvisionedController mCarDeviceProvisionedController; private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy; private final OverlayViewGlobalStateController mOverlayViewGlobalStateController;
private final ViewGroup mWindow; private final ViewGroup mWindow;
private final FrameLayout mHeadsUpContentFrame; private final FrameLayout mHeadsUpContentFrame;
private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
@Inject @Inject
CarHeadsUpNotificationSystemContainer(Context context, CarHeadsUpNotificationSystemContainer(Context context,
@Main Resources resources, @Main Resources resources,
CarDeviceProvisionedController deviceProvisionedController, CarDeviceProvisionedController deviceProvisionedController,
WindowManager windowManager, WindowManager windowManager,
Lazy<NotificationPanelViewController> notificationPanelViewControllerLazy) { OverlayViewGlobalStateController overlayViewGlobalStateController) {
mCarDeviceProvisionedController = deviceProvisionedController; mCarDeviceProvisionedController = deviceProvisionedController;
mNotificationPanelViewControllerLazy = notificationPanelViewControllerLazy; mOverlayViewGlobalStateController = overlayViewGlobalStateController;
boolean showOnBottom = resources.getBoolean(R.bool.config_showHeadsUpNotificationOnBottom); boolean showOnBottom = resources.getBoolean(R.bool.config_showHeadsUpNotificationOnBottom);
// Use TYPE_STATUS_BAR_SUB_PANEL window type since we need to find a window that is above
// status bar but below navigation bar.
WindowManager.LayoutParams lp = new WindowManager.LayoutParams( WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT); PixelFormat.TRANSLUCENT);
@@ -78,15 +77,11 @@ public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotifica
windowManager.addView(mWindow, lp); windowManager.addView(mWindow, lp);
mWindow.setVisibility(View.INVISIBLE); mWindow.setVisibility(View.INVISIBLE);
mHeadsUpContentFrame = mWindow.findViewById(R.id.headsup_content); mHeadsUpContentFrame = mWindow.findViewById(R.id.headsup_content);
mEnableHeadsUpNotificationWhenNotificationShadeOpen = resources.getBoolean(
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen);
} }
private void animateShow() { private void animateShow() {
if ((mEnableHeadsUpNotificationWhenNotificationShadeOpen if (mCarDeviceProvisionedController.isCurrentUserFullySetup()
|| !mNotificationPanelViewControllerLazy.get().isPanelExpanded()) && mOverlayViewGlobalStateController.shouldShowHUN()) {
&& mCarDeviceProvisionedController.isCurrentUserFullySetup()) {
mWindow.setVisibility(View.VISIBLE); mWindow.setVisibility(View.VISIBLE);
} }
} }

View File

@@ -73,6 +73,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
private final CarNotificationListener mCarNotificationListener; private final CarNotificationListener mCarNotificationListener;
private final NotificationClickHandlerFactory mNotificationClickHandlerFactory; private final NotificationClickHandlerFactory mNotificationClickHandlerFactory;
private final StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
private float mInitialBackgroundAlpha; private float mInitialBackgroundAlpha;
private float mBackgroundAlphaDiff; private float mBackgroundAlphaDiff;
@@ -144,6 +145,10 @@ public class NotificationPanelViewController extends OverlayPanelViewController
+ " percentage"); + " percentage");
} }
mBackgroundAlphaDiff = finalBackgroundAlpha - mInitialBackgroundAlpha; mBackgroundAlphaDiff = finalBackgroundAlpha - mInitialBackgroundAlpha;
mEnableHeadsUpNotificationWhenNotificationShadeOpen = mResources.getBoolean(
com.android.car.notification.R.bool
.config_enableHeadsUpNotificationWhenNotificationShadeOpen);
} }
@Override @Override
@@ -151,6 +156,16 @@ public class NotificationPanelViewController extends OverlayPanelViewController
reinflate(); reinflate();
} }
@Override
protected boolean shouldShowNavigationBar() {
return true;
}
@Override
protected boolean shouldShowHUN() {
return mEnableHeadsUpNotificationWhenNotificationShadeOpen;
}
/** Reinflates the view. */ /** Reinflates the view. */
public void reinflate() { public void reinflate() {
ViewGroup container = (ViewGroup) getLayout(); ViewGroup container = (ViewGroup) getLayout();

View File

@@ -375,10 +375,10 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
} }
if (visible && !getOverlayViewGlobalStateController().isWindowVisible()) { if (visible && !getOverlayViewGlobalStateController().isWindowVisible()) {
getOverlayViewGlobalStateController().setWindowVisible(true); getOverlayViewGlobalStateController().showView(/* panelViewController= */ this);
} }
if (!visible && getOverlayViewGlobalStateController().isWindowVisible()) { if (!visible && getOverlayViewGlobalStateController().isWindowVisible()) {
getOverlayViewGlobalStateController().setWindowVisible(false); getOverlayViewGlobalStateController().hideView(/* panelViewController= */ this);
} }
getLayout().setVisibility(visible ? View.VISIBLE : View.INVISIBLE); getLayout().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
getOverlayViewGlobalStateController().setWindowFocusable(visible); getOverlayViewGlobalStateController().setWindowFocusable(visible);

View File

@@ -54,7 +54,6 @@ public class OverlayViewController {
mOverlayViewGlobalStateController.hideView(/* viewController= */ this, this::hide); mOverlayViewGlobalStateController.hideView(/* viewController= */ this, this::hide);
} }
/** /**
* Inflate layout owned by controller. * Inflate layout owned by controller.
*/ */
@@ -72,7 +71,7 @@ public class OverlayViewController {
} }
/** /**
* Returns [@code true} if layout owned by controller has been inflated. * Returns {@code true} if layout owned by controller has been inflated.
*/ */
public final boolean isInflated() { public final boolean isInflated() {
return mLayout != null; return mLayout != null;
@@ -125,4 +124,18 @@ public class OverlayViewController {
protected final OverlayViewGlobalStateController getOverlayViewGlobalStateController() { protected final OverlayViewGlobalStateController getOverlayViewGlobalStateController() {
return mOverlayViewGlobalStateController; return mOverlayViewGlobalStateController;
} }
/**
* Returns {@code true} if heads up notifications should be displayed over this view.
*/
protected boolean shouldShowHUN() {
return true;
}
/**
* Returns {@code true} if navigation bar should be displayed over this view.
*/
protected boolean shouldShowNavigationBar() {
return false;
}
} }

View File

@@ -16,14 +16,17 @@
package com.android.systemui.car.window; package com.android.systemui.car.window;
import android.annotation.Nullable;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.navigationbar.CarNavigationBarController;
import java.util.HashSet; import java.util.HashMap;
import java.util.Set; import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -39,11 +42,17 @@ import javax.inject.Singleton;
*/ */
@Singleton @Singleton
public class OverlayViewGlobalStateController { public class OverlayViewGlobalStateController {
private static final boolean DEBUG = false;
private static final String TAG = OverlayViewGlobalStateController.class.getSimpleName(); private static final String TAG = OverlayViewGlobalStateController.class.getSimpleName();
private static final int UNKNOWN_Z_ORDER = -1;
private final SystemUIOverlayWindowController mSystemUIOverlayWindowController; private final SystemUIOverlayWindowController mSystemUIOverlayWindowController;
private final CarNavigationBarController mCarNavigationBarController; private final CarNavigationBarController mCarNavigationBarController;
@VisibleForTesting @VisibleForTesting
Set<String> mShownSet; Map<OverlayViewController, Integer> mZOrderMap;
@VisibleForTesting
SortedMap<Integer, OverlayViewController> mZOrderVisibleSortedMap;
@VisibleForTesting
OverlayViewController mHighestZOrder;
@Inject @Inject
public OverlayViewGlobalStateController( public OverlayViewGlobalStateController(
@@ -52,7 +61,8 @@ public class OverlayViewGlobalStateController {
mSystemUIOverlayWindowController = systemUIOverlayWindowController; mSystemUIOverlayWindowController = systemUIOverlayWindowController;
mSystemUIOverlayWindowController.attach(); mSystemUIOverlayWindowController.attach();
mCarNavigationBarController = carNavigationBarController; mCarNavigationBarController = carNavigationBarController;
mShownSet = new HashSet<>(); mZOrderMap = new HashMap<>();
mZOrderVisibleSortedMap = new TreeMap<>();
} }
/** /**
@@ -66,51 +76,127 @@ public class OverlayViewGlobalStateController {
} }
/** /**
* Show content in Overlay Window. * Show content in Overlay Window using {@link OverlayPanelViewController}.
*
* This calls {@link OverlayViewGlobalStateController#showView(OverlayViewController, Runnable)}
* where the runnable is nullified since the actual showing of the panel is handled by the
* controller itself.
*/ */
public void showView(OverlayViewController viewController, Runnable show) { public void showView(OverlayPanelViewController panelViewController) {
if (mShownSet.isEmpty()) { showView(panelViewController, /* show= */ null);
mCarNavigationBarController.hideBars();
setWindowVisible(true);
}
inflateView(viewController);
show.run();
mShownSet.add(viewController.getClass().getName());
Log.d(TAG, "Content shown: " + viewController.getClass().getName());
} }
/** /**
* Hide content in Overlay Window. * Show content in Overlay Window using {@link OverlayViewController}.
*/ */
public void hideView(OverlayViewController viewController, Runnable hide) { public void showView(OverlayViewController viewController, @Nullable Runnable show) {
debugLog();
if (mZOrderVisibleSortedMap.isEmpty()) {
setWindowVisible(true);
}
if (!(viewController instanceof OverlayPanelViewController)) {
inflateView(viewController);
}
if (show != null) {
show.run();
}
updateInternalsWhenShowingView(viewController);
refreshNavigationBarVisibility();
Log.d(TAG, "Content shown: " + viewController.getClass().getName());
debugLog();
}
private void updateInternalsWhenShowingView(OverlayViewController viewController) {
int zOrder;
if (mZOrderMap.containsKey(viewController)) {
zOrder = mZOrderMap.get(viewController);
} else {
zOrder = mSystemUIOverlayWindowController.getBaseLayout().indexOfChild(
viewController.getLayout());
mZOrderMap.put(viewController, zOrder);
}
mZOrderVisibleSortedMap.put(zOrder, viewController);
refreshHighestZOrderWhenShowingView(viewController);
}
private void refreshHighestZOrderWhenShowingView(OverlayViewController viewController) {
if (mZOrderMap.getOrDefault(mHighestZOrder, UNKNOWN_Z_ORDER) < mZOrderMap.get(
viewController)) {
mHighestZOrder = viewController;
}
}
/**
* Hide content in Overlay Window using {@link OverlayPanelViewController}.
*
* This calls {@link OverlayViewGlobalStateController#hideView(OverlayViewController, Runnable)}
* where the runnable is nullified since the actual hiding of the panel is handled by the
* controller itself.
*/
public void hideView(OverlayPanelViewController panelViewController) {
hideView(panelViewController, /* hide= */ null);
}
/**
* Hide content in Overlay Window using {@link OverlayViewController}.
*/
public void hideView(OverlayViewController viewController, @Nullable Runnable hide) {
debugLog();
if (!viewController.isInflated()) { if (!viewController.isInflated()) {
Log.d(TAG, "Content cannot be hidden since it isn't inflated: " Log.d(TAG, "Content cannot be hidden since it isn't inflated: "
+ viewController.getClass().getName()); + viewController.getClass().getName());
return; return;
} }
if (!mShownSet.contains(viewController.getClass().getName())) { if (!mZOrderMap.containsKey(viewController)) {
Log.d(TAG, "Content cannot be hidden since it isn't shown: " Log.d(TAG, "Content cannot be hidden since it has never been shown: "
+ viewController.getClass().getName());
return;
}
if (!mZOrderVisibleSortedMap.containsKey(mZOrderMap.get(viewController))) {
Log.d(TAG, "Content cannot be hidden since it isn't currently shown: "
+ viewController.getClass().getName()); + viewController.getClass().getName());
return; return;
} }
hide.run(); if (hide != null) {
mShownSet.remove(viewController.getClass().getName()); hide.run();
}
if (mShownSet.isEmpty()) { mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
mCarNavigationBarController.showBars(); refreshHighestZOrderWhenHidingView(viewController);
refreshNavigationBarVisibility();
if (mZOrderVisibleSortedMap.isEmpty()) {
setWindowVisible(false); setWindowVisible(false);
} }
Log.d(TAG, "Content hidden: " + viewController.getClass().getName()); Log.d(TAG, "Content hidden: " + viewController.getClass().getName());
debugLog();
} }
/** Sets the window visibility state. */ private void refreshHighestZOrderWhenHidingView(OverlayViewController viewController) {
public void setWindowVisible(boolean expanded) { if (mZOrderVisibleSortedMap.isEmpty()) {
mSystemUIOverlayWindowController.setWindowVisible(expanded); mHighestZOrder = null;
return;
}
if (!mHighestZOrder.equals(viewController)) {
return;
}
mHighestZOrder = mZOrderVisibleSortedMap.get(mZOrderVisibleSortedMap.lastKey());
}
private void refreshNavigationBarVisibility() {
if (mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowNavigationBar()) {
mCarNavigationBarController.showBars();
} else {
mCarNavigationBarController.hideBars();
}
} }
/** Returns {@code true} is the window is visible. */ /** Returns {@code true} is the window is visible. */
@@ -118,13 +204,14 @@ public class OverlayViewGlobalStateController {
return mSystemUIOverlayWindowController.isWindowVisible(); return mSystemUIOverlayWindowController.isWindowVisible();
} }
/** Sets the focusable flag of the sysui overlawy window. */ private void setWindowVisible(boolean visible) {
public void setWindowFocusable(boolean focusable) { mSystemUIOverlayWindowController.setWindowVisible(visible);
mSystemUIOverlayWindowController.setWindowFocusable(focusable);
} }
/** Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the /**
* sysui overlay window */ * Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the
* sysui overlay window.
*/
public void setWindowNeedsInput(boolean needsInput) { public void setWindowNeedsInput(boolean needsInput) {
mSystemUIOverlayWindowController.setWindowNeedsInput(needsInput); mSystemUIOverlayWindowController.setWindowNeedsInput(needsInput);
} }
@@ -134,10 +221,34 @@ public class OverlayViewGlobalStateController {
return mSystemUIOverlayWindowController.isWindowFocusable(); return mSystemUIOverlayWindowController.isWindowFocusable();
} }
/** Sets the focusable flag of the sysui overlawy window. */
public void setWindowFocusable(boolean focusable) {
mSystemUIOverlayWindowController.setWindowFocusable(focusable);
}
/** Inflates the view controlled by the given view controller. */ /** Inflates the view controlled by the given view controller. */
public void inflateView(OverlayViewController viewController) { public void inflateView(OverlayViewController viewController) {
if (!viewController.isInflated()) { if (!viewController.isInflated()) {
viewController.inflate(mSystemUIOverlayWindowController.getBaseLayout()); viewController.inflate(mSystemUIOverlayWindowController.getBaseLayout());
} }
} }
/**
* Return {@code true} if OverlayWindow is in a state where HUNs should be displayed above it.
*/
public boolean shouldShowHUN() {
return mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowHUN();
}
private void debugLog() {
if (!DEBUG) {
return;
}
Log.d(TAG, "mHighestZOrder: " + mHighestZOrder);
Log.d(TAG, "mZOrderVisibleSortedMap.size(): " + mZOrderVisibleSortedMap.size());
Log.d(TAG, "mZOrderVisibleSortedMap: " + mZOrderVisibleSortedMap);
Log.d(TAG, "mZOrderMap.size(): " + mZOrderMap.size());
Log.d(TAG, "mZOrderMap: " + mZOrderMap);
}
} }

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 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.
-->
<!-- Fullscreen views in sysui should be listed here in increasing Z order. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewStub android:id="@+id/overlay_view_controller_stub_1"
android:inflatedId="@+id/overlay_view_controller_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/overlay_view_controller_stub"/>
<ViewStub android:id="@+id/overlay_view_controller_stub_2"
android:inflatedId="@+id/overlay_view_controller_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/overlay_view_controller_stub"/>
<ViewStub android:id="@+id/overlay_view_controller_stub_3"
android:inflatedId="@+id/overlay_view_controller_3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/overlay_view_controller_stub"/>
</FrameLayout>

View File

@@ -16,9 +16,10 @@
package com.android.systemui.car.keyguard; package com.android.systemui.car.keyguard;
import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -29,7 +30,6 @@ import android.os.Handler;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
@@ -40,7 +40,6 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.car.window.OverlayViewGlobalStateController; import com.android.systemui.car.window.OverlayViewGlobalStateController;
import com.android.systemui.car.window.SystemUIOverlayWindowController;
import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.BiometricUnlockController;
@@ -51,6 +50,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -61,28 +61,20 @@ import dagger.Lazy;
public class CarKeyguardViewControllerTest extends SysuiTestCase { public class CarKeyguardViewControllerTest extends SysuiTestCase {
private TestableCarKeyguardViewController mCarKeyguardViewController; private TestableCarKeyguardViewController mCarKeyguardViewController;
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
private ViewGroup mBaseLayout;
@Mock
private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
@Mock @Mock
private KeyguardBouncer mBouncer; private KeyguardBouncer mBouncer;
@Mock @Mock
private CarNavigationBarController mCarNavigationBarController; private CarNavigationBarController mCarNavigationBarController;
@Mock @Mock
private SystemUIOverlayWindowController mSystemUIOverlayWindowController;
@Mock
private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener; private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mOverlayViewGlobalStateController = new OverlayViewGlobalStateController(
mCarNavigationBarController, mSystemUIOverlayWindowController);
mBaseLayout = (ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.sysui_overlay_window, /* root= */ null);
when(mSystemUIOverlayWindowController.getBaseLayout()).thenReturn(mBaseLayout);
mCarKeyguardViewController = new TestableCarKeyguardViewController( mCarKeyguardViewController = new TestableCarKeyguardViewController(
mContext, mContext,
Handler.getMain(), Handler.getMain(),
@@ -98,6 +90,8 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
mock(FalsingManager.class), mock(FalsingManager.class),
() -> mock(KeyguardBypassController.class) () -> mock(KeyguardBypassController.class)
); );
mCarKeyguardViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.sysui_overlay_window, /* root= */ null));
} }
@Test @Test
@@ -113,8 +107,7 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
when(mBouncer.isSecure()).thenReturn(true); when(mBouncer.isSecure()).thenReturn(true);
mCarKeyguardViewController.show(/* options= */ null); mCarKeyguardViewController.show(/* options= */ null);
assertThat(mBaseLayout.findViewById(R.id.keyguard_container).getVisibility()).isEqualTo( verify(mOverlayViewGlobalStateController).showView(eq(mCarKeyguardViewController), any());
View.VISIBLE);
} }
@Test @Test
@@ -130,8 +123,17 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
when(mBouncer.isSecure()).thenReturn(false); when(mBouncer.isSecure()).thenReturn(false);
mCarKeyguardViewController.show(/* options= */ null); mCarKeyguardViewController.show(/* options= */ null);
assertThat(mBaseLayout.findViewById(R.id.keyguard_container).getVisibility()).isEqualTo( // Here we check for both showView and hideView since the current implementation of show
View.GONE); // with bouncer being not secure has the following method execution orders:
// 1) show -> start -> showView
// 2) show -> reset -> dismissAndCollapse -> hide -> stop -> hideView
// Hence, we want to make sure that showView is called before hideView and not in any
// other combination.
InOrder inOrder = inOrder(mOverlayViewGlobalStateController);
inOrder.verify(mOverlayViewGlobalStateController).showView(eq(mCarKeyguardViewController),
any());
inOrder.verify(mOverlayViewGlobalStateController).hideView(eq(mCarKeyguardViewController),
any());
} }
@Test @Test
@@ -156,8 +158,11 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
mCarKeyguardViewController.show(/* options= */ null); mCarKeyguardViewController.show(/* options= */ null);
mCarKeyguardViewController.hide(/* startTime= */ 0, /* fadeoutDelay= */ 0); mCarKeyguardViewController.hide(/* startTime= */ 0, /* fadeoutDelay= */ 0);
assertThat(mBaseLayout.findViewById(R.id.keyguard_container).getVisibility()).isEqualTo( InOrder inOrder = inOrder(mOverlayViewGlobalStateController);
View.GONE); inOrder.verify(mOverlayViewGlobalStateController).showView(eq(mCarKeyguardViewController),
any());
inOrder.verify(mOverlayViewGlobalStateController).hideView(eq(mCarKeyguardViewController),
any());
} }
@Test @Test

View File

@@ -28,9 +28,9 @@ import android.view.WindowManager;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.window.OverlayViewGlobalStateController;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -42,12 +42,11 @@ import org.mockito.MockitoAnnotations;
@TestableLooper.RunWithLooper @TestableLooper.RunWithLooper
@SmallTest @SmallTest
public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase { public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase {
private CarHeadsUpNotificationSystemContainer mDefaultController; private CarHeadsUpNotificationSystemContainer mCarHeadsUpNotificationSystemContainer;
private CarHeadsUpNotificationSystemContainer mOverrideEnabledController;
@Mock @Mock
private CarDeviceProvisionedController mCarDeviceProvisionedController; private CarDeviceProvisionedController mCarDeviceProvisionedController;
@Mock @Mock
private NotificationPanelViewController mNotificationPanelViewController; private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
@Mock @Mock
private WindowManager mWindowManager; private WindowManager mWindowManager;
@@ -58,76 +57,63 @@ public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(/* testClass= */this);
when(mNotificationPanelViewController.isPanelExpanded()).thenReturn(false); when(mOverlayViewGlobalStateController.shouldShowHUN()).thenReturn(true);
when(mCarDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true); when(mCarDeviceProvisionedController.isCurrentUserFullySetup()).thenReturn(true);
when(mCarDeviceProvisionedController.isCurrentUserSetupInProgress()).thenReturn(false);
TestableResources testableResources = mContext.getOrCreateTestableResources(); TestableResources testableResources = mContext.getOrCreateTestableResources();
testableResources.addOverride( mCarHeadsUpNotificationSystemContainer = new CarHeadsUpNotificationSystemContainer(mContext,
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen, false);
mDefaultController = new CarHeadsUpNotificationSystemContainer(mContext,
testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager, testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager,
() -> mNotificationPanelViewController); mOverlayViewGlobalStateController);
testableResources.addOverride(
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen, true);
mOverrideEnabledController = new CarHeadsUpNotificationSystemContainer(mContext,
testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager,
() -> mNotificationPanelViewController);
} }
@Test @Test
public void testDisplayNotification_firstNotification_isVisible() { public void testDisplayNotification_firstNotification_isVisible() {
mDefaultController.displayNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
assertThat(mDefaultController.isVisible()).isTrue(); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
} }
@Test @Test
public void testRemoveNotification_lastNotification_isInvisible() { public void testRemoveNotification_lastNotification_isInvisible() {
mDefaultController.displayNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
mDefaultController.removeNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.removeNotification(mNotificationView);
assertThat(mDefaultController.isVisible()).isFalse(); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
} }
@Test @Test
public void testRemoveNotification_nonLastNotification_isVisible() { public void testRemoveNotification_nonLastNotification_isVisible() {
mDefaultController.displayNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
mDefaultController.displayNotification(mNotificationView2); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView2);
mDefaultController.removeNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.removeNotification(mNotificationView);
assertThat(mDefaultController.isVisible()).isTrue(); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
} }
@Test @Test
public void testDisplayNotification_userSetupInProgress_isInvisible() { public void testDisplayNotification_userFullySetupTrue_isInvisible() {
when(mCarDeviceProvisionedController.isCurrentUserSetupInProgress()).thenReturn(true); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
mDefaultController.displayNotification(mNotificationView); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
assertThat(mDefaultController.isVisible()).isFalse();
} }
@Test @Test
public void testDisplayNotification_userSetupIncomplete_isInvisible() { public void testDisplayNotification_userFullySetupFalse_isInvisible() {
when(mCarDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false); when(mCarDeviceProvisionedController.isCurrentUserFullySetup()).thenReturn(false);
mDefaultController.displayNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
assertThat(mDefaultController.isVisible()).isFalse(); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
} }
@Test @Test
public void testDisplayNotification_notificationPanelExpanded_isInvisible() { public void testDisplayNotification_overlayWindowStateShouldShowHUNFalse_isInvisible() {
when(mNotificationPanelViewController.isPanelExpanded()).thenReturn(true); when(mOverlayViewGlobalStateController.shouldShowHUN()).thenReturn(false);
mDefaultController.displayNotification(mNotificationView); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
assertThat(mDefaultController.isVisible()).isFalse(); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isFalse();
} }
@Test @Test
public void testDisplayNotification_notificationPanelExpandedEnabledHUNWhenOpen_isVisible() { public void testDisplayNotification_overlayWindowStateShouldShowHUNTrue_isVisible() {
when(mNotificationPanelViewController.isPanelExpanded()).thenReturn(true); mCarHeadsUpNotificationSystemContainer.displayNotification(mNotificationView);
mOverrideEnabledController.displayNotification(mNotificationView); assertThat(mCarHeadsUpNotificationSystemContainer.isVisible()).isTrue();
assertThat(mOverrideEnabledController.isVisible()).isTrue();
} }
} }

View File

@@ -339,7 +339,7 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
mOverlayPanelViewController.setPanelVisible(true); mOverlayPanelViewController.setPanelVisible(true);
verify(mOverlayViewGlobalStateController).setWindowVisible(true); verify(mOverlayViewGlobalStateController).showView(mOverlayPanelViewController);
} }
@Test @Test
@@ -349,7 +349,7 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
mOverlayPanelViewController.setPanelVisible(true); mOverlayPanelViewController.setPanelVisible(true);
verify(mOverlayViewGlobalStateController, never()).setWindowVisible(true); verify(mOverlayViewGlobalStateController, never()).showView(mOverlayPanelViewController);
} }
@Test @Test
@@ -377,7 +377,7 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
mOverlayPanelViewController.setPanelVisible(false); mOverlayPanelViewController.setPanelVisible(false);
verify(mOverlayViewGlobalStateController).setWindowVisible(false); verify(mOverlayViewGlobalStateController).hideView(mOverlayPanelViewController);
} }
@Test @Test
@@ -387,7 +387,7 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
mOverlayPanelViewController.setPanelVisible(false); mOverlayPanelViewController.setPanelVisible(false);
verify(mOverlayViewGlobalStateController, never()).setWindowVisible(false); verify(mOverlayViewGlobalStateController, never()).hideView(mOverlayPanelViewController);
} }
@Test @Test
@@ -428,10 +428,6 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
private static class TestOverlayPanelViewController extends OverlayPanelViewController { private static class TestOverlayPanelViewController extends OverlayPanelViewController {
private boolean mShouldAnimateCollapsePanel;
private boolean mShouldAnimateExpandPanel;
private boolean mShouldAllowClosingScroll;
boolean mOnAnimateCollapsePanelCalled; boolean mOnAnimateCollapsePanelCalled;
boolean mAnimateCollapsePanelCalled; boolean mAnimateCollapsePanelCalled;
boolean mOnAnimateExpandPanelCalled; boolean mOnAnimateExpandPanelCalled;
@@ -440,6 +436,9 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
boolean mOnExpandAnimationEndCalled; boolean mOnExpandAnimationEndCalled;
boolean mOnOpenScrollStartEnd; boolean mOnOpenScrollStartEnd;
List<Integer> mOnScrollHeights; List<Integer> mOnScrollHeights;
private boolean mShouldAnimateCollapsePanel;
private boolean mShouldAnimateExpandPanel;
private boolean mShouldAllowClosingScroll;
TestOverlayPanelViewController( TestOverlayPanelViewController(
Context context, Context context,

View File

@@ -24,25 +24,33 @@ import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.view.ViewStub;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.navigationbar.CarNavigationBarController; import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.tests.R;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.Arrays;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper @TestableLooper.RunWithLooper
@SmallTest @SmallTest
public class OverlayViewGlobalStateControllerTest extends SysuiTestCase { public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
private static final String MOCK_OVERLAY_VIEW_CONTROLLER_NAME = "OverlayViewController"; private static final int OVERLAY_VIEW_CONTROLLER_1_Z_ORDER = 0;
private static final int OVERLAY_VIEW_CONTROLLER_2_Z_ORDER = 1;
private static final int OVERLAY_PANEL_VIEW_CONTROLLER_Z_ORDER = 2;
private OverlayViewGlobalStateController mOverlayViewGlobalStateController; private OverlayViewGlobalStateController mOverlayViewGlobalStateController;
private ViewGroup mBaseLayout; private ViewGroup mBaseLayout;
@@ -54,7 +62,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Mock @Mock
private OverlayViewMediator mOverlayViewMediator; private OverlayViewMediator mOverlayViewMediator;
@Mock @Mock
private OverlayViewController mOverlayViewController; private OverlayViewController mOverlayViewController1;
@Mock
private OverlayViewController mOverlayViewController2;
@Mock
private OverlayPanelViewController mOverlayPanelViewController;
@Mock @Mock
private Runnable mRunnable; private Runnable mRunnable;
@@ -62,14 +74,15 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(/* testClass= */ this); MockitoAnnotations.initMocks(/* testClass= */ this);
mBaseLayout = (ViewGroup) LayoutInflater.from(mContext).inflate(
R.layout.overlay_view_global_state_controller_test, /* root= */ null);
when(mSystemUIOverlayWindowController.getBaseLayout()).thenReturn(mBaseLayout);
mOverlayViewGlobalStateController = new OverlayViewGlobalStateController( mOverlayViewGlobalStateController = new OverlayViewGlobalStateController(
mCarNavigationBarController, mSystemUIOverlayWindowController); mCarNavigationBarController, mSystemUIOverlayWindowController);
verify(mSystemUIOverlayWindowController).attach(); verify(mSystemUIOverlayWindowController).attach();
mBaseLayout = new FrameLayout(mContext);
when(mSystemUIOverlayWindowController.getBaseLayout()).thenReturn(mBaseLayout);
} }
@Test @Test
@@ -87,182 +100,445 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
} }
@Test @Test
public void showView_nothingAlreadyShown_navigationBarsHidden() { public void showView_nothingAlreadyShown_shouldShowNavBarFalse_navigationBarsHidden() {
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); setupOverlayViewController1();
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).hideBars(); verify(mCarNavigationBarController).hideBars();
} }
@Test @Test
public void showView_nothingAlreadyShown_windowIsExpanded() { public void showView_nothingAlreadyShown_shouldShowNavBarTrue_navigationBarsShown() {
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); setupOverlayViewController1();
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).showBars();
}
@Test
public void showView_nothingAlreadyShown_windowIsSetVisible() {
setupOverlayViewController1();
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mSystemUIOverlayWindowController).setWindowVisible(true); verify(mSystemUIOverlayWindowController).setWindowVisible(true);
} }
@Test @Test
public void showView_somethingAlreadyShown_navigationBarsHidden() { public void showView_nothingAlreadyShown_newHighestZOrder() {
mOverlayViewGlobalStateController.mShownSet.add(MOCK_OVERLAY_VIEW_CONTROLLER_NAME); setupOverlayViewController1();
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController, never()).hideBars(); assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController1);
} }
@Test @Test
public void showView_somethingAlreadyShown_windowIsExpanded() { public void showView_nothingAlreadyShown_newHighestZOrder_isVisible() {
mOverlayViewGlobalStateController.mShownSet.add(MOCK_OVERLAY_VIEW_CONTROLLER_NAME); setupOverlayViewController1();
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsKey(
OVERLAY_VIEW_CONTROLLER_1_Z_ORDER)).isTrue();
}
@Test
public void showView_newHighestZOrder() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController2);
}
@Test
public void showView_newHighestZOrder_shouldShowNavBarFalse_navigationBarsHidden() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
verify(mCarNavigationBarController).hideBars();
}
@Test
public void showView_newHighestZOrder_shouldShowNavBarTrue_navigationBarsShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
verify(mCarNavigationBarController).showBars();
}
@Test
public void showView_newHighestZOrder_correctViewsShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.keySet().toArray())
.isEqualTo(Arrays.asList(OVERLAY_VIEW_CONTROLLER_1_Z_ORDER,
OVERLAY_VIEW_CONTROLLER_2_Z_ORDER).toArray());
}
@Test
public void showView_oldHighestZOrder() {
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController2);
}
@Test
public void showView_oldHighestZOrder_shouldShowNavBarFalse_navigationBarsHidden() {
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).hideBars();
}
@Test
public void showView_oldHighestZOrder_shouldShowNavBarTrue_navigationBarsShown() {
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).showBars();
}
@Test
public void showView_oldHighestZOrder_correctViewsShown() {
setupOverlayViewController1();
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.keySet().toArray())
.isEqualTo(Arrays.asList(OVERLAY_VIEW_CONTROLLER_1_Z_ORDER,
OVERLAY_VIEW_CONTROLLER_2_Z_ORDER).toArray());
}
@Test
public void showView_somethingAlreadyShown_windowVisibleNotCalled() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
verify(mSystemUIOverlayWindowController, never()).setWindowVisible(true); verify(mSystemUIOverlayWindowController, never()).setWindowVisible(true);
} }
@Test @Test
public void showView_viewControllerNotInflated_inflateViewController() { public void showView_viewControllerNotInflated_inflateViewController() {
when(mOverlayViewController.isInflated()).thenReturn(false); setupOverlayViewController2();
when(mOverlayViewController2.isInflated()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
verify(mOverlayViewController).inflate(mBaseLayout); verify(mOverlayViewController2).inflate(mBaseLayout);
} }
@Test @Test
public void showView_viewControllerInflated_inflateViewControllerNotCalled() { public void showView_viewControllerInflated_inflateViewControllerNotCalled() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController2();
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
verify(mOverlayViewController, never()).inflate(mBaseLayout); verify(mOverlayViewController2, never()).inflate(mBaseLayout);
}
@Test
public void showView_panelViewController_inflateViewControllerNotCalled() {
setupOverlayPanelViewController();
mOverlayViewGlobalStateController.showView(mOverlayPanelViewController, mRunnable);
verify(mOverlayPanelViewController, never()).inflate(mBaseLayout);
verify(mOverlayPanelViewController, never()).isInflated();
} }
@Test @Test
public void showView_showRunnableCalled() { public void showView_showRunnableCalled() {
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable); setupOverlayViewController1();
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
verify(mRunnable).run(); verify(mRunnable).run();
} }
@Test
public void showView_overlayViewControllerAddedToShownSet() {
mOverlayViewGlobalStateController.showView(mOverlayViewController, mRunnable);
assertThat(mOverlayViewGlobalStateController.mShownSet.contains(
mOverlayViewController.getClass().getName())).isTrue();
}
@Test @Test
public void hideView_viewControllerNotInflated_hideRunnableNotCalled() { public void hideView_viewControllerNotInflated_hideRunnableNotCalled() {
when(mOverlayViewController.isInflated()).thenReturn(false); when(mOverlayViewController2.isInflated()).thenReturn(false);
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mRunnable, never()).run(); verify(mRunnable, never()).run();
} }
@Test @Test
public void hideView_nothingShown_hideRunnableNotCalled() { public void hideView_nothingShown_hideRunnableNotCalled() {
when(mOverlayViewController.isInflated()).thenReturn(true); when(mOverlayViewController2.isInflated()).thenReturn(true);
mOverlayViewGlobalStateController.mShownSet.clear(); mOverlayViewGlobalStateController.mZOrderMap.clear();
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mRunnable, never()).run(); verify(mRunnable, never()).run();
} }
@Test @Test
public void hideView_viewControllerNotShown_hideRunnableNotCalled() { public void hideView_viewControllerNotShown_hideRunnableNotCalled() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add(MOCK_OVERLAY_VIEW_CONTROLLER_NAME); setOverlayViewControllerAsShowing(mOverlayViewController1);
when(mOverlayViewController2.isInflated()).thenReturn(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mRunnable, never()).run(); verify(mRunnable, never()).run();
} }
@Test @Test
public void hideView_viewControllerShown_hideRunnableCalled() { public void hideView_viewControllerShown_hideRunnableCalled() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName());
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mRunnable).run(); verify(mRunnable).run();
} }
@Test @Test
public void hideView_viewControllerOnlyShown_nothingShown() { public void hideView_viewControllerOnlyShown_noHighestZOrder() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName());
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mShownSet.isEmpty()).isTrue(); assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isNull();
} }
@Test @Test
public void hideView_viewControllerNotOnlyShown_navigationBarNotShown() { public void hideView_viewControllerOnlyShown_nothingShown() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName());
mOverlayViewGlobalStateController.mShownSet.add(MOCK_OVERLAY_VIEW_CONTROLLER_NAME);
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController, never()).showBars(); assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.isEmpty()).isTrue();
}
@Test
public void hideView_viewControllerOnlyShown_viewControllerNotShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsKey(
OVERLAY_VIEW_CONTROLLER_1_Z_ORDER)).isFalse();
}
@Test
public void hideView_newHighestZOrder_twoViewsShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController1);
}
@Test
public void hideView_newHighestZOrder_threeViewsShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
setupOverlayPanelViewController();
setOverlayViewControllerAsShowing(mOverlayPanelViewController);
mOverlayViewGlobalStateController.hideView(mOverlayPanelViewController, mRunnable);
assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController2);
}
@Test
public void hideView_newHighestZOrder_shouldShowNavBarFalse_navigationBarHidden() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mCarNavigationBarController).hideBars();
}
@Test
public void hideView_newHighestZOrder_shouldShowNavBarTrue_navigationBarShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mCarNavigationBarController).showBars();
}
@Test
public void hideView_oldHighestZOrder() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
assertThat(mOverlayViewGlobalStateController.mHighestZOrder).isEqualTo(
mOverlayViewController2);
}
@Test
public void hideView_oldHighestZOrder_shouldShowNavBarFalse_navigationBarHidden() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).hideBars();
}
@Test
public void hideView_oldHighestZOrder_shouldShowNavBarTrue_navigationBarShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
setOverlayViewControllerAsShowing(mOverlayViewController2);
when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).showBars();
} }
@Test @Test
public void hideView_viewControllerNotOnlyShown_windowNotCollapsed() { public void hideView_viewControllerNotOnlyShown_windowNotCollapsed() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName()); setupOverlayViewController2();
mOverlayViewGlobalStateController.mShownSet.add(MOCK_OVERLAY_VIEW_CONTROLLER_NAME); setOverlayViewControllerAsShowing(mOverlayViewController2);
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
verify(mSystemUIOverlayWindowController, never()).setWindowVisible(false); verify(mSystemUIOverlayWindowController, never()).setWindowVisible(false);
} }
@Test @Test
public void hideView_viewControllerOnlyShown_navigationBarShown() { public void hideView_viewControllerOnlyShown_navigationBarShown() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName());
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mCarNavigationBarController).showBars(); verify(mCarNavigationBarController).showBars();
} }
@Test @Test
public void hideView_viewControllerOnlyShown_windowCollapsed() { public void hideView_viewControllerOnlyShown_windowCollapsed() {
when(mOverlayViewController.isInflated()).thenReturn(true); setupOverlayViewController1();
mOverlayViewGlobalStateController.mShownSet.add( setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewController.getClass().getName());
mOverlayViewGlobalStateController.hideView(mOverlayViewController, mRunnable); mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
verify(mSystemUIOverlayWindowController).setWindowVisible(false); verify(mSystemUIOverlayWindowController).setWindowVisible(false);
} }
@Test @Test
public void inflateView_notInflated_inflates() { public void inflateView_notInflated_inflates() {
when(mOverlayViewController.isInflated()).thenReturn(false); when(mOverlayViewController2.isInflated()).thenReturn(false);
mOverlayViewGlobalStateController.inflateView(mOverlayViewController); mOverlayViewGlobalStateController.inflateView(mOverlayViewController2);
verify(mOverlayViewController).inflate(mBaseLayout); verify(mOverlayViewController2).inflate(mBaseLayout);
} }
@Test @Test
public void inflateView_alreadyInflated_doesNotInflate() { public void inflateView_alreadyInflated_doesNotInflate() {
when(mOverlayViewController.isInflated()).thenReturn(true); when(mOverlayViewController2.isInflated()).thenReturn(true);
mOverlayViewGlobalStateController.inflateView(mOverlayViewController); mOverlayViewGlobalStateController.inflateView(mOverlayViewController2);
verify(mOverlayViewController, never()).inflate(mBaseLayout); verify(mOverlayViewController2, never()).inflate(mBaseLayout);
}
private void setupOverlayViewController1() {
setupOverlayViewController(mOverlayViewController1, R.id.overlay_view_controller_stub_1,
R.id.overlay_view_controller_1);
}
private void setupOverlayViewController2() {
setupOverlayViewController(mOverlayViewController2, R.id.overlay_view_controller_stub_2,
R.id.overlay_view_controller_2);
}
private void setupOverlayPanelViewController() {
setupOverlayViewController(mOverlayPanelViewController, R.id.overlay_view_controller_stub_3,
R.id.overlay_view_controller_3);
}
private void setupOverlayViewController(OverlayViewController overlayViewController,
int stubId, int inflatedId) {
ViewStub viewStub = mBaseLayout.findViewById(stubId);
View layout;
if (viewStub == null) {
layout = mBaseLayout.findViewById(inflatedId);
} else {
layout = viewStub.inflate();
}
when(overlayViewController.getLayout()).thenReturn(layout);
when(overlayViewController.isInflated()).thenReturn(true);
}
private void setOverlayViewControllerAsShowing(OverlayViewController overlayViewController) {
mOverlayViewGlobalStateController.showView(overlayViewController, /* show= */ null);
Mockito.reset(mCarNavigationBarController, mSystemUIOverlayWindowController);
when(mSystemUIOverlayWindowController.getBaseLayout()).thenReturn(mBaseLayout);
} }
} }