Migrate GlobalActionsDialogLite to predictive back
As part of the effort to rollout Predictive Back, the old "just in time" back handlers need to be migrated over to the new "ahead of time" api (before any animation/feedback can be added). This is the first change in this API migration, with more to come. This also adds tests for GlobalActionsDialogLite. Bug: 238358031 Test: atest GlobalActionsDialogLiteTest Change-Id: Id8ee4ec97e34e6de63659d30784384e7c9ef9590
This commit is contained in:
@@ -90,6 +90,8 @@ import android.widget.ImageView.ScaleType;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListPopupWindow;
|
||||
import android.widget.TextView;
|
||||
import android.window.OnBackInvokedCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
@@ -155,6 +157,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|
||||
public static final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
|
||||
public static final String SYSTEM_DIALOG_REASON_DREAM = "dream";
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String TAG = "GlobalActionsDialogLite";
|
||||
|
||||
private static final String INTERACTION_JANK_TAG = "global_actions";
|
||||
@@ -2177,6 +2181,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|
||||
|
||||
protected ViewGroup mContainer;
|
||||
|
||||
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
|
||||
logOnBackInvocation();
|
||||
dismiss();
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
protected GestureDetector.SimpleOnGestureListener mGestureListener =
|
||||
new GestureDetector.SimpleOnGestureListener() {
|
||||
@@ -2221,6 +2230,16 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// this exists so that we can point it to a mock during Unit Testing
|
||||
private OnBackInvokedDispatcher mOverriddenBackDispatcher;
|
||||
|
||||
// the following method exists so that a Unit Test can supply a `OnBackInvokedDispatcher`
|
||||
@VisibleForTesting
|
||||
void setBackDispatcherOverride(OnBackInvokedDispatcher mockDispatcher) {
|
||||
mOverriddenBackDispatcher = mockDispatcher;
|
||||
}
|
||||
|
||||
ActionsDialogLite(Context context, int themeRes, MyAdapter adapter,
|
||||
MyOverflowAdapter overflowAdapter,
|
||||
SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
|
||||
@@ -2254,6 +2273,22 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|
||||
super.onCreate(savedInstanceState);
|
||||
initializeLayout();
|
||||
mWindowDimAmount = getWindow().getAttributes().dimAmount;
|
||||
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mOnBackInvokedCallback);
|
||||
if (DEBUG) Log.d(TAG, "OnBackInvokedCallback handler registered");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Override
|
||||
public OnBackInvokedDispatcher getOnBackInvokedDispatcher() {
|
||||
if (mOverriddenBackDispatcher != null) return mOverriddenBackDispatcher;
|
||||
else return super.getOnBackInvokedDispatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromWindow() {
|
||||
getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
|
||||
if (DEBUG) Log.d(TAG, "OnBackInvokedCallback handler unregistered");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2453,7 +2488,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
super.onBackPressed();
|
||||
logOnBackInvocation();
|
||||
}
|
||||
|
||||
private void logOnBackInvocation() {
|
||||
mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_BACK);
|
||||
if (DEBUG) Log.d(TAG, "onBack invoked");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" />
|
||||
|
||||
<application android:debuggable="true" android:largeHeap="true">
|
||||
<application android:debuggable="true" android:largeHeap="true"
|
||||
android:enableOnBackInvokedCallback="true" >
|
||||
<uses-library android:name="android.test.runner" />
|
||||
|
||||
<receiver android:name="com.android.systemui.SliceBroadcastRelayHandlerTest$Receiver"
|
||||
|
||||
@@ -42,8 +42,11 @@ import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
import android.window.OnBackInvokedCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -73,6 +76,8 @@ import com.android.systemui.util.settings.SecureSettings;
|
||||
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;
|
||||
|
||||
@@ -117,6 +122,8 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
|
||||
@Mock private CentralSurfaces mCentralSurfaces;
|
||||
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
@Mock private DialogLaunchAnimator mDialogLaunchAnimator;
|
||||
@Mock private OnBackInvokedDispatcher mOnBackInvokedDispatcher;
|
||||
@Captor private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback;
|
||||
|
||||
private TestableLooper mTestableLooper;
|
||||
|
||||
@@ -202,6 +209,58 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
|
||||
verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_BACK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPredictiveBackCallbackRegisteredAndUnregistered() {
|
||||
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
|
||||
doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
|
||||
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
|
||||
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
|
||||
String[] actions = {
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
|
||||
};
|
||||
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
|
||||
|
||||
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
|
||||
dialog.setBackDispatcherOverride(mOnBackInvokedDispatcher);
|
||||
dialog.create();
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
|
||||
eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), any());
|
||||
dialog.onDetachedFromWindow();
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPredictiveBackInvocationDismissesDialog() {
|
||||
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
|
||||
doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
|
||||
doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
|
||||
doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
|
||||
String[] actions = {
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
|
||||
GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
|
||||
};
|
||||
doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
|
||||
|
||||
GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
|
||||
dialog.create();
|
||||
dialog.show();
|
||||
mTestableLooper.processAllMessages();
|
||||
dialog.getWindow().injectInputEvent(
|
||||
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
|
||||
dialog.getWindow().injectInputEvent(
|
||||
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
|
||||
mTestableLooper.processAllMessages();
|
||||
verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_BACK);
|
||||
assertThat(dialog.isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleTap_logAndDismiss() {
|
||||
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
|
||||
|
||||
Reference in New Issue
Block a user