长按事件动作的配置
frameworks\base\core\res\res\values\config.xml 选择1会弹出Global actions menu
<!-- Control the behavior when the user long presses the power button.0 - Nothing1 - Global actions menu2 - Power off (with confirmation)3 - Power off (without confirmation)4 - Go to voice assist5 - Go to assistant (Settings.Secure.ASSISTANT)--><integer name="config_longPressOnPowerBehavior">1</integer>
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
对长按事件的处理
private void powerLongPress(long eventTime) {final int behavior = getResolvedLongPressOnPowerBehavior();Slog.d(TAG, "powerLongPress: eventTime=" + eventTime+ " mLongPressOnPowerBehavior=" + mLongPressOnPowerBehavior);switch (behavior) {case LONG_PRESS_POWER_NOTHING:break;case LONG_PRESS_POWER_GLOBAL_ACTIONS:mPowerKeyHandled = true;performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,"Power - Long Press - Global Actions");showGlobalActions();break;case LONG_PRESS_POWER_SHUT_OFF:case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:mPowerKeyHandled = true;performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,"Power - Long Press - Shut Off");sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);break;case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:mPowerKeyHandled = true;performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,"Power - Long Press - Go To Voice Assist");// Some devices allow the voice assistant intent during setup (and use that intent// to launch something else, like Settings). So we explicitly allow that via the// config_allowStartActivityForLongPressOnPowerInSetup resource in config.xml.launchVoiceAssist(mAllowStartActivityForLongPressOnPowerDuringSetup);break;case LONG_PRESS_POWER_ASSISTANT:mPowerKeyHandled = true;performHapticFeedback(HapticFeedbackConstants.ASSISTANT_BUTTON, false,"Power - Long Press - Go To Assistant");final int powerKeyDeviceId = Integer.MIN_VALUE;launchAssistAction(null, powerKeyDeviceId, eventTime,AssistUtils.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS);break;}}
@Overridepublic void showGlobalActions() {mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS);}
public void handleMessage(Message msg) {switch (msg.what) {case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);break;case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);break;case MSG_DISPATCH_SHOW_RECENTS:showRecentApps(false);break;case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:showGlobalActionsInternal();break;
void showGlobalActionsInternal() {if (mGlobalActions == null) {mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);}final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());// since it took two seconds of long press to bring this up,// poke the wake lock so they have some time to see the dialog.mPowerManager.userActivity(SystemClock.uptimeMillis(), false);}
frameworks\base\services\core\java\com\android\server\policy\GlobalActions.java
private void ensureLegacyCreated() {if (mLegacyGlobalActions != null) return;mLegacyGlobalActions = new LegacyGlobalActions(mContext, mWindowManagerFuncs,this::onGlobalActionsDismissed);}public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);if (mGlobalActionsProvider != null && mGlobalActionsProvider.isGlobalActionsDisabled()) {return;}mKeyguardShowing = keyguardShowing;mDeviceProvisioned = deviceProvisioned;mShowing = true;if (mGlobalActionsAvailable && !"box".equals(SystemProperties.get("ro.target.product","unkonw"))) {mHandler.postDelayed(mShowTimeout, 5000);mGlobalActionsProvider.showGlobalActions();} else {// SysUI isn't alive, show legacy menu.ensureLegacyCreated();mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);}}
item的创建在LegacyGlobalActions里
frameworks\base\services\core\java\com\android\server\policy\LegacyGlobalActions.java
/*** Create the global actions dialog.* @return A new dialog.*/private ActionsDialog createDialog() {// Simple toggle style if there's no vibrator, otherwise use a tri-stateif (!mHasVibrator) {mSilentModeAction = new SilentModeToggleAction();} else {mSilentModeAction = new SilentModeTriStateAction(mContext, mAudioManager, mHandler);}mAirplaneModeOn = new ToggleAction(R.drawable.ic_lock_airplane_mode,R.drawable.ic_lock_airplane_mode_off,R.string.global_actions_toggle_airplane_mode,R.string.global_actions_airplane_mode_on_status,R.string.global_actions_airplane_mode_off_status) {@Overridepublic void onToggle(boolean on) {if (mHasTelephony && TelephonyProperties.in_ecm_mode().orElse(false)) {mIsWaitingForEcmExit = true;// Launch ECM exit dialogIntent ecmDialogIntent =new Intent(TelephonyManager.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mContext.startActivity(ecmDialogIntent);} else {changeAirplaneModeSystemSetting(on);}}@Overrideprotected void changeStateFromPress(boolean buttonOn) {if (!mHasTelephony) return;// In ECM mode airplane state cannot be changedif (!TelephonyProperties.in_ecm_mode().orElse(false)) {mState = buttonOn ? State.TurningOn : State.TurningOff;mAirplaneState = mState;}}@Overridepublic boolean showDuringKeyguard() {return true;}@Overridepublic boolean showBeforeProvisioning() {return false;}};onAirplaneModeChanged();mItems = new ArrayList<Action>();String[] defaultActions = mContext.getResources().getStringArray(com.android.internal.R.array.config_globalActionsList);ArraySet<String> addedKeys = new ArraySet<String>();for (int i = 0; i < defaultActions.length; i++) {String actionKey = defaultActions[i];if (addedKeys.contains(actionKey)) {// If we already have added this, don't add it again.continue;}if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {mItems.add(new PowerAction(mContext, mWindowManagerFuncs));} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {mItems.add(mAirplaneModeOn);} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {if (Settings.Global.getInt(mContext.getContentResolver(),Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {mItems.add(new BugReportAction());}} else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {if (mShowSilentToggle) {mItems.add(mSilentModeAction);}} else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)) {if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {addUsersToMenu(mItems);}} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {mItems.add(getSettingsAction());} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {mItems.add(getLockdownAction());} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {mItems.add(getVoiceAssistAction());} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {mItems.add(getAssistAction());} else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) {mItems.add(new RestartAction(mContext, mWindowManagerFuncs));} else {Log.e(TAG, "Invalid global action key " + actionKey);}// Add here so we don't add more than one.addedKeys.add(actionKey);}if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {mItems.add(getEmergencyAction());}mAdapter = new ActionsAdapter(mContext, mItems,() -> mDeviceProvisioned, () -> mKeyguardShowing);AlertController.AlertParams params = new AlertController.AlertParams(mContext);params.mAdapter = mAdapter;params.mOnClickListener = this;params.mForceInverseBackground = true;ActionsDialog dialog = new ActionsDialog(mContext, params);dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.dialog.getListView().setItemsCanFocus(true);dialog.getListView().setLongClickable(true);dialog.getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view, int position,long id) {final Action action = mAdapter.getItem(position);if (action instanceof LongPressAction) {return ((LongPressAction) action).onLongPress();}return false;}});dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);// Don't acquire soft keyboard focus, to avoid destroying state when capturing bugreportsdialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM);dialog.setOnDismissListener(this);return dialog;}private class BugReportAction extends SinglePressAction implements LongPressAction {public BugReportAction() {super(com.android.internal.R.drawable.ic_lock_bugreport, R.string.bugreport_title);}@Overridepublic void onPress() {// don't actually trigger the bugreport if we are running stability// tests via monkeyif (ActivityManager.isUserAMonkey()) {return;}// Add a little delay before executing, to give the// dialog a chance to go away before it takes a// screenshot.mHandler.postDelayed(new Runnable() {@Overridepublic void run() {try {// Take an "interactive" bugreport.MetricsLogger.action(mContext,MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE);ActivityManager.getService().requestInteractiveBugReport();} catch (RemoteException e) {}}}, 500);}@Overridepublic boolean onLongPress() {// don't actually trigger the bugreport if we are running stability// tests via monkeyif (ActivityManager.isUserAMonkey()) {return false;}try {// Take a "full" bugreport.MetricsLogger.action(mContext, MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL);ActivityManager.getService().requestFullBugReport();} catch (RemoteException e) {}return false;}@Overridepublic boolean showDuringKeyguard() {return true;}@Overridepublic boolean showBeforeProvisioning() {return false;}@Overridepublic String getStatus() {return mContext.getString(com.android.internal.R.string.bugreport_status,Build.VERSION.RELEASE_OR_CODENAME,Build.ID);}}
添加菜单可以参考 Android 6.0长按电源键添加重启菜单-CSDN博客