1.功用描绘

双击电源键会快速翻开相机,这个很早就有的功用了。

2.相关类

>GestureLauncherService

frameworks/base/services/core/java/com/android/server/GestureLauncherService.java
现在只支持相机手势

/**
 * The service that listens for gestures detected in sensor firmware and starts the intent
 * accordingly.
 * <p>For now, only camera launch gesture is supported, and in the future, more gestures can be
 * added.</p>
 * @hide
 */
public class GestureLauncherService extends SystemService {
    private static final boolean DBG = false;
        @Override
    public void onStart() {
        LocalServices.addService(GestureLauncherService.class, this);
    }

这个类是在SystemService里调用的

            if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) {
                t.traceBegin("StartGestureLauncher");
                //这个主要是调用GestureLauncherService的onStart办法
                mSystemServiceManager.startService(GestureLauncherService.class);
                t.traceEnd();
            }

相关办法


    /**
     * Whether GestureLauncherService should be enabled according to system properties.
     */
    public static boolean isGestureLauncherEnabled(Resources resources) {
        return isCameraLaunchEnabled(resources)
                || isCameraDoubleTapPowerEnabled(resources)
                || isCameraLiftTriggerEnabled(resources)
                || isEmergencyGestureEnabled(resources);
    }

>> —

默许配置里id是-1,所以这儿的listener不会注册,

        int cameraLaunchGestureId = resources.getInteger(
                com.android.internal.R.integer.config_cameraLaunchGestureSensorType);
        if (cameraLaunchGestureId != -1) {

这个没有注册,不必研讨


    private final class GestureEventListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
            if (!mCameraLaunchRegistered) {
              return;
            }
            if (event.sensor == mCameraLaunchSensor) {
                if (handleCameraGesture(true /* useWakelock */,
                        StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
                    mMetricsLogger.action(MetricsEvent.ACTION_WIGGLE_CAMERA_GESTURE);
                    mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_WIGGLE);
                    trackCameraLaunchEvent(event);
                }
                return;
            }
        }

3.PhoneWindowManager.java

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java


/**
 * WindowManagerPolicy implementation for the Android phone UI.  This
 * introduces a new method suffix, Lp, for an internal lock of the
 * PhoneWindowManager.  This is used to protect some internal state, and
 * can be acquired with either the Lw and Li lock held, so has the restrictions
 * of both of those when held.
 */
public class PhoneWindowManager implements WindowManagerPolicy {

获取GestureLauncherService的实例

    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        mKeyguardDelegate.onSystemReady();
//...
        mGestureLauncherService = LocalServices.getService(GestureLauncherService.class);
    }

>handleCameraGesture

查下上述实例调用的当地

    // 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;
            // Wake device up early to prevent display doing redundant turning off/on stuff.
            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromPowerKey,
                    PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                    "android.policy:CAMERA_GESTURE_PREVENT_LOCK");
        }
        return true;
    }

>handleKeyGesture

继续检查上述办法在哪里被调用

    private void handleKeyGesture(KeyEvent event, boolean interactive) {
        if (mKeyCombinationManager.interceptKey(event, interactive)) {
            // handled by combo keys manager.
            mSingleKeyGestureDetector.reset();
            return;
        }
        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);
    }

>interceptKeyBeforeQueueing

继续检查handleKeyGesture办法的调用

    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        final int keyCode = event.getKeyCode();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
                || event.isWakeKey();
        if (!mSystemBooted) {
//系统还没发动的时候,不处理key event
            return 0;
        }
