Merge "Migrate CentralSurfacesImpl to Predictive Back api" into tm-qpr-dev

This commit is contained in:
Rahul Banerjee
2022-09-14 16:48:03 +00:00
committed by Android (Google) Code Review
2 changed files with 120 additions and 4 deletions

View File

@@ -100,11 +100,14 @@ import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.widget.DateTimeView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
@@ -526,10 +529,17 @@ public class CentralSurfacesImpl extends CoreStartable implements
private CentralSurfacesComponent mCentralSurfacesComponent;
// Flags for disabling the status bar
// Two variables becaseu the first one evidently ran out of room for new flags.
// Two variables because the first one evidently ran out of room for new flags.
private int mDisabled1 = 0;
private int mDisabled2 = 0;
/**
* This keeps track of whether we have (or haven't) registered the predictive back callback.
* Since we can have visible -> visible transitions, we need to avoid
* double-registering (or double-unregistering) our callback.
*/
private boolean mIsBackCallbackRegistered = false;
/** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
private @Appearance int mAppearance;
@@ -653,6 +663,12 @@ public class CentralSurfacesImpl extends CoreStartable implements
private final InteractionJankMonitor mJankMonitor;
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
if (DEBUG) {
Log.d(TAG, "mOnBackInvokedCallback() called");
}
onBackPressed();
};
/**
* Public constructor for CentralSurfaces.
@@ -2751,9 +2767,38 @@ public class CentralSurfacesImpl extends CoreStartable implements
if (visibleToUser) {
handleVisibleToUserChangedImpl(visibleToUser);
mNotificationLogger.startNotificationLogging();
if (!mIsBackCallbackRegistered) {
ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
viewRootImpl.getOnBackInvokedDispatcher()
.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT,
mOnBackInvokedCallback);
mIsBackCallbackRegistered = true;
if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered");
}
} else {
if (DEBUG) Log.d(TAG, "is now VISIBLE to user, BUT callback ALREADY unregistered");
}
} else {
mNotificationLogger.stopNotificationLogging();
handleVisibleToUserChangedImpl(visibleToUser);
if (mIsBackCallbackRegistered) {
ViewRootImpl viewRootImpl = getViewRootImpl();
if (viewRootImpl != null) {
viewRootImpl.getOnBackInvokedDispatcher()
.unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
mIsBackCallbackRegistered = false;
if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered");
}
} else {
if (DEBUG) {
Log.d(TAG,
"is NOT VISIBLE to user, BUT NO callback (or callback ALREADY "
+ "unregistered)");
}
}
}
}
@@ -3464,6 +3509,12 @@ public class CentralSurfacesImpl extends CoreStartable implements
return mNotificationPanelViewController.getKeyguardBottomAreaView();
}
protected ViewRootImpl getViewRootImpl() {
NotificationShadeWindowView nswv = getNotificationShadeWindowView();
if (nswv != null) return nswv.getViewRootImpl();
return null;
}
/**
* Propagation of the bouncer state, indicating that it's fully visible.
*/
@@ -3781,6 +3832,12 @@ public class CentralSurfacesImpl extends CoreStartable implements
updateScrimController();
}
@VisibleForTesting
public void setNotificationShadeWindowViewController(
NotificationShadeWindowViewController nswvc) {
mNotificationShadeWindowViewController = nswvc;
}
/**
* Set the amount of progress we are currently in if we're transitioning to the full shade.
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full

View File

@@ -35,6 +35,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -69,7 +70,11 @@ import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.WindowOnBackInvokedDispatcher;
import androidx.test.filters.SmallTest;
@@ -168,6 +173,7 @@ 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;
@@ -279,6 +285,15 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Mock private InteractionJankMonitor mJankMonitor;
@Mock private DeviceStateManager mDeviceStateManager;
@Mock private WiredChargingRippleController mWiredChargingRippleController;
/**
* The process of registering/unregistering a predictive back callback requires a
* ViewRootImpl, which is present IRL, but may be missing during a Mockito unit test.
* To prevent an NPE during test execution, we explicitly craft and provide a fake ViewRootImpl.
*/
@Mock private ViewRootImpl mViewRootImpl;
@Mock private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback;
private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -368,10 +383,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
return null;
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
mShadeController = new ShadeControllerImpl(mCommandQueue,
mShadeController = spy(new ShadeControllerImpl(mCommandQueue,
mStatusBarStateController, mNotificationShadeWindowController,
mStatusBarKeyguardViewManager, mContext.getSystemService(WindowManager.class),
() -> Optional.of(mCentralSurfaces), () -> mAssistManager);
() -> Optional.of(mCentralSurfaces), () -> mAssistManager));
when(mOperatorNameViewControllerFactory.create(any()))
.thenReturn(mOperatorNameViewController);
@@ -460,7 +475,14 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mActivityLaunchAnimator,
mJankMonitor,
mDeviceStateManager,
mWiredChargingRippleController, mDreamManager);
mWiredChargingRippleController, mDreamManager) {
@Override
protected ViewRootImpl getViewRootImpl() {
return mViewRootImpl;
}
};
when(mViewRootImpl.getOnBackInvokedDispatcher())
.thenReturn(mOnBackInvokedDispatcher);
when(mKeyguardViewMediator.registerCentralSurfaces(
any(CentralSurfacesImpl.class),
any(NotificationPanelViewController.class),
@@ -738,6 +760,43 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
}
}
/**
* Do the following:
* 1. verify that a predictive back callback is registered when CSurf becomes visible
* 2. verify that the same callback is unregistered when CSurf becomes invisible
*/
@Test
public void testPredictiveBackCallback_registration() {
mCentralSurfaces.handleVisibleToUserChanged(true);
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
mOnBackInvokedCallback.capture());
mCentralSurfaces.handleVisibleToUserChanged(false);
verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback(
eq(mOnBackInvokedCallback.getValue()));
}
/**
* Do the following:
* 1. capture the predictive back callback during registration
* 2. call the callback directly
* 3. verify that the ShadeController's panel collapse animation is invoked
*/
@Test
public void testPredictiveBackCallback_invocationCollapsesPanel() {
mCentralSurfaces.setNotificationShadeWindowViewController(
mNotificationShadeWindowViewController);
mCentralSurfaces.handleVisibleToUserChanged(true);
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
mOnBackInvokedCallback.capture());
when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
mOnBackInvokedCallback.getValue().onBackInvoked();
verify(mShadeController).animateCollapsePanels();
}
@Test
public void testPanelOpenForHeadsUp() {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);