MTK平台双击Power打开Camera(一)——SystemUI简单流程
(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最原始的事件觸發(fā)從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);}最終調(diào)用到StatusBarManagerService這里:
//frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java@Overridepublic void onCameraLaunchGestureDetected(int source) {if (mBar != null) {try {android.util.Log.e("dxf_onCameraLaunchGestureDetected", "source = " + source,new NullPointerException());mBar.onCameraLaunchGestureDetected(source);} catch (RemoteException e) {}}}上面Framework層的邏輯如果不清楚,可以根據(jù)backtrace來追蹤Code查看Flow,這里將重點的Power鍵單雙擊事件寫成另外一篇文章,可以參考一下MTK平臺雙擊Power打開Camera——Framework層長短按Power鍵簡單流程(2)
(2)SystemUI中的Flow
(A)Android S 流程
接下來這里即將調(diào)用到SystemUI當(dāng)中的StatusBar當(dāng)中。
//vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.javapublic 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設(shè)置為true,等到后續(xù)用于判斷FlowmLaunchCameraOnFinishedGoingToSleep = 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();}//... }從Log可以看到第一次的調(diào)用都被第一個if語句攔截住了,開始執(zhí)行isGoingToSleep()。
從上面第一次進入onCameraLaunchGestureDetected后,被判斷條件攔截,進而后續(xù)又重新回調(diào)如下函數(shù),準(zhǔn)備重新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) //vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.javafinal WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {@Overridepublic 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.//這里再次調(diào)用onCameraLaunchGestureDetected函數(shù)mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource));}// When finished going to sleep, force the status bar state to avoid stale state.updateIsKeyguard(true /* force */);}我們再次進入到onCameraLaunchGestureDetected函數(shù)中:
//vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.javapublic 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)這里直接調(diào)用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;}}}從這里開始SystemUI分為不同的處理流程,那是為什么呢?因為這兩種處理流程主要表現(xiàn)在鎖屏和不鎖屏的情況下雙擊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)(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)進而最終都會調(diào)用到StatusBar當(dāng)中的startActivityDismissingKeyguard函數(shù)。
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()); }(B)Android T 流程
進入SystemUI的onCameraLaunchGestureDetected函數(shù)。
//vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.javapublic 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) {mKeyguardUpdateMonitor.onCameraLaunched();}if (!mStatusBarKeyguardViewManager.isShowing()) {//(1)不鎖屏的情況下走的Flowfinal 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()) {// 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()) {//(2)鎖屏情況下生命周期處于喚醒狀態(tài)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 {// 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 (CentralSurfaces.DEBUG_CAMERA_LIFT) {Slog.d(CentralSurfaces.TAG, "Deferring until screen turns on");}//(3)鎖屏情況下生命周期處于非喚醒狀態(tài)mCentralSurfaces.setLaunchCameraOnFinishedWaking(true);}}}鎖屏情況下雙擊Power打開相機,即上面流程的(2)和(3)最終會走到如下Flow:
//vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.javapublic void launchCamera(String source) {final Intent intent = getCameraIntent();intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity(intent, KeyguardUpdateMonitor.getCurrentUser());//(1)有密碼鎖的鎖屏情況下走的Flowif (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {AsyncTask.execute(new Runnable() {@Overridepublic void run() {int result = ActivityManager.START_CANCELED;// Normally an activity will set it's 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). So, we ask the WindowManager to// force the crossfade animation if an orientation change// happens to occur during the launch.ActivityOptions o = ActivityOptions.makeBasic();o.setDisallowEnterPictureInPictureWhileLaunching(true);o.setRotationAnimationHint(WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);try {//M: add clear top flag for ALPS02320925intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);result = ActivityTaskManager.getService().startActivityAsUser(null, getContext().getBasePackageName(),getContext().getAttributionTag(), intent,intent.resolveTypeIfNeeded(getContext().getContentResolver()),null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),UserHandle.CURRENT.getIdentifier());} catch (RemoteException e) {Log.w(TAG, "Unable to start camera activity", e);}final boolean launched = isSuccessfulLaunch(result);post(new Runnable() {@Overridepublic void run() {unbindCameraPrewarmService(launched);}});}});} else {//(2)沒有密碼鎖的鎖屏情況下走的Flow// We need to delay starting the activity because ResolverActivity finishes itself if// launched behind lockscreen.mActivityStarter.startActivity(intent, false /* dismissShade */,new ActivityStarter.Callback() {@Overridepublic void onActivityStarted(int resultCode) {unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));}});}}以上(1)和(2)就是鎖屏情況下分有密碼和沒密碼走的Flow。
總結(jié)
以上是生活随笔為你收集整理的MTK平台双击Power打开Camera(一)——SystemUI简单流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Check failed: 0 == b
- 下一篇: 国赛VS美赛,前排速来观战