//...
        // Basic policy based on interactive state.
        int result;
        if (interactive || (isInjected && !isWakeKey)) {
            // When the device is interactive or the key is injected pass the
            // key to the application.
            result = ACTION_PASS_TO_USER;
            isWakeKey = false;
            if (interactive) {
                // If the screen is awake, but the button pressed was the one that woke the device
                // then don't pass it to the application
                if (keyCode == mPendingWakeKey && !down) {
                    result = 0;
                }
                // Reset the pending key
                mPendingWakeKey = PENDING_KEY_NULL;
            }
        } else if (shouldDispatchInputWhenNonInteractive(displayId, keyCode)) {
            // If we're currently dozing with the screen on and the keyguard showing, pass the key
            // to the application but preserve its wake key status to make sure we still move
            // from dozing to fully interactive if we would normally go from off to fully
            // interactive.
            result = ACTION_PASS_TO_USER;
            // Since we're dispatching the input, reset the pending key
            mPendingWakeKey = PENDING_KEY_NULL;
        } else {
            // When the screen is off and the key is not injected, determine whether
            // to wake the device but don't pass the key to the application.
            result = 0;
            if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
                isWakeKey = false;
            }
            // Cache the wake key on down event so we can also avoid sending the up event to the app
            if (isWakeKey && down) {
                mPendingWakeKey = keyCode;
            }
        }
        // If the key would be handled globally, just return the result, don't worry about special
        // key processing.
        if (isValidGlobalKey(keyCode)
                && mGlobalKeyManager.shouldHandleGlobalKey(keyCode)) {
            // Dispatch if global key defined dispatchWhenNonInteractive.
            if (!interactive && isWakeKey && down
                    && mGlobalKeyManager.shouldDispatchFromNonInteractive(keyCode)) {
                mGlobalKeyManager.setBeganFromNonInteractive();
                result = ACTION_PASS_TO_USER;
                // Since we're dispatching the input, reset the pending key
                mPendingWakeKey = PENDING_KEY_NULL;
            }
            if (isWakeKey) {
                wakeUpFromWakeKey(event);
            }
            return result;
        }
        // Alternate TV power to power key for Android TV device.
        final HdmiControlManager hdmiControlManager = getHdmiControlManager();
        if (keyCode == KeyEvent.KEYCODE_TV_POWER && mHasFeatureLeanback
                && (hdmiControlManager == null || !hdmiControlManager.shouldHandleTvPowerKey())) {
            event = KeyEvent.obtain(
                    event.getDownTime(), event.getEventTime(),
                    event.getAction(), KeyEvent.KEYCODE_POWER,
                    event.getRepeatCount(), event.getMetaState(),
                    event.getDeviceId(), event.getScanCode(),
                    event.getFlags(), event.getSource(), event.getDisplayId(), null);
                    //递归调用自己?
            return interceptKeyBeforeQueueing(event, policyFlags);
        }
        // This could prevent some wrong state in multi-displays environment,
        // the default display may turned off but interactive is true.
        final boolean isDefaultDisplayOn = Display.isOnState(mDefaultDisplay.getState());
        final boolean interactiveAndOn = interactive && isDefaultDisplayOn;
        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
        //这儿调用的
            handleKeyGesture(event, interactiveAndOn);
        }

>interceptFallback

继续查

    private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
            int policyFlags) {
            //这儿
        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
        if ((actions & ACTION_PASS_TO_USER) != 0) {
            long delayMillis = interceptKeyBeforeDispatching(
                    focusedToken, fallbackEvent, policyFlags);
            if (delayMillis == 0 && !interceptUnhandledKey(fallbackEvent)) {
                return true;
            }
        }
        return false;
    }

>dispatchUnhandledKey

继续

    public KeyEvent dispatchUnhandledKey(IBinder focusedToken, KeyEvent event, int policyFlags) {
        // Note: This method is only called if the initial down was unhandled.
        //...
        //这儿处理下3个特殊的键,空格,z键,system request键
        if (interceptUnhandledKey(event)) {
            return null;
        }
        KeyEvent fallbackEvent = null;
        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
            final KeyCharacterMap kcm = event.getKeyCharacterMap();
            final int keyCode = event.getKeyCode();
            final int metaState = event.getMetaState();
            final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getRepeatCount() == 0;
            // Check for fallback actions specified by the key character map.
            final FallbackAction fallbackAction;
            if (initialDown) {
                fallbackAction = kcm.getFallbackAction(keyCode, metaState);
            } else {
                fallbackAction = mFallbackActions.get(keyCode);
            }
            if (fallbackAction != null) {
                final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
                fallbackEvent = KeyEvent.obtain(
                        event.getDownTime(), event.getEventTime(),
                        event.getAction(), fallbackAction.keyCode,
                        event.getRepeatCount(), fallbackAction.metaState,
                        event.getDeviceId(), event.getScanCode(),
                        flags, event.getSource(), event.getDisplayId(), null);
//这儿调用的
                if (!interceptFallback(focusedToken, fallbackEvent, policyFlags)) {
                    fallbackEvent.recycle();
                    fallbackEvent = null;
                }
                if (initialDown) {
                    mFallbackActions.put(keyCode, fallbackAction);
                } else if (event.getAction() == KeyEvent.ACTION_UP) {
                    mFallbackActions.remove(keyCode);
                    fallbackAction.recycle();
                }
            }
        }
        return fallbackEvent;
    }

