文章目录
长按关机流程
frameworks/base/core/res/res/values/config.xml
这个xml中指定了长按电源键的处理方式
<!-- Control the behavior when the user long presses the power button.
0 - Nothing
1 - Global actions menu
2 - Power off (with confirmation)
3 - Power off (without confirmation)
4 - Go to voice assist
5 - 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
java
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
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
java
@Override
public 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
java
@VisibleForTesting
protected String[] getDefaultActions() {
return mResources.getStringArray(R.array.config_globalActionsList);
}
......
private void initializeLayout() {
// layout xml
setContentView(com.android.systemui.R.layout.global_actions_grid_v2);
}
@VisibleForTesting
protected 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
xml
<!-- Defines the default set of global actions. Actions may still be disabled or hidden based
on 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
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 completes
mHandler.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() {
@Override
public 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 bugreports
dialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM);
dialog.setOnDismissListener(this);
return dialog;
}
可以看出LegacyGlobalActions的关机窗口是由createDialog函数中创建的ActionsDialog实现的。
作者:帅得不敢出门