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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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键值
1 2 3 4 5 6 7 8 9 | 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键按下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 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
1 2 3 4 5 | private void updateCameraDoubleTapPowerEnabled() { boolean enabled = isCameraDoubleTapPowerSettingEnabled(mContext, mUserId); synchronized ( this ) { mCameraDoubleTapPowerEnabled = enabled; |
isCameraDoubleTapPowerSettingEnabled
1 2 3 4 5 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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 拉起相机
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /** * @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 ; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】