4.GestureLauncherService

>interceptPowerKeyDown

这个办法便是PhoneWindowManger类的handleCameraGesture办法里调用的

    /**
     * Attempts to intercept power key down event by detecting certain gesture patterns
     *
     * @param interactive true if the event's policy contains {@code FLAG_INTERACTIVE}
     * @param outLaunched true if some action is taken as part of the key intercept (eg, app launch)
     * @return true if the key down event is intercepted
     */
    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
            MutableBoolean outLaunched) {
            //先判别emergency手势相关
        if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0
                && event.getEventTime() - mLastEmergencyGestureTriggered
                < mEmergencyGesturePowerButtonCooldownPeriodMs) {
            outLaunched.value = false;
            return true;
        }
//长按的话不做处理
        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.
            outLaunched.value = false;
            return false;
        }
        boolean launchCamera = false;
        boolean launchEmergencyGesture = false;
        boolean intercept = false;
        long powerTapInterval;
        synchronized (this) {
            powerTapInterval = event.getEventTime() - mLastPowerDown;
            mLastPowerDown = event.getEventTime();
            两次距离大于300ms的,本次event当做初始事情
            if (powerTapInterval >= POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) {//500ms
                // Tap too slow, reset consecutive tap counts.
                mFirstPowerDown  = event.getEventTime();
                mPowerButtonConsecutiveTaps = 1;
                mPowerButtonSlowConsecutiveTaps = 1;
            } else if (powerTapInterval >= CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {//300ms
                // Tap too slow for shortcuts
                mFirstPowerDown  = event.getEventTime();
                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.
                // Since watch doesn't have camera gesture, only intercept power key event after
                // emergency gesture tap count.
                //feature watch 指的是手表,手表的话阈值是5次
                if (mPowerButtonConsecutiveTaps
                        > (mHasFeatureWatch ? EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD : 1)) {
                    intercept = interactive;
                }
                //连续点击等于5次
                if (mPowerButtonConsecutiveTaps == EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD) {
                    long emergencyGestureSpentTime = event.getEventTime() - mFirstPowerDown;
                    long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt(
                            mContext.getContentResolver(),
                            Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS,
                            EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS);
                    if (emergencyGestureSpentTime <= emergencyGestureTapDetectionMinTimeMs) {
// 连续点击太快了,比最小值还小,重置event为第一次点击
                        // Reset consecutive tap counts.
                        mFirstPowerDown = event.getEventTime();
                        mPowerButtonConsecutiveTaps = 1;
                        mPowerButtonSlowConsecutiveTaps = 1;
                    } else {
                     //触发紧急手势事情了
                        launchEmergencyGesture = true;
                        mMetricsLogger.histogram("emergency_gesture_spent_time",
                                (int) emergencyGestureSpentTime);
                    }
                }
            }
            //判别是否满意双击电源键翻开相机的条件
            //双击功用功用需要enable,再次2次点击距离小于300ms,继续点击次数是2
            if (mCameraDoubleTapPowerEnabled
                    && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS
                    && mPowerButtonConsecutiveTaps == CAMERA_POWER_TAP_COUNT_THRESHOLD) {
                launchCamera = true;
                intercept = interactive;
            }
        }
        if (launchCamera) {
//根据上边的判别满意双击翻开相机的逻辑
            launchCamera = handleCameraGesture(false /* useWakelock */,
                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
//...
        } else if (launchEmergencyGesture) {
            Slog.i(TAG, "Emergency gesture detected, launching.");
            //处理紧急事情
            launchEmergencyGesture = handleEmergencyGesture();
            // Record emergency trigger time if emergency UI was launched
            if (launchEmergencyGesture) {
                synchronized (this) {
                    mLastEmergencyGestureTriggered = event.getEventTime();
                }
            }
        }
        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();
    }

>handleCameraGesture

调用发动相机的逻辑,成功的话回来true,不然回来false。

    /**
     * @return true if camera was launched, false otherwise.
     */
    boolean handleCameraGesture(boolean useWakelock, int source) {
        try {
            boolean userSetupComplete = isUserSetupComplete();
            if (!userSetupComplete) {
//
                return false;
            }
            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 {
        }
    }

>handleEmergencyGesture

    /**
     * @return true if emergency gesture UI was launched, false otherwise.
     */
    boolean handleEmergencyGesture() {
        try {
            boolean userSetupComplete = isUserSetupComplete();
            if (!userSetupComplete) {
                return false;
            }
            if (mHasFeatureWatch) {
            //这个是手表的逻辑
                onEmergencyGestureDetectedOnWatch();
                return true;
            }
            StatusBarManagerInternal service = LocalServices.getService(
                    StatusBarManagerInternal.class);
            service.onEmergencyActionLaunchGestureDetected();
            return true;
        } finally {
        }
    }

5.StatusBarManagerInternal

翻开相机以及紧急事情都是这个类处理的,看一下,大部分都是经过一个mBar的对象来处理

    /**
     * Private API used by NotificationManagerService.
     */
    private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
        private boolean mNotificationLightOn;
        //
        public void onCameraLaunchGestureDetected(int source) {
            if (mBar != null) {
                try {
                    mBar.onCameraLaunchGestureDetected(source);
                } catch (RemoteException e) {
                }
            }
        }
        /**
         * Notifies the status bar that a Emergency Action launch gesture has been detected.
         */
        @Override
        public void onEmergencyActionLaunchGestureDetected() {
            if (mBar != null) {
                try {
                    mBar.onEmergencyActionLaunchGestureDetected();
                } catch (RemoteException e) {
                }
            }
        }

这个mBar是外部传进来的

    public RegisterStatusBarResult registerStatusBar(IStatusBar bar) {
        enforceStatusBarService();
        Slog.i(TAG, "registerStatusBar bar=" + bar);
        mBar = bar;

>IStatusBar来历

IStatusBar便是下边的那个CommandQueue(继承的IStatusBar.Stub),里面的办法终究又调用的callbacks里的办法

来历CentralSurfacesImpl.java

//结构办法里初始化的,注解生成的
    protected final CommandQueue mCommandQueue;
    @Override
    public void start() {
    //...StatusBarManagerService
        mBarService = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
//...
        RegisterStatusBarResult result = null;
        try {
            result = mBarService.registerStatusBar(mCommandQueue);
        } catch (RemoteException ex) {
            ex.rethrowFromSystemServer();
        }

mCommandQueue里增加的callback是CentralSurfacesCommandQueueCallbacks

    private void inflateStatusBarWindow() {
    //...
        if (mCommandQueueCallbacks != null) {
            mCommandQueue.removeCallback(mCommandQueueCallbacks);
        }
        mCommandQueueCallbacks =
                mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks();
        // Connect in to the status bar manager service
        mCommandQueue.addCallback(mCommandQueueCallbacks);

CentralSurfacesCommandQueueCallbacks

    CentralSurfacesCommandQueueCallbacks getCentralSurfacesCommandQueueCallbacks();

>CentralSurfacesCommandQueueCallbacks

这儿便是详细的翻开相机,以及紧急事情的处理逻辑了
下边的mCentralSurfaces便是CentralSurfacesImpl.java

@CentralSurfacesComponent.CentralSurfacesScope
public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callbacks {
    @Override
    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");
            }
            //修改了一个boolean值,在goingToSleep完毕的回调里用到,终究又调用了这个callbacks,详见参阅1
            mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true);
            return;
        }
        //判别相机是否可用,不可用的话直接return,详见参阅2
        if (!mCameraLauncherLazy.get().canCameraGestureBeLaunched(
                mNotificationPanelViewController.getBarState())) {
            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();
//我们双击电源键终究传递的source便是这个
        if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
            //告诉keyguard要翻开相机了,好更新一些状况
            mKeyguardUpdateMonitor.onCameraLaunched();
        }
//下边根据是否有键盘锁,翻开两种不同的camera task
        if (!mKeyguardStateController.isShowing()) {
        //没有键盘锁
        //发动普通相机的代码,详细参阅4
            final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
            cameraIntent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source);
            mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent,
                    false /* onlyProvisioned */, true /* dismissShade */,
                    true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
                    null /* animationController */, UserHandle.CURRENT);
        } else {
        //有键盘锁
            if (!mCentralSurfaces.isDeviceInteractive()) {
                // Avoid flickering of the scrim when we instant launch the camera and the bouncer
                // comes on.
                mCentralSurfaces.acquireGestureWakeLock(
                        CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
            }
            //唤醒状况,直接发动camera
            if (isWakingUpOrAwake()) {
                if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                    mStatusBarKeyguardViewManager.reset(true /* hide */);
                }
                //发动相机,详见参阅5
                mCameraLauncherLazy.get().launchCamera(source,
                        mNotificationPanelViewController.isFullyCollapsed());
                mCentralSurfaces.updateScrimController();
            } else {
                // We need to defer the camera launch until the screen comes on, since otherwise
                // we will dismiss us too early since we are waiting on an activity to be drawn and
                // incorrectly get notified because of the screen on event (which resumes and pauses
                // some activities)
//非唤醒状况,在唤醒完毕的回调里处理,详见参阅3
                mCentralSurfaces.setLaunchCameraOnFinishedWaking(true);
            }
        }
    }
    @Override
    public void onEmergencyActionLaunchGestureDetected() {
        Intent emergencyIntent = mCentralSurfaces.getEmergencyActionIntent();
        if (emergencyIntent == null) {
            Log.wtf(CentralSurfaces.TAG, "Couldn't find an app to process the emergency intent.");
            return;
        }
        if (isGoingToSleep()) {
            mCentralSurfaces.setLaunchEmergencyActionOnFinishedGoingToSleep(true);
            return;
        }
        if (!mCentralSurfaces.isDeviceInteractive()) {
            mPowerManager.wakeUp(SystemClock.uptimeMillis(),
                    PowerManager.WAKE_REASON_GESTURE,
                    "com.android.systemui:EMERGENCY_GESTURE");
        }
        // TODO(b/169087248) Possibly add haptics here for emergency action. Currently disabled for
        // app-side haptic experimentation.
        if (!mKeyguardStateController.isShowing()) {
            mCentralSurfaces.startActivityDismissingKeyguard(emergencyIntent,
                    false /* onlyProvisioned */, true /* dismissShade */,
                    true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
                    null /* animationController */, UserHandle.CURRENT);
            return;
        }
        if (!mCentralSurfaces.isDeviceInteractive()) {
            // Avoid flickering of the scrim when we instant launch the camera and the bouncer
            // comes on.
            mCentralSurfaces.acquireGestureWakeLock(
                    CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
        }
        if (isWakingUpOrAwake()) {
            if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                mStatusBarKeyguardViewManager.reset(true /* hide */);
            }
            mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
            return;
        }
        // We need to defer the emergency action launch until the screen comes on, since otherwise
        // we will dismiss us too early since we are waiting on an activity to be drawn and
        // incorrectly get notified because of the screen on event (which resumes and pauses
        // some activities)
        mCentralSurfaces.setLaunchEmergencyActionOnFinishedWaking(true);
    }

