这一次我们来分析下home的源码。
1. dispatchUnhandledKey()
我们知道,在系统级别的按键处理都在PhoneWindowManager.java-->dispatchUnhandledKey()函数中进行处理的,我们看
f (!interceptFallback(win, fallbackEvent, policyFlags))
这一个判断,其实这里包含了很多信息,我们来看
private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
if ((actions & ACTION_PASS_TO_USER) != 0) {
long delayMillis = interceptKeyBeforeDispatching(
win, fallbackEvent, policyFlags);
.........
return false;
}
是不是觉得在这个地方很熟悉”interceptKeyBeforeDispatching()”,
进入到这个函数里来看,
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
if (keyCode == KeyEvent.KEYCODE_HOME) {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (!down) {
cancelPreloadRecentApps();
mHomePressed = false;
if (mHomeConsumed) {
mHomeConsumed = false;
return -1;
}
if (canceled) {
Log.i(TAG, "Ignoring HOME; event canceled.");
return -1;
}
// Delay handling home if a double-tap is possible.
if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
mHomeDoubleTapPending = true;
mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
ViewConfiguration.getDoubleTapTimeout());
return -1;
}
handleShortPressOnHome();
return -1;
}
// If a system window has focus, then it doesn't make sense
// right now to interact with applications.
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
|| (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// the "app" is keyguard, so give it the key
return 0;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
return -1;
}
}
}
// Remember that home is pressed and handle special actions.
if (repeatCount == 0) {
mHomePressed = true;
}
.......
handleShortPressOnHome();
.......
handleLongPressOnHome();
.............
}
其实在这段代码中,核心的只有两个地方,
短按: handleShortPressOnHome();
长按: handleLongPressOnHome();
这就处理了home的两个状态值,这是整个系统所有的一个很关键的地方,下面,我们分别来重点关注一下这两个地方。
- handleShortPressOnHome()
private void handleShortPressOnHome() {
......
// Go home!
launchHomeFromHotKey();
}
这里的注释已经说明了很多问题,直接返回launcher桌面。
- handleLongPressOnHome()
private void handleLongPressOnHome() {
.....
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
toggleRecentApps();
} else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_ASSIST) {
launchAssistAction();
}
}
}
从上面的调用来看,
toggleRecentApps()关闭最近使用的app;
launchAssistAction()提示没有最近使用的app;
附录堆栈信息:
at com.android.internal.policy.impl.PhoneWindowManager.dispatchUnhandledKey(PhoneWindowManager.java:3019)
at com.android.server.wm.InputMonitor.dispatchUnhandledKey(InputMonitor.java:581)
at com.android.server.input.InputManagerService.dispatchUnhandledKey(InputManagerService.java:1553