美文网首页Android进阶之路Android技术知识
Android 13 双击power键唤起安全相机

Android 13 双击power键唤起安全相机

作者: 孤街酒客0911 | 来源:发表于2023-01-17 16:43 被阅读0次

    事件处理主要都是在 PhoneWindowManager.java 中,电源键处理在 PhoneWindowManager#interceptKeyBeforeQueueing() 中:

    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
     
            // 省略部分代码......
            if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                Log.d(TAG,"handleKeyGesture +000");
                handleKeyGesture(event, interactiveAndOn);
            }
            // 省略部分代码......
    }
     
    
        private void handleKeyGesture(KeyEvent event, boolean interactive) {
            // 省略部分代码......
            if (event.getKeyCode() == KEYCODE_POWER && event.getAction() == KeyEvent.ACTION_DOWN) {
                mPowerKeyHandled = handleCameraGesture(event, interactive);
                if (mPowerKeyHandled) {
                    // handled by camera gesture.
                    mSingleKeyGestureDetector.reset();
                    return;
                }
            }
     
            mSingleKeyGestureDetector.interceptKey(event, interactive);
        }
     
    
        // The camera gesture will be detected by GestureLauncherService.
        private boolean handleCameraGesture(KeyEvent event, boolean interactive) {
            // camera gesture.
            // 省略部分代码......
            final boolean intercept =
                    mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);
            // 省略部分代码......
        } 
    

    接着看GestureLauncherService.java

        public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
                MutableBoolean outLaunched) {
            // 省略部分代码......
     
            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);
            }
            // 省略部分代码......
        }
     
    
        @VisibleForTesting
        boolean handleCameraGesture(boolean useWakelock, int source) {
            // 省略部分代码......
                if (useWakelock) {
                    // Make sure we don't sleep too early
                    mWakeLock.acquire(500L);
                }
                StatusBarManagerInternal service = LocalServices.getService(
                        StatusBarManagerInternal.class);
                service.onCameraLaunchGestureDetected(source);
                return true;
            // 省略部分代码......
        }
    

    StatusBarManagerInternal.java 是一个 interface 接口,实现在 StatusBarManagerService.java 。
    StatusBarManagerService#onCameraLaunchGestureDetected()

            @Override
            public void onCameraLaunchGestureDetected(int source) {
                if (mBar != null) {
                    try {
                        mBar.onCameraLaunchGestureDetected(source);
                    } catch (RemoteException e) {
                    }
                }
            }
    

    mBar 是 IStatusBar 对象,被 CommandQueue.java 继承;CentralSurfacesCommandQueueCallbacks 又继承了实现了 CommandQueue.Callbacks,最终下一步会调用到 CentralSurfacesCommandQueueCallbacks#onCameraLaunchGestureDetected()

        public void onCameraLaunchGestureDetected(int source) {
            mCentralSurfaces.setLastCameraLaunchSource(source);
            if (mCentralSurfaces.isGoingToSleep()) {
                if (CentralSurfaces.DEBUG_CAMERA_LIFT) {
                    Slog.d(CentralSurfaces.TAG, "Finish going to sleep before launching camera");
                }
                mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true);
                return;
            }
            if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
                if (CentralSurfaces.DEBUG_CAMERA_LIFT) {
                    Slog.d(CentralSurfaces.TAG, "Can't launch camera right now");
                }
                return;
            }
            if (!mCentralSurfaces.isDeviceInteractive()) {
                mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                        "com.android.systemui:CAMERA_GESTURE");
            }
            vibrateForCameraGesture();
    
            if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
                Log.v(CentralSurfaces.TAG, "Camera launch");
                // 屏蔽人脸或者指纹解锁
                mKeyguardUpdateMonitor.onCameraLaunched();
            }
    
            if (!mStatusBarKeyguardViewManager.isShowing()) {
                final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
                mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent,
                        false /* onlyProvisioned */, true /* dismissShade */,
                        true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
                        null /* animationController */, UserHandle.CURRENT);
            } else {
                if (!mCentralSurfaces.isDeviceInteractive()) {
                    // 当我们立即启动相机并且弹跳器启动时,避免稀松布闪烁                
                    mCentralSurfaces.acquireGestureWakeLock(
                            CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
                }
                if (isWakingUpOrAwake()) {
                    if (CentralSurfaces.DEBUG_CAMERA_LIFT) {
                        Slog.d(CentralSurfaces.TAG, "Launching camera");
                    }
                    if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                        mStatusBarKeyguardViewManager.reset(true /* hide */);
                    }
                    // 启动相机
                    mNotificationPanelViewController.launchCamera(mCentralSurfaces.isDeviceInteractive() /* animate */, source);
    
                    mCentralSurfaces.updateScrimController();
                } else {
    
                    if (CentralSurfaces.DEBUG_CAMERA_LIFT) {
                        Slog.d(CentralSurfaces.TAG, "Deferring until screen turns on");
                    }
                    mCentralSurfaces.setLaunchCameraOnFinishedWaking(true);
                }
            }
        }
    

    再看 NotificationPanelViewController#launchCamera():

        public void launchCamera(boolean animate, int source) {
            if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
                mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
            } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
                mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
            } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) {
                mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER;
            } else {
                // Default.
                mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
            }
    
            if (!isFullyCollapsed()) {
                setLaunchingAffordance(true);
            } else {
                animate = false;
            }
            mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
            // 启动相机
            mAffordanceHelper.launchAffordance(
                    animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
        }
    

    接着看 KeyguardAffordanceHelper#launchAffordance():

        public void launchAffordance(boolean animate, boolean left) {
            if (mSwipingInProgress) {
                // We don't want to mess with the state if the user is actually swiping already.
                return;
            }
            KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
            KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
            startSwiping(targetView);
    
            // Do not animate the circle expanding if the affordance isn't visible,
            // otherwise the circle will be meaningless.
            if (targetView.getVisibility() != View.VISIBLE) {
                animate = false;
            }
    
            if (animate) {
                fling(0, false, !left);  // 这里面会回调 KeyguardAffordanceHelperCallback#onAnimationToSideStarted() 方法,去启动相机,并且里面有个动画。
                updateIcon(otherView, 0.0f, 0, true, false, true, false);
            } else {
                mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
                mTranslation = left ? mCallback.getMaxTranslationDistance()
                        : mCallback.getMaxTranslationDistance();
                updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
                targetView.instantFinishAnimation();
                mFlingEndListener.onAnimationEnd(null);
                mAnimationEndRunnable.run();
            }
        }
    

    当动画执行完成,则会执行 mAnimationEndRunnable.run(),进而回调到:KeyguardAffordanceHelperCallback#onAnimationToSideEnded(): 方法里

            public void onAnimationToSideEnded() {
                mIsLaunchTransitionRunning = false;
                mIsLaunchTransitionFinished = true;
                if (mLaunchAnimationEndRunnable != null) {
                    // 这里会去销毁密码锁界面、图案锁界面;
                    mLaunchAnimationEndRunnable.run();
                    mLaunchAnimationEndRunnable = null;
                }
                mCentralSurfaces.readyForKeyguardDone();
            }
    

    这里补充个流程: 在未解锁的情况下,打开临时占用的app,比如 相机,紧急拨号等会调用如下函数:

        public void setOccluded(boolean occluded, boolean animate) {
            final boolean isOccluding = !mOccluded && occluded;
            final boolean isUnOccluding = mOccluded && !occluded;
            setOccludedAndUpdateStates(occluded);
    
            if (mShowing && isOccluding) {
                SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
                        SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED);
                if (mCentralSurfaces.isInLaunchTransition()) {
                    final Runnable endRunnable = new Runnable() {
                        @Override
                        public void run() {
                            ///M: [ALPS01807921]
                            ///   mOccluded may be changed before the runnable is executed.
                            if (mOccluded) {
                                mNotificationShadeWindowController.setKeyguardOccluded(mOccluded);
                                reset(true /* hideBouncerWhenShowing */);
                            } else {
                                Log.d(TAG, "setOccluded.run() - mOccluded was set to false") ;
                            }
                        }
                    };
                    
                    mCentralSurfaces.fadeKeyguardAfterLaunchTransition(
                            null /* beforeFading */,
                            endRunnable,
                            endRunnable);
                    return;
                }
             // 省略部分代码......
        }
    
    

    相关文章

      网友评论

        本文标题:Android 13 双击power键唤起安全相机

        本文链接:https://www.haomeiwen.com/subject/opathdtx.html