>>参阅1

在isGongingToSleep完毕的回调里处理

    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
    // isGoingToSleep 完毕今后的回调
        @Override
        public void onFinishedGoingToSleep() {
//...
//前边回调里判别isGoingToSleep就把下边这个变量改为true了,所以在isGoingToSleep完毕的时候会走if条件
            if (mLaunchCameraOnFinishedGoingToSleep) {
                mLaunchCameraOnFinishedGoingToSleep = false;
                // This gets executed before we will show Keyguard, so post it in order that the state
                // is correct.
                //又回调前边的callback了
                mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
                        mLastCameraLaunchSource));
            }
            if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
                mLaunchEmergencyActionOnFinishedGoingToSleep = false;
                // This gets executed before we will show Keyguard, so post it in order that the
                // state is correct.
                mMainExecutor.execute(
                        () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected());
            }
            updateIsKeyguard();
        }

>>参阅2

判别camera是否可用的相关代码,CameraGestureHelper.kt

    fun canCameraGestureBeLaunched(statusBarState: Int): Boolean {
        if (!centralSurfaces.isCameraAllowedByAdmin) {
            return false
        }
        val resolveInfo: ResolveInfo? = packageManager.resolveActivityAsUser(
            getStartCameraIntent(),
            PackageManager.MATCH_DEFAULT_ONLY,
            KeyguardUpdateMonitor.getCurrentUser()
        )
        val resolvedPackage = resolveInfo?.activityInfo?.packageName
        return (resolvedPackage != null &&
                (statusBarState != StatusBarState.SHADE ||
                !activityManager.isInForeground(resolvedPackage)))
    }

