(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
最原始的事件触发从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);
}
最终调用到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) {
}
}
}
上面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();
}
//...
}
从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)
//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 */);
}
我们再次进入到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;
}
}
}
从这里开始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)
(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)
进而最终都会调用到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());
}