Android 短按两次Power键打开相机
RK3368 Android6.0
今天 12.31 有点搞笑 有测试人员反馈 短按power键 会跳转到camera2
先看了一下日志 确实跳转到了camera2 把东西捋了一下 问了一下 硬件(一度怀疑power的键值是不是改变了) 硬件说要拿烙铁帮我看一下日志 哈哈哈
一.日志先上
12-31 15:06:45.716 GestureLauncherService( 586): Power button double tap gesture detected, launching camera. Interval=240ms 噫
12-31 15:06:45.959 ActivityManager( 586): START u0 {act=android.media.action.STILL_IMAGE_CAMERA
12-31 15:06:45.476 W/TelecomManager( 586): Telecom Service not found.
12-31 15:06:45.624 D/XHApiManager( 586): enter XHApiManager
12-31 15:06:45.625 I/PowerManagerService( 586): Going to sleep due to power button (uid 1000)...
12-31 15:06:45.627 I/PowerManagerService( 586): Sleeping (uid 1000)...
12-31 15:06:45.715 D/XHApiManager( 586): enter XHApiManager
12-31 15:06:45.716 W/TelecomManager( 586): Telecom Service not found.
12-31 15:06:45.716 I/GestureLauncherService( 586): Power button double tap gesture detected, launching camera. Interval=240ms
12-31 15:06:45.717 I/PowerManagerService( 586): Waking up from sleep (uid 1000)...
12-31 15:06:45.733 D/SensorsHal( 586): Couldn't open /dev/mma8452_daemon (No such file or directory)
12-31 15:06:45.733 E/SensorService( 586): Error activating sensor 0 (Operation not permitted)
12-31 15:06:45.734 V/KeyguardServiceDelegate( 586): onStartedWakingUp()
12-31 15:06:45.749 D/WifiConfigStore( 586): Retrieve network priorities before PNO. Max priority: 0
12-31 15:06:45.751 D/XHService( 586): receiver intent :android.intent.action.SCREEN_OFF
12-31 15:06:45.751 E/WifiStateMachine( 586): Fail to set up pno, want true now false
12-31 15:06:45.776 E/native ( 586): do suspend true
12-31 15:06:45.779 I/ActivityManager( 586): START u0 {act=android.media.action.STILL_IMAGE_CAMERA flg=0x14000000 cmp=com.android.camera2/com.android.camera.CameraActivity} from uid 10011 on display 0
1.1.frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java
power键值
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
power键按下
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
if (!mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.acquire();
}
// Cancel multi-press detection timeout.
if (mPowerKeyPressCounter != 0) {
mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
}
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
}
// Latch power key state to detect screenshot chord.
if (interactive && !mScreenshotChordPowerKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordPowerKeyTriggered = true;
mScreenshotChordPowerKeyTime = event.getDownTime();
interceptScreenshotChord();
}
// Stop ringing or end call if configured to do so when power is pressed.
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
telecomManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telecomManager.isInCall() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telecomManager.endCall();
}
}
GestureLauncherService gestureService = LocalServices.getService(
GestureLauncherService.class);
boolean gesturedServiceIntercepted = false;
if (gestureService != null) {
gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
}
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
|| mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
if (!mPowerKeyHandled) {
if (interactive) {
// When interactive, we're already awake.
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
} else {
wakeUpFromPowerKey(event.getDownTime());
if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
mBeganFromNonInteractive = true;
} else {
final int maxCount = getMaxMultiPressPowerCount();
if (maxCount <= 1) {
mPowerKeyHandled = true;
} else {
mBeganFromNonInteractive = true;
}
}
}
}
}
1.2.frameworks\base\services\core\java\com\android\server\GestureLauncherService.java
双击拉起camera2 mCameraDoubleTapPowerEnabled && 判断距离上一次按键时间
mCameraDoubleTapPowerEnabled ->isCameraDoubleTapPowerSettingEnabled->Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED
updateCameraDoubleTapPowerEnabled
private void updateCameraDoubleTapPowerEnabled() {
boolean enabled = isCameraDoubleTapPowerSettingEnabled(mContext, mUserId);
synchronized (this) {
mCameraDoubleTapPowerEnabled = enabled;
isCameraDoubleTapPowerSettingEnabled
public static boolean isCameraDoubleTapPowerSettingEnabled(Context context, int userId) {
return isCameraDoubleTapPowerEnabled(context.getResources())
&& (Settings.Secure.getIntForUser(context.getContentResolver(),
Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, userId) == 0);
}
interceptPowerKeyDown
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
boolean launched = false;
boolean intercept = false;
long doubleTapInterval;
synchronized (this) {
doubleTapInterval = event.getEventTime() - mLastPowerDown;
if (mCameraDoubleTapPowerEnabled
&& doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS
&& doubleTapInterval > CAMERA_POWER_DOUBLE_TAP_MIN_TIME_MS) {
launched = true;
intercept = interactive;
}
mLastPowerDown = event.getEventTime();
}
if (launched) {
Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval="
+ doubleTapInterval + "ms");
launched = handleCameraLaunchGesture(false /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
if (launched) {
MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
(int) doubleTapInterval);
}
}
MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
return intercept && launched;
}
handleCameraGesture 拉起相机
/**
* @return true if camera was launched, false otherwise.
*/
private boolean handleCameraLaunchGesture(boolean useWakelock, int source) {
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
if (!userSetupComplete) {
if (DBG) Slog.d(TAG, String.format(
"userSetupComplete = %s, ignoring camera launch gesture.",
userSetupComplete));
return false;
}
if (DBG) Slog.d(TAG, String.format(
"userSetupComplete = %s, performing camera launch 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;
}

浙公网安备 33010602011771号