>>参阅3

在wakeup相关的回调里处理

    public void setLaunchCameraOnFinishedWaking(boolean launch) {
        mLaunchCameraWhenFinishedWaking = launch;
    }
    @VisibleForTesting
    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
        public void onFinishedWakingUp() {
            mWakeUpCoordinator.setFullyAwake(true);
            mWakeUpCoordinator.setWakingUp(false);
//...
//在唤醒流程完毕的回调里再开始调用相机
            if (mLaunchCameraWhenFinishedWaking) {
                mCameraLauncherLazy.get().launchCamera(mLastCameraLaunchSource,
                        mNotificationPanelViewController.isFullyCollapsed());
                mLaunchCameraWhenFinishedWaking = false;
            }
            if (mLaunchEmergencyActionWhenFinishedWaking) {
                mLaunchEmergencyActionWhenFinishedWaking = false;
                Intent emergencyIntent = getEmergencyActionIntent();
                if (emergencyIntent != null) {
                    mContext.startActivityAsUser(emergencyIntent,
                            getActivityUserHandle(emergencyIntent));
                }
            }
            updateScrimController();
        }

>>参阅4

CameraIntents.kt

        fun getInsecureCameraIntent(context: Context): Intent {
            val intent = Intent(DEFAULT_INSECURE_CAMERA_INTENT_ACTION)
            getOverrideCameraPackage(context)?.let {
                intent.setPackage(it)
            }
            return intent
        }
    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
            final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
            final Callback callback, int flags,
            @Nullable ActivityLaunchAnimator.Controller animationController,
            final UserHandle userHandle) {
        if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
//...
        Runnable runnable = () -> {
//intent 增加了flag
            intent.setFlags(
                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(flags);
            int[] result = new int[]{ActivityManager.START_CANCELED};
            mActivityLaunchAnimator.startIntentWithAnimation(animController,
                    animate, intent.getPackage(), (adapter) -> {
                        ActivityOptions options = new ActivityOptions(
                                CentralSurfaces.getActivityOptions(mDisplayId, adapter));
//...
                        try {
                        //这个便是终究的发动intent的代码了,详细的便是 ActivityTaskManagerService类
                            result[0] = ActivityTaskManager.getService().startActivityAsUser(
                                    null, mContext.getBasePackageName(),
                                    mContext.getAttributionTag(),
                                    intent,
                                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                    null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
                                    options.toBundle(), userHandle.getIdentifier());
                        } catch (RemoteException e) {
                            Log.w(TAG, "Unable to start activity", e);
                        }
                        return result[0];
                    });
            if (callback != null) {
                callback.onActivityStarted(result[0]);
            }
        };
        Runnable cancelRunnable = () -> {
            if (callback != null) {
                callback.onActivityStarted(ActivityManager.START_CANCELED);
            }
        };
//...
//下边便是处理keyguard消失今后发动runnable
        executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
                willLaunchResolverActivity, deferred /* deferred */, animate);
    }

