Android Framework定制长按电源键关机的窗口
文章目录
- 长按关机流程
- SystemUI实现的关机窗口
- LegacyGlobalActions实现的关机窗口
- 简介
- 功能概述
长按关机流程
frameworks/base/core/res/res/values/config.xml
这个xml中指定了长按电源键的处理方式
<!-- 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>
- 什么都不操作
- 显示全局操作菜单,菜单中通常包含关机、重启、飞行模式等选项,这是最常见的配置。
- 关机,但要确认
- 直接关机,不需要确认
其他值:不同的 Android 设备或定制系统可能会有额外的自定义行为对应其他值。
若要修改为长按后直接关机,可以通过修改xml来实现。
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
处理关机键按键:
上面函数会调到以下函数showGlobalActionsInternal
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
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {// 其它省略// SystemUI的窗口if (mGlobalActionsAvailable) {mHandler.postDelayed(mShowTimeout, 5000);mGlobalActionsProvider.showGlobalActions();//GlobalActionsProvider} else {// SysUI isn't alive, show legacy menu.// SystemUI未存活时弹这个窗口ensureLegacyCreated();mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);}}
注意上面代码有两个分支了,
- 默认调用的是SystemUI的窗口
- 如果其未存活则调用LegacyGlobalActions.java中的showDialog。
如果要自定义关机窗口,可以考虑在showDialog处修改,用自定义的Dialog实现,避免对两个分支都处理。当然也可以分别到两个分支的实现端分别修改处理。
SystemUI实现的关机窗口
mGlobalActionsProvider.showGlobalActions()其通过各种回调,调用到SystemUI下的代码,中间过程省略
frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@Overridepublic void showGlobalActions(GlobalActionsManager manager) {if (mDisabled) return;// GlobalActionsDialog GlobalActionsDialog.java 在 Android 系统里是一个相当关键的类,它主要负责展示全局操作对话框。mGlobalActionsDialog = mGlobalActionsDialogLazy.get();mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),mDeviceProvisionedController.isDeviceProvisioned(),mWalletPluginProvider.get());Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();}
./frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@VisibleForTestingprotected String[] getDefaultActions() {return mResources.getStringArray(R.array.config_globalActionsList);}......private void initializeLayout() {// layout xmlsetContentView(com.android.systemui.R.layout.global_actions_grid_v2);}@VisibleForTestingprotected void createActionItems() {String[] defaultActions = getDefaultActions();// ......// 这里addIfShouldShowAction会把需要的几个控件(比如关机,飞行模式等)加到UI中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)) {addIfShouldShowAction(tempActions, shutdownAction);} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {addIfShouldShowAction(tempActions, mAirplaneModeOn);} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {// 像这个bugreport是有条件的if (shouldDisplayBugReport(currentUser.get())) {addIfShouldShowAction(tempActions, new BugReportAction());}}// .....}
从上面代码可以得到SystemUI关机窗口的layout文件是
frameworks/base/packages/SystemUI/res/layout/global_actions_grid_v2.xml
上面的按钮是通过R.array.config_globalActionsList定义的
frameworks/base/core/res/res/values/config.xml
<!-- Defines the default set of global actions. Actions may still be disabled or hidden basedon the current state of the device.Each item must be one of the following strings:"power" = Power off"settings" = An action to launch settings"airplane" = Airplane mode toggle"bugreport" = Take bug report, if available"silent" = silent mode"users" = list of users"restart" = restart device"emergency" = Launch emergency dialer"lockdown" = Lock down device until the user authenticates"logout" = Logout the current user--><string-array translatable="false" name="config_globalActionsList"><item>emergency</item><item>lockdown</item><item>power</item><item>restart</item><item>logout</item><item>bugreport</item><item>screenshot</item></string-array>
当前定义的操作项包括:
- emergency:紧急拨号
- lockdown:设备锁定(需验证身份才能解锁)
- power:关机
- restart:重启设备
- ogout:当前用户登出
- bugreport:生成 bug 报告(通常仅开发者模式可见)
- screenshot:截图
操作项的可用性受系统状态限制(如 logout 仅多用户模式有效)
bugreport 通常需要开启开发者模式才会显示。
LegacyGlobalActions实现的关机窗口
简介
LegacyGlobalActions.java 是 Android 系统 Framework 层里的一个关键类,它主要负责管理和展示系统的全局操作菜单。这个菜单一般会在用户长按电源键时弹出,包含诸如关机、重启、飞行模式等操作选项。
功能概述
- 操作菜单管理:对全局操作菜单中的各个操作选项进行管理,像添加、删除、更新操作选项等。
- 界面显示与交互:负责全局操作菜单的显示,处理用户对操作选项的点击事件。
- 系统操作执行:当用户点击某个操作选项时,执行相应的系统操作,例如关机、重启等。
frameworks/base/services/core/java/com/android/server/policy/LegacyGlobalActions.java
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {mKeyguardShowing = keyguardShowing;mDeviceProvisioned = isDeviceProvisioned;if (mDialog != null) {mDialog.dismiss();mDialog = null;// Show delayed, so that the dismiss of the previous dialog completesmHandler.sendEmptyMessageDelayed(MESSAGE_SHOW,SHOW_DIALOG_DELAY);//unisoc: fix for bug 1136724} else {handleShow(); // 这个函数会执行弹可选关机或重启的窗口}}// 显示由此函数实现private void handleShow() {if(mHandler != null && mHandler.hasMessages(MESSAGE_SHOW)) {Log.d(TAG, "delayed show dialog message.");return;}awakenIfNecessary();mDialog = createDialog(); // 这里是创建窗口的函数prepareDialog();// If we only have 1 item and it's a simple press action, just do this action.if (mAdapter.getCount() == 1&& mAdapter.getItem(0) instanceof SinglePressAction&& !(mAdapter.getItem(0) instanceof LongPressAction)) {((SinglePressAction) mAdapter.getItem(0)).onPress();} else {if (mDialog != null) {WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();attrs.setTitle("LegacyGlobalActions");mDialog.getWindow().setAttributes(attrs);mDialog.show();mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);}}}// createDialog就是创建了一个ActionsDialog,在 Android 系统中,ActionsDialog.java 通常用于创建和管理包含多个操作选项的对话框,这种对话框一般会在用户进行某些操作时弹出,为用户提供一系列可选择的操作,例如长按电源键弹出的包含关机、重启、飞行模式等选项的对话框。
private ActionsDialog createDialog() {// 其它省略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;
}
可以看出LegacyGlobalActions的关机窗口是由createDialog函数中创建的ActionsDialog实现的。
作者:帅得不敢出门