這一次我們來分析下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