>>参阅5

CameraLauncher.java

    public void launchCamera(int source, boolean isShadeFullyCollapsed) {
        if (!isShadeFullyCollapsed) {
            setLaunchingAffordance(true);
        }
        mCameraGestureHelper.launchCamera(source);
    }
    fun launchCamera(source: Int) {
        val intent: Intent = getStartCameraIntent()
        intent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source)
        val wouldLaunchResolverActivity = activityIntentHelper.wouldLaunchResolverActivity(
            intent, KeyguardUpdateMonitor.getCurrentUser()
        )
        if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {
            uiExecutor.execute {
                // Normally an activity will set its requested rotation animation on its window.
                // However when launching an activity causes the orientation to change this is too
                // late. In these cases, the default animation is used. This doesn't look good for
                // the camera (as it rotates the camera contents out of sync with physical reality).
                // Therefore, we ask the WindowManager to force the cross-fade animation if an
                // orientation change happens to occur during the launch.
                val activityOptions = ActivityOptions.makeBasic()
                activityOptions.setDisallowEnterPictureInPictureWhileLaunching(true)
                activityOptions.rotationAnimationHint =
                    WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
                try {
                //这儿也走到start activity了
                    activityTaskManager.startActivityAsUser(
                        null,
                        context.basePackageName,
                        context.attributionTag,
                        intent,
                        intent.resolveTypeIfNeeded(contentResolver),
                        null,
                        null,
                        0,
                        Intent.FLAG_ACTIVITY_NEW_TASK,
                        null,
                        activityOptions.toBundle(),
                        UserHandle.CURRENT.identifier,
                    )
                } catch (e: RemoteException) {
                    Log.w(
                        "CameraGestureHelper",
                        "Unable to start camera activity",
                        e
                    )
                }
            }
        } else {
            // We need to delay starting the activity because ResolverActivity finishes itself if
            // launched from behind the lock-screen.
            //这个终究调的是参阅4里的那个startActivity办法
            activityStarter.startActivity(intent, false /* dismissShade */)
        }
