最近项目中接触到需要修改手机按键的需求,整理一下分享给大家
双击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);
}
}
原生双击启动相机流程差不多就是这样,有任何问题欢迎留言讨论
网友评论