文章目录
- 需求场景
- 参考资料
- 源码分析
-
- 按键长按流程
-
- 查看配置
- 加载长按配置
- SingleKeyGestureDetector 手势按键
- 长按回调
- powerLongPress
- showGlobalActions()
- showGlobalActionsInternal()
- mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
- mGlobalActionsProvider
- LocalService
- 回归到:mGlobalActionsProvider
- StatusBarManagerService
- IStatusBar
- CentralSurfacesImpl.java
- CommandQueue
- handleShowGlobalActionsMenu
- GlobalActionsComponent
- GlobalActionsImpl
- 总结
需求场景
应用层模拟实现 物理Power按键长按功能。用户关机、重启界面功能就不需要再长按物理按键了
需求的目的:
- 物理按键长按到弹框的逻辑源码流程梳理:因为弹框是在SystemUI
里面的一个弹框,按键反馈是在Framework里面的。外部调用是在其它app或者也在Framework里面的。如何模调用或者间接调用SystemUI里面的成功提醒弹框。 - 举了一个例子,物理按键流程和SystemUI调用,整体梳理起来。
参考资料
个人以前写得总结,可参考,就是让两个东西融合进来,进一步整理。
KeyCode及KeyCode分发机制
MTK Android12 关机界面全屏展示
其它参考资料:
Android U Input 系统:单按键手势功能
RK3568 Android12 长按power键功能设置
Android11 关机界面修改-Android关机界面
源码分析
按键长按流程
关注PhoneWindowManager.java 长按相关的常量
// must match: config_LongPressOnPowerBehavior in config.xml
// The config value can be overridden using Settings.Global.POWER_BUTTON_LONG_PRESS
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4;
static final int LONG_PRESS_POWER_ASSISTANT = 5; // Settings.Secure.ASSISTANT
// must match: config_veryLongPresOnPowerBehavior in config.xml
// The config value can be overridden using Settings.Global.POWER_BUTTON_VERY_LONG_PRESS
static final int VERY_LONG_PRESS_POWER_NOTHING = 0;
static final int VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
查看配置
frameworks/base/core/res/res/values/config.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">5</integer>
举例,不同的默认显示不同的效果,下面实际配置后的显示如下。
比如1 和 2 的配置,分别显示如下:
参考
所以, 在实际项目中的配置根据项目需要进行配置,这里我们项目配置的是1
加载长按配置
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
获取当前长按配置:
private int getResolvedLongPressOnPowerBehavior() {
if (FactoryTest.isLongPressOnPowerOffEnabled()) {
return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
}
// If the config indicates the assistant behavior but the device isn't yet provisioned, show
// global actions instead.
if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_ASSISTANT && !isDeviceProvisioned()) {
return LONG_PRESS_POWER_GLOBAL_ACTIONS;
}
// If long press to launch assistant is disabled in settings, do nothing.
if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_GO_TO_VOICE_ASSIST
&& !isLongPressToAssistantEnabled(mContext)) {
return LONG_PRESS_POWER_NOTHING;
}
return mLongPressOnPowerBehavior;
}
是否有长按配置:
private boolean hasLongPressOnPowerBehavior() {
return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
}
SingleKeyGestureDetector 手势按键
SingleKeyGestureDetector 在线源码
手势按键,就说这个Power按键的功能逻辑判断都是在这里封装的。短按/长按/双击/多次单击的 逻辑判断。
长按回调
回归到PhoneWindowManager 类的中回调Power长按事件
@Override
void onLongPress(long eventTime) {
if (mSingleKeyGestureDetector.beganFromNonInteractive()
&& !mSupportLongPressPowerWhenNonInteractive) {
Slog.v(TAG, "Not support long press power when device is not interactive.");
return;
}
powerLongPress(eventTime); //最终指向:powerLongPress
}
一个内部类实现:
/**
* Rule for single power key gesture.
*/
private final class PowerKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
PowerKeyRule() {
super(KEYCODE_POWER);
}
@Override
boolean supportLongPress() {
return hasLongPressOnPowerBehavior();
}
@Override
boolean supportVeryLongPress() {
return hasVeryLongPressOnPowerBehavior();
}
@Override
int getMaxMultiPressCount() {
return getMaxMultiPressPowerCount();
}
@Override
void onPress(long downTime, int displayId) {
if (mShouldEarlyShortPressOnPower) {
return;
}
powerPress(downTime, 1 /*count*/, displayId);
}
@Override
long getLongPressTimeoutMs() {
if (getResolvedLongPressOnPowerBehavior() == LONG_PRESS_POWER_ASSISTANT) {
return mLongPressOnPowerAssistantTimeoutMs;
} else {
return super.getLongPressTimeoutMs();
}
}
@Override
void onLongPress(long eventTime) {
if (mSingleKeyGestureDetector.beganFromNonInteractive()
&& !mSupportLongPressPowerWhenNonInteractive) {
Slog.v(TA