diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index a83b13c506713..3873c25f32c64 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -226,7 +226,7 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite ActionsDialog dialog = new ActionsDialog(getContext(), mAdapter, mOverflowAdapter, this::getWalletViewController, mDepthController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter); + mSysUiState, this::onRotate, isKeyguardShowing(), mPowerAdapter, getEventLogger()); if (shouldShowLockMessage(dialog)) { dialog.showLockMessage(); @@ -294,11 +294,11 @@ public class GlobalActionsDialog extends GlobalActionsDialogLite SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, - MyPowerOptionsAdapter powerAdapter) { + MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger) { super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions, adapter, overflowAdapter, depthController, sysuiColorExtractor, statusBarService, notificationShadeWindowController, sysuiState, - onRotateCallback, keyguardShowing, powerAdapter); + onRotateCallback, keyguardShowing, powerAdapter, uiEventLogger); mWalletFactory = walletFactory; // Update window attributes diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index 2eb37624f5980..f9bb35fcb723b 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -249,7 +249,43 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene GA_SCREENSHOT_PRESS(347), @UiEvent(doc = "The global actions screenshot button was long pressed.") - GA_SCREENSHOT_LONG_PRESS(348); + GA_SCREENSHOT_LONG_PRESS(348), + + @UiEvent(doc = "The global actions power off button was pressed.") + GA_SHUTDOWN_PRESS(802), + + @UiEvent(doc = "The global actions power off button was long pressed.") + GA_SHUTDOWN_LONG_PRESS(803), + + @UiEvent(doc = "The global actions reboot button was pressed.") + GA_REBOOT_PRESS(349), + + @UiEvent(doc = "The global actions reboot button was long pressed.") + GA_REBOOT_LONG_PRESS(804), + + @UiEvent(doc = "The global actions lockdown button was pressed.") + GA_LOCKDOWN_PRESS(354), // already created by cwren apparently + + @UiEvent(doc = "Power menu was opened via quick settings button.") + GA_OPEN_QS(805), + + @UiEvent(doc = "Power menu was opened via power + volume up.") + GA_OPEN_POWER_VOLUP(806), + + @UiEvent(doc = "Power menu was opened via long press on power.") + GA_OPEN_LONG_PRESS_POWER(807), + + @UiEvent(doc = "Power menu was closed via long press on power.") + GA_CLOSE_LONG_PRESS_POWER(808), + + @UiEvent(doc = "Power menu was dismissed by back gesture.") + GA_CLOSE_BACK(809), + + @UiEvent(doc = "Power menu was dismissed by tapping outside dialog.") + GA_CLOSE_TAP_OUTSIDE(810), + + @UiEvent(doc = "Power menu was closed via power + volume up.") + GA_CLOSE_POWER_VOLUP(811); private final int mId; @@ -349,6 +385,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene return mContext; } + protected UiEventLogger getEventLogger() { + return mUiEventLogger; + } + /** * Show the global actions dialog (creating if necessary) * @@ -581,7 +621,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mAdapter, mOverflowAdapter, mDepthController, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter); + mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger); dialog.setOnDismissListener(this); dialog.setOnShowListener(this); @@ -679,13 +719,14 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @VisibleForTesting final class ShutDownAction extends SinglePressAction implements LongPressAction { - private ShutDownAction() { + ShutDownAction() { super(R.drawable.ic_lock_power_off, R.string.global_action_power_off); } @Override public boolean onLongPress() { + mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS); if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { mWindowManagerFuncs.reboot(true); return true; @@ -705,6 +746,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Override public void onPress() { + mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_PRESS); // shutdown by making sure radio and power are handled accordingly. mWindowManagerFuncs.shutdown(); } @@ -807,12 +849,13 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @VisibleForTesting final class RestartAction extends SinglePressAction implements LongPressAction { - private RestartAction() { + RestartAction() { super(R.drawable.ic_restart, R.string.global_action_restart); } @Override public boolean onLongPress() { + mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_LONG_PRESS); if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { mWindowManagerFuncs.reboot(true); return true; @@ -832,6 +875,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Override public void onPress() { + mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_PRESS); mWindowManagerFuncs.reboot(false); } } @@ -1062,6 +1106,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene public void onPress() { mLockPatternUtils.requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN, UserHandle.USER_ALL); + mUiEventLogger.log(GlobalActionsEvent.GA_LOCKDOWN_PRESS); try { mIWindowManager.lockNow(null); // Lock profiles (if any) on the background thread. @@ -2049,6 +2094,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private ListPopupWindow mOverflowPopup; private Dialog mPowerOptionsDialog; protected final Runnable mOnRotateCallback; + private UiEventLogger mUiEventLogger; protected ViewGroup mContainer; @@ -2058,7 +2104,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, - MyPowerOptionsAdapter powerAdapter) { + MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger) { super(context, themeRes); mContext = context; mAdapter = adapter; @@ -2071,6 +2117,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mSysUiState = sysuiState; mOnRotateCallback = onRotateCallback; mKeyguardShowing = keyguardShowing; + mUiEventLogger = uiEventLogger; // Window initialization Window window = getWindow(); @@ -2141,7 +2188,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mGlobalActionsLayout.setAdapter(mAdapter); mContainer = findViewById(com.android.systemui.R.id.global_actions_container); mContainer.setOnClickListener(v -> { - // TODO: add logging (b/182830510) + mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); cancel(); }); @@ -2217,6 +2264,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mColorExtractor.removeOnColorsChangedListener(this); } + @Override + public void onBackPressed() { + super.onBackPressed(); + mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_BACK); + } + @Override public void show() { super.show(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index 1fa9260098612..f6d93895ce05b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -29,6 +29,7 @@ import android.widget.TextView; import android.widget.Toast; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; @@ -73,6 +74,7 @@ public class QSFooterViewController extends ViewController impleme private final View mPowerMenuLite; private final boolean mShowPMLiteButton; private GlobalActionsDialogLite mGlobalActionsDialog; + private final UiEventLogger mUiEventLogger; private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener = new UserInfoController.OnUserInfoChangedListener() { @@ -122,6 +124,7 @@ public class QSFooterViewController extends ViewController impleme startSettingsActivity(); } } else if (v == mPowerMenuLite) { + mUiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS); mGlobalActionsDialog.showOrHideDialog(false, true); } } @@ -139,7 +142,7 @@ public class QSFooterViewController extends ViewController impleme QuickQSPanelController quickQSPanelController, TunerService tunerService, MetricsLogger metricsLogger, FalsingManager falsingManager, @Named(PM_LITE_ENABLED) boolean showPMLiteButton, - GlobalActionsDialogLite globalActionsDialog) { + GlobalActionsDialogLite globalActionsDialog, UiEventLogger uiEventLogger) { super(view); mUserManager = userManager; mUserInfoController = userInfoController; @@ -161,6 +164,7 @@ public class QSFooterViewController extends ViewController impleme mPowerMenuLite = mView.findViewById(R.id.pm_lite); mShowPMLiteButton = showPMLiteButton; mGlobalActionsDialog = globalActionsDialog; + mUiEventLogger = uiEventLogger; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java index 80716f9398f35..003368d99dcc5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java @@ -39,6 +39,7 @@ import android.service.dreams.IDreamManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.IWindowManager; +import android.view.View; import android.view.WindowManagerPolicyConstants; import androidx.test.filters.SmallTest; @@ -171,6 +172,44 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_POWER_MENU_CLOSE); } + @Test + public void testShouldLogClose_backButton() { + mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); + doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems(); + doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any()); + doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any()); + String[] actions = { + GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY, + GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN, + GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER, + GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART, + }; + doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions(); + GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); + dialog.onBackPressed(); + mTestableLooper.processAllMessages(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_BACK); + } + + @Test + public void testShouldLogOnTapOutside() { + mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite); + doReturn(4).when(mGlobalActionsDialogLite).getMaxShownPowerItems(); + doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any()); + doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any()); + String[] actions = { + GlobalActionsDialog.GLOBAL_ACTION_KEY_EMERGENCY, + GlobalActionsDialog.GLOBAL_ACTION_KEY_LOCKDOWN, + GlobalActionsDialog.GLOBAL_ACTION_KEY_POWER, + GlobalActionsDialog.GLOBAL_ACTION_KEY_RESTART, + }; + doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions(); + GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); + View container = dialog.findViewById(com.android.systemui.R.id.global_actions_container); + container.callOnClick(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); + } + @Test public void testShouldLogBugreportPress() throws InterruptedException { GlobalActionsDialog.BugReportAction bugReportAction = @@ -286,4 +325,44 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty(); assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty(); } + + @Test + public void testShouldLogLockdownPress() { + GlobalActionsDialogLite.LockDownAction lockDownAction = + mGlobalActionsDialogLite.new LockDownAction(); + lockDownAction.onPress(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_LOCKDOWN_PRESS); + } + + @Test + public void testShouldLogShutdownPress() { + GlobalActionsDialogLite.ShutDownAction shutDownAction = + mGlobalActionsDialogLite.new ShutDownAction(); + shutDownAction.onPress(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SHUTDOWN_PRESS); + } + + @Test + public void testShouldLogShutdownLongPress() { + GlobalActionsDialogLite.ShutDownAction shutDownAction = + mGlobalActionsDialogLite.new ShutDownAction(); + shutDownAction.onLongPress(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS); + } + + @Test + public void testShouldLogRebootPress() { + GlobalActionsDialogLite.RestartAction restartAction = + mGlobalActionsDialogLite.new RestartAction(); + restartAction.onPress(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_REBOOT_PRESS); + } + + @Test + public void testShouldLogRebootLongPress() { + GlobalActionsDialogLite.RestartAction restartAction = + mGlobalActionsDialogLite.new RestartAction(); + restartAction.onLongPress(); + verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_REBOOT_LONG_PRESS); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java index d35597f799ee5..6f7bf3b09daa8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,6 +36,7 @@ import android.widget.TextView; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -82,6 +84,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { private QuickQSPanelController mQuickQSPanelController; private FakeTunerService mFakeTunerService; private MetricsLogger mMetricsLogger = new FakeMetricsLogger(); + private FalsingManagerFake mFalsingManager; @Mock private SettingsButton mSettingsButton; @@ -95,12 +98,15 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { private View mPowerMenuLiteView; @Mock private GlobalActionsDialogLite mGlobalActionsDialog; + @Mock + private UiEventLogger mUiEventLogger; private QSFooterViewController mController; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); + mFalsingManager = new FalsingManagerFake(); injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); @@ -121,7 +127,8 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { mController = new QSFooterViewController(mView, mUserManager, mUserInfoController, mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController, mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService, - mMetricsLogger, new FalsingManagerFake(), false, mGlobalActionsDialog); + mMetricsLogger, mFalsingManager, false, mGlobalActionsDialog, + mUiEventLogger); mController.init(); } @@ -154,4 +161,27 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { // Verify Settings wasn't launched. verify(mActivityStarter, never()).startActivity(any(), anyBoolean()); } + + @Test + public void testLogPowerMenuClick() { + // Enable power menu button + mController = new QSFooterViewController(mView, mUserManager, mUserInfoController, + mActivityStarter, mDeviceProvisionedController, mUserTracker, mQSPanelController, + mMultiUserSwitchController, mQuickQSPanelController, mFakeTunerService, + mMetricsLogger, new FalsingManagerFake(), true, mGlobalActionsDialog, + mUiEventLogger); + mController.init(); + mController.setExpanded(true); + mFalsingManager.setFalseTap(false); + + ArgumentCaptor onClickCaptor = + ArgumentCaptor.forClass(View.OnClickListener.class); + verify(mPowerMenuLiteView).setOnClickListener(onClickCaptor.capture()); + + onClickCaptor.getValue().onClick(mPowerMenuLiteView); + + // Verify clicks are logged + verify(mUiEventLogger, times(1)) + .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS); + } }