最近项目中接触到需要修改手机按键的需求,整理一下分享给大家
双击power键大概流程
PhoneWindowManager.java类是 处理各种 power 键流程的地方,路径如下:
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
关键代码:
case KeyEvent.KEYCODE_POWER: { EventLogTags.writeInterceptPower( KeyEvent.actionToString(event.getAction()), mPowerKeyHandled ? 1 : 0, mSingleKeyGestureDetector.getKeyPressCounter(KeyEvent.KEYCODE_POWER)); // Any activity on the power button stops the accessibility shortcut result &= ~ACTION_PASS_TO_USER; isWakeKey = false; // wake-up will be handled separately if (down) { /*SPRD : add power debug log start*/ Slog.d(TAG, "Receive Input KeyEvent of Powerkey down"); /*SPRD : add power debug log end*/ interceptPowerKeyDown(event, interactiveAndOn); } else { /*SPRD : add power debug log start*/ Slog.d(TAG, "Receive Input KeyEvent of Powerkey up"); /*SPRD : add power debug log end*/ interceptPowerKeyUp(event, canceled); } break; }
power键按下在interceptPowerKeyDown()执行,松开的操作在interceptPowerKeyUp()中执行interceptPowerKeyDown()方法中会调用GestureLauncherService.java的 interceptPowerKeyDown()
方法
关键代码:
// The camera gesture will be detected by GestureLauncherService. private boolean handleCameraGesture(KeyEvent event, boolean interactive) { // camera gesture. if (mGestureLauncherService == null) { return false; } mCameraGestureTriggered = false; final MutableBoolean outLaunched = new MutableBoolean(false); final boolean intercept = mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched); if (!outLaunched.value) { // If GestureLauncherService intercepted the power key, but didn't launch camera app, // we should still return the intercept result. This prevents the single key gesture // detector from processing the power key later on. return intercept; } mCameraGestureTriggered = true; if (mRequestedOrSleepingDefaultDisplay) { mCameraGestureTriggeredDuringGoingToSleep = true; } return true; }
跟踪看看GestureLauncherService.java 中 执行 **interceptPowerKeyDown()**方法如下
GestureLauncherService.java,路径如下:
frameworks/base/services/core/java/com/android/server/GestureLauncherService.java
关键代码:
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, MutableBoolean outLaunched, boolean isScreenOn) { if (event.isLongPress()) { // Long presses are sent as a second key down. If the long press threshold is set lower // than the double tap of sequence interval thresholds, this could cause false double // taps or consecutive taps, so we want to ignore the long press event. return false; } boolean launchCamera = false; boolean launchEmergencyGesture = false; boolean intercept = false; long powerTapInterval; synchronized (this) { powerTapInterval = event.getEventTime() - mLastPowerDown; mLastPowerDown = event.getEventTime(); if (powerTapInterval >= POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) { // Tap too slow, reset consecutive tap counts. mPowerButtonConsecutiveTaps = 1; mPowerButtonSlowConsecutiveTaps = 1; } else if (powerTapInterval >= CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { // Tap too slow for shortcuts mPowerButtonConsecutiveTaps = 1; mPowerButtonSlowConsecutiveTaps++; } else { // Fast consecutive tap mPowerButtonConsecutiveTaps++; mPowerButtonSlowConsecutiveTaps++; } // Check if we need to launch camera or emergency gesture flows if (mEmergencyGestureEnabled) { // Commit to intercepting the powerkey event after the second "quick" tap to avoid // lockscreen changes between launching camera and the emergency gesture flow. if (mPowerButtonConsecutiveTaps > 1) { intercept = interactive; } if (mPowerButtonConsecutiveTaps == EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD) { launchEmergencyGesture = true; } } if (mCameraDoubleTapPowerEnabled && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS && mPowerButtonConsecutiveTaps == CAMERA_POWER_TAP_COUNT_THRESHOLD) { launchCamera = true; intercept = interactive; } } if (mPowerButtonConsecutiveTaps > 1 || mPowerButtonSlowConsecutiveTaps > 1) { Slog.i(TAG, Long.valueOf(mPowerButtonConsecutiveTaps) + " consecutive power button taps detected, " + Long.valueOf(mPowerButtonSlowConsecutiveTaps) + " consecutive slow power button taps detected"); } if (launchCamera) { Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" + powerTapInterval + "ms"); // 调用开启相机 launchCamera = handleCameraGesture(false /* useWakelock */, StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); if (launchCamera) { mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) powerTapInterval); mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); } } else if (launchEmergencyGesture) { Slog.i(TAG, "Emergency gesture detected, launching."); launchEmergencyGesture = handleEmergencyGesture(); mUiEventLogger.log(GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); } mMetricsLogger.histogram("power_consecutive_short_tap_count", mPowerButtonSlowConsecutiveTaps); mMetricsLogger.histogram("power_double_tap_interval", (int) powerTapInterval); outLaunched.value = launchCamera || launchEmergencyGesture; // Intercept power key event if the press is part of a gesture (camera, eGesture) and the // user has completed setup. return intercept && isUserSetupComplete(); }
系统会对mCameraDoubleTapPowerEnabled 取值,核心是通过resources.getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled) 来取,
其实这个值是配置在/frameworks/base/core/res/res/values/config.xml中,这里是为true的
<!-- Allow the gesture to double tap the power button twice to start the camera while the device is non-interactive. --> <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool>
接下来会分别对power连续按2或者1次进行判断,如果mCameraDoubleTapPowerEnabled = true 会通过比较按键的时间powerTapInterval小于系统默认时间
(CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS=300毫秒),
mPowerButtonConsecutiveTaps计数加1,说明连续按power键,或者延迟最大500毫秒内连续按键,系统预计用户接下来可能会执行一些操作,计数也会加1
static final long POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS = 500; static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; powerTapInterval = event.getEventTime() - mLastPowerDown; mLastPowerDown = event.getEventTime(); if (mCameraDoubleTapPowerEnabled && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS && mPowerButtonConsecutiveTaps == CAMERA_POWER_TAP_COUNT_THRESHOLD) if (powerTapInterval < POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS)
执行完成之后会调用handleCameraGesture()方法调用开启摄像机。
@VisibleForTesting boolean handleCameraGesture(boolean useWakelock, int source) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "GestureLauncher:handleCameraGesture"); try { boolean userSetupComplete = isUserSetupComplete(); if (!userSetupComplete) { if (DBG) { Slog.d(TAG, String.format( "userSetupComplete = %s, ignoring camera gesture.", userSetupComplete)); } return false; } if (DBG) { Slog.d(TAG, String.format( "userSetupComplete = %s, performing camera gesture.", userSetupComplete)); } if (useWakelock) { // Make sure we don't sleep too early mWakeLock.acquire(500L); } StatusBarManagerInternal service = LocalServices.getService( StatusBarManagerInternal.class); // 启动相机 service.onCameraLaunchGestureDetected(source); return true; } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }