Merge "Migrate CentralSurfacesImpl to Predictive Back api" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2d622277af
@@ -100,11 +100,14 @@ import android.view.MotionEvent;
|
|||||||
import android.view.ThreadedRenderer;
|
import android.view.ThreadedRenderer;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewRootImpl;
|
||||||
import android.view.WindowInsetsController.Appearance;
|
import android.view.WindowInsetsController.Appearance;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.WindowManagerGlobal;
|
import android.view.WindowManagerGlobal;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.widget.DateTimeView;
|
import android.widget.DateTimeView;
|
||||||
|
import android.window.OnBackInvokedCallback;
|
||||||
|
import android.window.OnBackInvokedDispatcher;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.Lifecycle;
|
import androidx.lifecycle.Lifecycle;
|
||||||
@@ -526,10 +529,17 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
|||||||
private CentralSurfacesComponent mCentralSurfacesComponent;
|
private CentralSurfacesComponent mCentralSurfacesComponent;
|
||||||
|
|
||||||
// Flags for disabling the status bar
|
// 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 mDisabled1 = 0;
|
||||||
private int mDisabled2 = 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) */
|
/** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
|
||||||
private @Appearance int mAppearance;
|
private @Appearance int mAppearance;
|
||||||
|
|
||||||
@@ -653,6 +663,12 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
|||||||
|
|
||||||
private final InteractionJankMonitor mJankMonitor;
|
private final InteractionJankMonitor mJankMonitor;
|
||||||
|
|
||||||
|
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "mOnBackInvokedCallback() called");
|
||||||
|
}
|
||||||
|
onBackPressed();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public constructor for CentralSurfaces.
|
* Public constructor for CentralSurfaces.
|
||||||
@@ -2751,9 +2767,38 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
|||||||
if (visibleToUser) {
|
if (visibleToUser) {
|
||||||
handleVisibleToUserChangedImpl(visibleToUser);
|
handleVisibleToUserChangedImpl(visibleToUser);
|
||||||
mNotificationLogger.startNotificationLogging();
|
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 {
|
} else {
|
||||||
mNotificationLogger.stopNotificationLogging();
|
mNotificationLogger.stopNotificationLogging();
|
||||||
handleVisibleToUserChangedImpl(visibleToUser);
|
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();
|
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.
|
* Propagation of the bouncer state, indicating that it's fully visible.
|
||||||
*/
|
*/
|
||||||
@@ -3781,6 +3832,12 @@ public class CentralSurfacesImpl extends CoreStartable implements
|
|||||||
updateScrimController();
|
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.
|
* 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
|
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.doAnswer;
|
|||||||
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.reset;
|
import static org.mockito.Mockito.reset;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -69,7 +70,11 @@ import android.util.DisplayMetrics;
|
|||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
import android.view.ViewRootImpl;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.window.OnBackInvokedCallback;
|
||||||
|
import android.window.OnBackInvokedDispatcher;
|
||||||
|
import android.window.WindowOnBackInvokedDispatcher;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -168,6 +173,7 @@ 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.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
@@ -279,6 +285,15 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
|||||||
@Mock private InteractionJankMonitor mJankMonitor;
|
@Mock private InteractionJankMonitor mJankMonitor;
|
||||||
@Mock private DeviceStateManager mDeviceStateManager;
|
@Mock private DeviceStateManager mDeviceStateManager;
|
||||||
@Mock private WiredChargingRippleController mWiredChargingRippleController;
|
@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 ShadeController mShadeController;
|
||||||
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
|
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
|
||||||
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
|
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
|
||||||
@@ -368,10 +383,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
|||||||
return null;
|
return null;
|
||||||
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
|
}).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
|
||||||
|
|
||||||
mShadeController = new ShadeControllerImpl(mCommandQueue,
|
mShadeController = spy(new ShadeControllerImpl(mCommandQueue,
|
||||||
mStatusBarStateController, mNotificationShadeWindowController,
|
mStatusBarStateController, mNotificationShadeWindowController,
|
||||||
mStatusBarKeyguardViewManager, mContext.getSystemService(WindowManager.class),
|
mStatusBarKeyguardViewManager, mContext.getSystemService(WindowManager.class),
|
||||||
() -> Optional.of(mCentralSurfaces), () -> mAssistManager);
|
() -> Optional.of(mCentralSurfaces), () -> mAssistManager));
|
||||||
|
|
||||||
when(mOperatorNameViewControllerFactory.create(any()))
|
when(mOperatorNameViewControllerFactory.create(any()))
|
||||||
.thenReturn(mOperatorNameViewController);
|
.thenReturn(mOperatorNameViewController);
|
||||||
@@ -460,7 +475,14 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
|
|||||||
mActivityLaunchAnimator,
|
mActivityLaunchAnimator,
|
||||||
mJankMonitor,
|
mJankMonitor,
|
||||||
mDeviceStateManager,
|
mDeviceStateManager,
|
||||||
mWiredChargingRippleController, mDreamManager);
|
mWiredChargingRippleController, mDreamManager) {
|
||||||
|
@Override
|
||||||
|
protected ViewRootImpl getViewRootImpl() {
|
||||||
|
return mViewRootImpl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
when(mViewRootImpl.getOnBackInvokedDispatcher())
|
||||||
|
.thenReturn(mOnBackInvokedDispatcher);
|
||||||
when(mKeyguardViewMediator.registerCentralSurfaces(
|
when(mKeyguardViewMediator.registerCentralSurfaces(
|
||||||
any(CentralSurfacesImpl.class),
|
any(CentralSurfacesImpl.class),
|
||||||
any(NotificationPanelViewController.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
|
@Test
|
||||||
public void testPanelOpenForHeadsUp() {
|
public void testPanelOpenForHeadsUp() {
|
||||||
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user