Loading packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +40 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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() { Loading Loading @@ -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, Loading Loading @@ -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 Loading Loading @@ -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 Loading packages/SystemUI/tests/AndroidManifest.xml +2 −1 Original line number Diff line number Diff line Loading @@ -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" Loading packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading
packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +40 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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() { Loading Loading @@ -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, Loading Loading @@ -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 Loading Loading @@ -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 Loading
packages/SystemUI/tests/AndroidManifest.xml +2 −1 Original line number Diff line number Diff line Loading @@ -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" Loading
packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading