序言:
1.所有FW系列的知识,皆基于Android 12。
2.PhoneWindowManager简称PWM。
3.PWM有超过6千行代码,不一一讲解,将分数篇,讲解不同事件的处理。
本篇将讲解Power事件的初始化流程,以及事件拦截。
一,PhoneWindowManager 是什么?
PWM负责Window System与FW的通信,处理与设备展示相关的事件。包括窗口管理,触摸事件,点击事件,以及Power键相关的事件处理。
二,Power键的初始化流程。
- 初始化入口:init(Context , WindowManagerFuncs )
/** {@inheritDoc} */
@Override
public void init(Context context, WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManagerFuncs = windowManagerFuncs;
// 代码省略...
// 初始化单个按键监听(也有组合键监听,不在此篇范畴)
initSingleKeyGestureRules();
// 代码省略...
}
- 注册单按键监听:initSingleKeyGestureRules()
private void initSingleKeyGestureRules() {
/**
* 初始化单键手势监听类,这里get(Context)的实现,
* 并非我们预想的单例模式,而是为了方便初始化一些静态变量。
* 详情可查对应方法,这里不赘述。
**/
mSingleKeyGestureDetector = SingleKeyGestureDetector.get(mContext);
int powerKeyGestures = 0;
// 判断当前设备是否支持Power键超长按事件
if (hasVeryLongPressOnPowerBehavior()) {
powerKeyGestures |= KEY_VERYLONGPRESS;
}
// 判断当前设备是否支持Power键长按事件
if (hasLongPressOnPowerBehavior()) {
powerKeyGestures |= KEY_LONGPRESS;
}
// 添加Power按键监听
mSingleKeyGestureDetector.addRule(new PowerKeyRule(powerKeyGestures));
// 判断当前设备是否支持长按Back事件
if (hasLongPressOnBackBehavior()) {
// 如果支持,则添加监听。
mSingleKeyGestureDetector.addRule(new BackKeyRule(KEY_LONGPRESS));
}
// 暂时未知这个StemPrimary是干嘛用的,先忽略
if (hasStemPrimaryBehavior()) {
int stemPrimaryKeyGestures = 0;
if (hasLongPressOnStemPrimaryBehavior()) {
stemPrimaryKeyGestures |= KEY_LONGPRESS;
}
mSingleKeyGestureDetector.addRule(new StemPrimaryKeyRule(stemPrimaryKeyGestures));
}
}
- 私有内部类: PowerKeyRule。 这个类,注册了多个事件监听,这里,我们仅讲解长按事件,其它的事件,原理相近,不再赘述。
/**
* 监听Power按键
*/
private final class PowerKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
PowerKeyRule(int gestures) {
super(KEYCODE_POWER, gestures);
}
@Override
int getMaxMultiPressCount() {
return getMaxMultiPressPowerCount();
}
@Override
void onPress(long downTime) {
powerPress(downTime, 1 /*count*/,
mSingleKeyGestureDetector.beganFromNonInteractive());
}
@Override
long getLongPressTimeoutMs() {
if (getResolvedLongPressOnPowerBehavior() == LONG_PRESS_POWER_ASSISTANT) {
return mLongPressOnPowerAssistantTimeoutMs;
} else {
return super.getLongPressTimeoutMs();
}
}
// Power键长按事件
@Override
void onLongPress(long eventTime) {
// 1. 判断用户当前是否有在使用设备,如果没有则返回。
// 没有使用的情况包括:屏幕未解锁,息屏等。
// 2.mSupportLongPressPowerWhenNonInteractive 为true时,
// 就算没有在使用设备,也会触发powerLongPress(eventTime);
if (mSingleKeyGestureDetector.beganFromNonInteractive()
&& !mSupportLongPressPowerWhenNonInteractive) {
Slog.v(TAG, "Not support long press power when device is not interactive.");
return;
}
// 长按Power键事件处理
powerLongPress(eventTime);
}
@Override
void onVeryLongPress(long eventTime) {
mActivityManagerInternal.prepareForPossibleShutdown();
powerVeryLongPress();
}
@Override
void onMultiPress(long downTime, int count) {
powerPress(downTime, count, mSingleKeyGestureDetector.beganFromNonInteractive());
}
}
- 长按Power事件处理方法: powerLongPress。
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_POWER_BUTTON, 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_POWER_BUTTON, 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_POWER_BUTTON, 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;
}
}
如上面代码所示,如果需要,在关机前处理一些逻辑,比如,Show个Dialog或做其它业务操作,可以在这个地方,加处理逻辑。但需要注意的是,需要在onPowerKeyHandled = true; 后面添加,不然,有可能会导致interceptKeyUp的handled值不正确。
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
// 标记事件已处理
mPowerKeyHandled = true;
// 添加其它业务逻辑
// 关机和震动代码
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power - Long Press - Shut Off");
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
break;