• MTK平台双击Power打开Camera的简单流程


    (1)Framework层Flow

    Framework层的backtrace如下:

    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.statusbar.StatusBarManagerService$1.onCameraLaunchGestureDetected(StatusBarManagerService.java:268)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.GestureLauncherService.handleCameraGesture(GestureLauncherService.java:432)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.GestureLauncherService.interceptPowerKeyDown(GestureLauncherService.java:390)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.policy.PhoneWindowManager.interceptPowerKeyDown(PhoneWindowManager.java:1117)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:4688)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.wm.InputManagerCallback.interceptKeyBeforeQueueing(InputManagerCallback.java:318)
    07-02 16:17:25.556  1066  2879 E dxf_onCameraLaunchGestureDetected: 	at com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1981)
    
    07-02 16:17:25.560  3058  3058 D StatusBar: Finish going to sleep before launching camera
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    最原始的事件触发从InputManagerService开始:

    //frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    
    // Native callback.
        private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
            return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最终调用到StatusBarManagerService这里:

    //frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
    
    @Override
            public void onCameraLaunchGestureDetected(int source) {
                if (mBar != null) {
                    try {
                        android.util.Log.e("dxf_onCameraLaunchGestureDetected", "source = " + source,new NullPointerException());
                        mBar.onCameraLaunchGestureDetected(source);
                    } catch (RemoteException e) {
                    }
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    上面Framework层的逻辑如果不清楚,可以根据backtrace来追踪Code查看Flow,这里将重点的Power键单双击事件写成另外一篇文章,可以参考一下Framework层长短按Power键触发事件

    接下来这里即将调用到SystemUI当中的StatusBar当中。

    //vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
    
    public void onCameraLaunchGestureDetected(int source) {
            android.util.Log.e("dxf_onCameraLaunchGestureDetected", "source = " + source,new NullPointerException());
            mLastCameraLaunchSource = source;
            if (isGoingToSleep()) {
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
                //这里将变量mLaunchCameraOnFinishedGoingToSleep设置为true,等到后续用于判断Flow
                mLaunchCameraOnFinishedGoingToSleep = true;
                return;
            }
            if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
                return;
            }
            if (!mDeviceInteractive) {
                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.i(TAG, "Camera launch");
                mKeyguardUpdateMonitor.onCameraLaunched();
            }
    		//...
    }
    
    • 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

    从Log可以看到第一次的调用都被第一个if语句拦截住了,开始执行isGoingToSleep()。

    (2)SystemUI中的Flow

    从上面第一次进入onCameraLaunchGestureDetected后,被判断条件拦截,进而后续又重新回调如下函数,准备重新OpenCamera。

    07-02 16:17:25.646  3058  3058 E dxf_onCameraLaunchGestureDetected: 	at com.android.systemui.statusbar.phone.StatusBar.onCameraLaunchGestureDetected(StatusBar.java:4162)
    07-02 16:17:25.646  3058  3058 E dxf_onCameraLaunchGestureDetected: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0(StatusBar.java:4027)
    07-02 16:17:25.646  3058  3058 E dxf_onCameraLaunchGestureDetected: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0$StatusBar$12(Unknown Source:0)
    
    • 1
    • 2
    • 3
    //vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
    
    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
            @Override
            public void onFinishedGoingToSleep() {
                mNotificationPanelViewController.onAffordanceLaunchEnded();
                releaseGestureWakeLock();
                mLaunchCameraWhenFinishedWaking = false;
                mDeviceInteractive = false;
                mWakeUpComingFromTouch = false;
                mWakeUpTouchLocation = null;
                mVisualStabilityManager.setScreenOn(false);
                updateVisibleToUser();
    
                updateNotificationPanelTouchState();
                mNotificationShadeWindowViewController.cancelCurrentTouch();
                if (mLaunchCameraOnFinishedGoingToSleep) {
                    mLaunchCameraOnFinishedGoingToSleep = false;
    
                    // This gets executed before we will show Keyguard, so post it in order that the state
                    // is correct.
                    
                    //这里再次调用onCameraLaunchGestureDetected函数
                    mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource));
                }
                // When finished going to sleep, force the status bar state to avoid stale state.
                updateIsKeyguard(true /* force */);
            }
    
    • 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

    我们再次进入到onCameraLaunchGestureDetected函数中:

    //vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
    
    public void onCameraLaunchGestureDetected(int source) {
            mLastCameraLaunchSource = source;
            if (isGoingToSleep()) {
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
                mLaunchCameraOnFinishedGoingToSleep = true;
                return;
            }
            if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
                return;
            }
            if (!mDeviceInteractive) {
                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.i(TAG, "Camera launch");
                mKeyguardUpdateMonitor.onCameraLaunched();
            }
    
            if (!mStatusBarKeyguardViewManager.isShowing()) {
                Log.i(TAG, "dxf_launch1");
                
                //(1)这里直接调用startActivityDismissingKeyguard来startActivityAsUser(非锁屏情况下)
                startActivityDismissingKeyguard(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
                        false /* onlyProvisioned */, true /* dismissShade */,
                        true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0);
            } else {
                Log.i(TAG, "dxf_launch2");
                if (!mDeviceInteractive) {
                    // Avoid flickering of the scrim when we instant launch the camera and the bouncer
                    // comes on.
                    mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
                }
                if (isWakingUpOrAwake()) {
                    if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
                    if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                        mStatusBarKeyguardViewManager.reset(true /* hide */);
                    }
                    // M: Mtk add for fix unresponse when swipe lock and occluded.
                    if (!mStatusBarKeyguardViewManager.isSecure()
                            && mStatusBarKeyguardViewManager.isOccluded()) {
                        Slog.d(TAG, "Non-Secure unlock, no need to launch camera");
                        return;
                    }
                    Log.i(TAG, "dxf_launch3");
                    
                    //(2)这里通过launchCamera最终来startActivityAsUser(锁屏情况下)
                    mNotificationPanelViewController.launchCamera(
                            mDeviceInteractive /* animate */, source);
                    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)
                    if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on");
                    mLaunchCameraWhenFinishedWaking = true;
                }
            }
        }
    
    • 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

    从这里开始SystemUI分为不同的处理流程,那是为什么呢?因为这两种处理流程主要表现在锁屏和不锁屏的情况下双击Power键的流程。

    (A)非锁屏情况下

    07-02 16:16:27.431  3058  3058 I StatusBar: dxf_launch1
    07-02 16:16:27.431  3058  3058 E dxf_startActivityDismissingKeyguard: Intent { act=android.media.action.STILL_IMAGE_CAMERA flg=0x14000000 }
    07-02 16:16:27.431  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar.startActivityDismissingKeyguard(StatusBar.java:2871)
    07-02 16:16:27.431  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar.onCameraLaunchGestureDetected(StatusBar.java:4186)
    07-02 16:16:27.431  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0(StatusBar.java:4027)
    07-02 16:16:27.431  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0$StatusBar$12(Unknown Source:0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (B)锁屏情况下

    07-02 16:17:25.674  3058  3058 I StatusBar: dxf_launch2
    07-02 16:17:25.674  3058  3058 D StatusBar: Launching camera
    07-02 16:17:25.676  3058  3058 I StatusBar: dxf_launch3
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: Intent { act=android.media.action.STILL_IMAGE_CAMERA flg=0x14000000 (has extras) }
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar.startActivityDismissingKeyguard(StatusBar.java:2871)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar.startActivity(StatusBar.java:1896)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.ActivityStarterDelegate.startActivity(ActivityStarterDelegate.java:89)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.KeyguardBottomAreaView.launchCamera(KeyguardBottomAreaView.java:603)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.NotificationPanelViewController$KeyguardAffordanceHelperCallback.onAnimationToSideStarted(NotificationPanelViewController.java:3370)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.KeyguardAffordanceHelper.fling(KeyguardAffordanceHelper.java:356)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.KeyguardAffordanceHelper.launchAffordance(KeyguardAffordanceHelper.java:534)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.NotificationPanelViewController.launchCamera(NotificationPanelViewController.java:2761)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar.onCameraLaunchGestureDetected(StatusBar.java:4208)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0(StatusBar.java:4027)
    07-02 16:17:25.685  3058  3058 E dxf_startActivityDismissingKeyguard: 	at com.android.systemui.statusbar.phone.StatusBar$12.lambda$onFinishedGoingToSleep$0$StatusBar$12(Unknown Source:0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    进而最终都会调用到StatusBar当中的startActivityDismissingKeyguard函数。

    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
                final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
                final Callback callback, int flags) {
            android.util.Log.e("dxf_startActivityDismissingKeyguard", intent.toString(),new NullPointerException());
    
    		//...
    		intent.setFlags(
                        Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(flags);
            int result = ActivityManager.START_CANCELED;
    
    		result = 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.CURRENT.getIdentifier());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    无穷级数几个基础知识
    R语言使用glm函数构建逻辑回归模型(logistic)、使用subgroupAnalysis函数进行亚组分析并可视化森林图
    如何怎麼搭建高效的爬蟲全球代理IP池?
    计算机毕业设计ssm+vue基本微信小程序的好物推荐分享系统
    银河麒麟系统下安装Kingbase数据库
    如何计算质心
    java毕业设计茶叶企业管理系统Mybatis+系统+数据库+调试部署
    OPT锂电池极耳缺陷检测方案
    动态渲染 echarts 饼图(vue 2 + axios + Springboot)
    [GWCTF 2019]枯燥的抽奖
  • 原文地址:https://blog.csdn.net/dongxianfei/article/details/125602012