//如果camera app发动失利,超时后恢复keyguard
        centralSurfaces.startLaunchTransitionTimeout()
//保证camera intent能够发动后躲藏keyguard
        centralSurfaces.readyForKeyguardDone()
    }

other

        fun getSecureCameraIntent(context: Context): Intent {
            val intent = Intent(DEFAULT_SECURE_CAMERA_INTENT_ACTION)
            getOverrideCameraPackage(context)?.let {
                intent.setPackage(it)
            }
            return intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
        }

>CommandQueue

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java

调用CommandQueue的某个办法今后,里面是经过handler处理的,handler里终究又给到了callback来处理

/**
 * This class takes the functions from IStatusBar that come in on
 * binder pool threads and posts messages to get them onto the main
 * thread, and calls onto Callbacks.  It also takes care of
 * coalescing these calls so they don't stack up.  For the calls
 * are coalesced, note that they are all idempotent.
 */
public class CommandQueue extends IStatusBar.Stub implements
        CallbackController<Callbacks>,
        DisplayManager.DisplayListener {
    @Override
    public void onCameraLaunchGestureDetected(int source) {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
            mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
        }
    }
    @Override
    public void onEmergencyActionLaunchGestureDetected() {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE);
            mHandler.obtainMessage(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE).sendToTarget();
        }
    }
//终究都是这些回调处理的
    @Override
    public void addCallback(@NonNull Callbacks callbacks) {
        mCallbacks.add(callbacks);
        // TODO(b/117478341): find a better way to pass disable flags by display.
        for (int i = 0; i < mDisplayDisabled.size(); i++) {
            int displayId = mDisplayDisabled.keyAt(i);
            int disabled1 = getDisabled1(displayId);
            int disabled2 = getDisabled2(displayId);
            callbacks.disable(displayId, disabled1, disabled2, false /* animate */);
        }
    }
//handler
    private final class H extends Handler {
        private H(Looper l) {
            super(l);
        }
        //...
                case MSG_CAMERA_LAUNCH_GESTURE:
                    for (int i = 0; i < mCallbacks.size(); i++) {
                        mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1);
                    }
                    break;
                case MSG_EMERGENCY_ACTION_LAUNCH_GESTURE:
                    for (int i = 0; i < mCallbacks.size(); i++) {
                        mCallbacks.get(i).onEmergencyActionLaunchGestureDetected();
                    }
                    break;

6.StatusBarManagerService

>结构办法

结构办法里绑定了StatusBarManagerInternal实例

    public StatusBarManagerService(Context context) {
        mContext = context;
        LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
        LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);

>实例化

是在frameworks/base/services/java/com/android/server/SystemServer.java里初始化的

import android.os.ServiceManager;
            if (!isWatch) {
                try {
                    statusBar = new StatusBarManagerService(context);
                    ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar, false,
                            DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
                } catch (Throwable e) {
                }
            }

>addService

frameworks/base/core/java/android/os/ServiceManager.java

    /**
     * Place a new @a service called @a name into the service
     * manager.
     *
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * @param dumpPriority supported dump priority levels as a bitmask
     * to access this service
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static void addService(String name, IBinder service, boolean allowIsolated,
            int dumpPriority) {
        try {
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

7.总结

双击电源键的手势,流程如下:
最先接纳到手势事情的是InputManagerService.java里的dispatchUnhandledKey办法,

完事传递给 PhoneWindowManager.java里的dispatchUnhandledKey办法,然后依次interceptFallback办法,》interceptKeyBeforeQueueing >>handleKeyGusture >>handleCameraGesture

然后是GestureLauncherService.java的interceptPowerKeyDown办法,》handleCameraGesture办法

继续走到StatusBarManagerInternal的onCameraLaunchGestureDetected办法,里面的详细完成都是经过一个变量mBar来处理的,这个mBar是个CommandQueue,详细完成又是给到了callback,这儿用到的是CentralSurfacesCommandQueueCallbacks.java,所以终究逻辑都在这个类里。