Merge "Add occlusion logic to OverlayViewGlobalStateController and CarKeyguardViewController" into rvc-dev

This commit is contained in:
TreeHugger Robot 2020-06-03 04:12:06 +00:00 committed by Android (Google) Code Review
commit 8920f765c9
5 changed files with 159 additions and 5 deletions

View File

@ -218,6 +218,14 @@ public class CarKeyguardViewController extends OverlayViewController implements
}
}
@Override
public void setOccluded(boolean occluded, boolean animate) {
getOverlayViewGlobalStateController().setOccluded(occluded);
if (!occluded) {
reset(/* hideBouncerWhenShowing= */ false);
}
}
@Override
public void onCancelClicked() {
if (mBouncer == null) return;
@ -314,11 +322,6 @@ public class CarKeyguardViewController extends OverlayViewController implements
// no-op
}
@Override
public void setOccluded(boolean occluded, boolean animate) {
// no-op
}
@Override
public boolean shouldDisableWindowAnimationsForUnlock() {
return false;

View File

@ -138,4 +138,11 @@ public class OverlayViewController {
protected boolean shouldShowNavigationBar() {
return false;
}
/**
* Returns {@code true} if this view should be hidden during the occluded state.
*/
protected boolean shouldShowWhenOccluded() {
return false;
}
}

View File

@ -24,7 +24,9 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@ -47,11 +49,16 @@ public class OverlayViewGlobalStateController {
private static final int UNKNOWN_Z_ORDER = -1;
private final SystemUIOverlayWindowController mSystemUIOverlayWindowController;
private final CarNavigationBarController mCarNavigationBarController;
private boolean mIsOccluded;
@VisibleForTesting
Map<OverlayViewController, Integer> mZOrderMap;
@VisibleForTesting
SortedMap<Integer, OverlayViewController> mZOrderVisibleSortedMap;
@VisibleForTesting
Set<OverlayViewController> mViewsHiddenForOcclusion;
@VisibleForTesting
OverlayViewController mHighestZOrder;
@Inject
@ -63,6 +70,7 @@ public class OverlayViewGlobalStateController {
mCarNavigationBarController = carNavigationBarController;
mZOrderMap = new HashMap<>();
mZOrderVisibleSortedMap = new TreeMap<>();
mViewsHiddenForOcclusion = new HashSet<>();
}
/**
@ -91,6 +99,10 @@ public class OverlayViewGlobalStateController {
*/
public void showView(OverlayViewController viewController, @Nullable Runnable show) {
debugLog();
if (mIsOccluded && !viewController.shouldShowWhenOccluded()) {
mViewsHiddenForOcclusion.add(viewController);
return;
}
if (mZOrderVisibleSortedMap.isEmpty()) {
setWindowVisible(true);
}
@ -147,6 +159,10 @@ public class OverlayViewGlobalStateController {
*/
public void hideView(OverlayViewController viewController, @Nullable Runnable hide) {
debugLog();
if (mIsOccluded && mViewsHiddenForOcclusion.contains(viewController)) {
mViewsHiddenForOcclusion.remove(viewController);
return;
}
if (!viewController.isInflated()) {
Log.d(TAG, "Content cannot be hidden since it isn't inflated: "
+ viewController.getClass().getName());
@ -240,6 +256,43 @@ public class OverlayViewGlobalStateController {
return mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowHUN();
}
/**
* Set the OverlayViewWindow to be in occluded or unoccluded state. When OverlayViewWindow is
* occluded, all views mounted to it that are not configured to be shown during occlusion will
* be hidden.
*/
public void setOccluded(boolean occluded) {
if (occluded) {
// Hide views before setting mIsOccluded to true so the regular hideView logic is used,
// not the one used during occlusion.
hideViewsForOcclusion();
mIsOccluded = true;
} else {
mIsOccluded = false;
// show views after setting mIsOccluded to false so the regular showView logic is used,
// not the one used during occlusion.
showViewsHiddenForOcclusion();
}
}
private void hideViewsForOcclusion() {
HashSet<OverlayViewController> viewsCurrentlyShowing = new HashSet<>(
mZOrderVisibleSortedMap.values());
viewsCurrentlyShowing.forEach(overlayController -> {
if (!overlayController.shouldShowWhenOccluded()) {
hideView(overlayController, overlayController::hideInternal);
mViewsHiddenForOcclusion.add(overlayController);
}
});
}
private void showViewsHiddenForOcclusion() {
mViewsHiddenForOcclusion.forEach(overlayViewController -> {
showView(overlayViewController, overlayViewController::showInternal);
});
mViewsHiddenForOcclusion.clear();
}
private void debugLog() {
if (!DEBUG) {
return;
@ -250,5 +303,8 @@ public class OverlayViewGlobalStateController {
Log.d(TAG, "mZOrderVisibleSortedMap: " + mZOrderVisibleSortedMap);
Log.d(TAG, "mZOrderMap.size(): " + mZOrderMap.size());
Log.d(TAG, "mZOrderMap: " + mZOrderMap);
Log.d(TAG, "mIsOccluded: " + mIsOccluded);
Log.d(TAG, "mViewsHiddenForOcclusion: " + mViewsHiddenForOcclusion);
Log.d(TAG, "mViewsHiddenForOcclusion.size(): " + mViewsHiddenForOcclusion.size());
}
}

View File

@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -168,6 +169,18 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase {
any());
}
@Test
public void setOccludedFalse_currentlyOccluded_bouncerReset() {
when(mBouncer.isSecure()).thenReturn(true);
mCarKeyguardViewController.show(/* options= */ null);
mCarKeyguardViewController.setOccluded(/* occluded= */ true, /* animate= */ false);
reset(mBouncer);
mCarKeyguardViewController.setOccluded(/* occluded= */ false, /* animate= */ false);
verify(mBouncer).show(/* resetSecuritySelection= */ true);
}
@Test
public void onCancelClicked_callsCancelClickedListener() {
when(mBouncer.isSecure()).thenReturn(true);

View File

@ -490,6 +490,81 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
verify(mSystemUIOverlayWindowController).setWindowVisible(false);
}
@Test
public void setOccludedTrue_viewToHideWhenOccludedVisible_viewHidden() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(false);
mOverlayViewGlobalStateController.setOccluded(true);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isFalse();
}
@Test
public void setOccludedTrue_viewToNotHideWhenOccludedVisible_viewShown() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(true);
mOverlayViewGlobalStateController.setOccluded(true);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isTrue();
}
@Test
public void hideViewAndThenSetOccludedTrue_viewHiddenForOcclusion_viewHiddenAfterOcclusion() {
setupOverlayViewController1();
setOverlayViewControllerAsShowing(mOverlayViewController1);
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(false);
mOverlayViewGlobalStateController.setOccluded(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, /* runnable= */ null);
mOverlayViewGlobalStateController.setOccluded(false);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isFalse();
}
@Test
public void setOccludedTrueAndThenShowView_viewToNotHideForOcclusion_viewShown() {
setupOverlayViewController1();
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(true);
mOverlayViewGlobalStateController.setOccluded(true);
setOverlayViewControllerAsShowing(mOverlayViewController1);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isTrue();
}
@Test
public void setOccludedTrueAndThenShowView_viewToHideForOcclusion_viewHidden() {
setupOverlayViewController1();
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(false);
mOverlayViewGlobalStateController.setOccluded(true);
setOverlayViewControllerAsShowing(mOverlayViewController1);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isFalse();
}
@Test
public void setOccludedFalse_viewShownAfterSetOccludedTrue_viewToHideForOcclusion_viewShown() {
setupOverlayViewController1();
when(mOverlayViewController1.shouldShowWhenOccluded()).thenReturn(false);
mOverlayViewGlobalStateController.setOccluded(true);
setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewGlobalStateController.setOccluded(false);
assertThat(mOverlayViewGlobalStateController.mZOrderVisibleSortedMap.containsValue(
mOverlayViewController1)).isTrue();
}
@Test
public void inflateView_notInflated_inflates() {
when(mOverlayViewController2.isInflated()).thenReturn(false);