Merge "Migrate GlobalActionsDialogLite to predictive back" into tm-qpr-dev

This commit is contained in:
Rahul Banerjee
2022-08-22 17:06:46 +00:00
committed by Android (Google) Code Review
3 changed files with 101 additions and 1 deletions

View File

@@ -90,6 +90,8 @@ import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ListPopupWindow; import android.widget.ListPopupWindow;
import android.widget.TextView; import android.widget.TextView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle; 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_GLOBAL_ACTIONS = "globalactions";
public static final String SYSTEM_DIALOG_REASON_DREAM = "dream"; 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 TAG = "GlobalActionsDialogLite";
private static final String INTERACTION_JANK_TAG = "global_actions"; private static final String INTERACTION_JANK_TAG = "global_actions";
@@ -2177,6 +2181,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
protected ViewGroup mContainer; protected ViewGroup mContainer;
private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
logOnBackInvocation();
dismiss();
};
@VisibleForTesting @VisibleForTesting
protected GestureDetector.SimpleOnGestureListener mGestureListener = protected GestureDetector.SimpleOnGestureListener mGestureListener =
new GestureDetector.SimpleOnGestureListener() { 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, ActionsDialogLite(Context context, int themeRes, MyAdapter adapter,
MyOverflowAdapter overflowAdapter, MyOverflowAdapter overflowAdapter,
SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
@@ -2254,6 +2273,22 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
initializeLayout(); initializeLayout();
mWindowDimAmount = getWindow().getAttributes().dimAmount; 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 @Override
@@ -2453,7 +2488,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
@Override @Override
public void onBackPressed() { public void onBackPressed() {
super.onBackPressed(); super.onBackPressed();
logOnBackInvocation();
}
private void logOnBackInvocation() {
mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_BACK); mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_BACK);
if (DEBUG) Log.d(TAG, "onBack invoked");
} }
@Override @Override

View File

@@ -53,7 +53,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS" /> <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" /> <uses-library android:name="android.test.runner" />
<receiver android:name="com.android.systemui.SliceBroadcastRelayHandlerTest$Receiver" <receiver android:name="com.android.systemui.SliceBroadcastRelayHandlerTest$Receiver"

View File

@@ -42,8 +42,11 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.IWindowManager; import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.WindowManagerPolicyConstants; import android.view.WindowManagerPolicyConstants;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -73,6 +76,8 @@ import com.android.systemui.util.settings.SecureSettings;
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.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
@@ -117,6 +122,8 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
@Mock private CentralSurfaces mCentralSurfaces; @Mock private CentralSurfaces mCentralSurfaces;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private DialogLaunchAnimator mDialogLaunchAnimator; @Mock private DialogLaunchAnimator mDialogLaunchAnimator;
@Mock private OnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback;
private TestableLooper mTestableLooper; private TestableLooper mTestableLooper;
@@ -202,6 +209,58 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_BACK); 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 @Test
public void testSingleTap_logAndDismiss() { public void testSingleTap_logAndDismiss() {
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);