src/com/android/keyguard/KeyguardSecurityContainerController.java
if (finish) {
mSecurityCallback.finish(strongAuth, targetUserId);
Log.d(TAG, "finish ");
}
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish() - return finish = " + finish) ;
/* add by *** for not allowed open camera begin*/
if (finish) {
SystemProperties.set("sys.keyguard_open","1");
}
/* add by *** for not allowed open camera begin*/
return finish;
}
src/com/android/systemui/statusbar/phone/StatusBar.java
@Override
public void onCameraLaunchGestureDetected(int source) {
mLastCameraLaunchSource = source;
/* add by *** for not allowed open camera begin*/
if ("0".equals(SystemProperties.get("sys.keyguard_open","0"))) {
return;
} else {
Slog.d(TAG, "The camera is not allowed to start because it has never been unlocked");
}
/* add by **** for not allowed open camera end*/
if (isGoingToSleep()) {
if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
mLaunchCameraOnFinishedGoingToSleep = true;
return;
}
分析双击电源键打开相机的流程:
找到电源按键上报的代码:
base/services/core/java/com/android/server/policy/PhoneWindowManager.java
关键函数:
在这两个函数中处理,注意可能被重写导致不在PhoneWindowManager.java中出现
1)interceptKeyBeforeDispatching
2)interceptKeyBeforeQueueing
处理流程:
base/services/core/java/com/android/server/policy/PhoneWindowManager.java
interceptKeyBeforeQueueing->
handleKeyGesture->
mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);
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);
......
}
/********************************************************************************/
base/services/core/java/com/android/server/GestureLauncherService.java
interceptPowerKeyDown->
handleCameraGesture->
onCameraLaunchGestureDetected
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;
......
}
base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@Override
public void onCameraLaunchGestureDetected(int source) {
if (mBar != null) {
try {
mBar.onCameraLaunchGestureDetected(source);
} catch (RemoteException e) {
}
}
}
base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@Override
public void onCameraLaunchGestureDetected(int source) {
mLastCameraLaunchSource = source;
// Slog.e(TAG, Log.getStackTraceString(new Throwable()));
/* add by zhoujian for not allowed open camera begin*/
if ("0".equals(SystemProperties.get("sys.keyguard_open","0"))) {
return;
} else {
Slog.e(TAG, "The camera is allowed to start because it has been unlocked");
}
/* add by zhoujian for not allowed open camera end*/
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.v(TAG, "Camera launch");
/// M: ALPS05974700 Fix the screen desplay white while double click power key
mCameraLaunchPowerDouble = true;
mKeyguardUpdateMonitor.onCameraLaunched();//屏蔽人脸或者指纹解锁
}
if (!mStatusBarKeyguardViewManager.isShowing()) {
final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
startActivityDismissingKeyguard(cameraIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
null /* animationController */);
} else {
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 aaa");
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;
}
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;
}
}
}
startActivityDismissingKeyguard()
private void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
final Callback callback, int flags,
@Nullable ActivityLaunchAnimator.Controller animationController) {
Slog.e(TAG, Log.getStackTraceString(new Throwable()));
if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
final boolean willLaunchResolverActivity =
mActivityIntentHelper.wouldLaunchResolverActivity(intent,
mLockscreenUserManager.getCurrentUserId());
boolean animate =
animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
true /* isActivityIntent */);
ActivityLaunchAnimator.Controller animController =
animate ? wrapAnimationController(animationController, dismissShade) : null;
// If we animate, we will dismiss the shade only once the animation is done. This is taken
// care of by the StatusBarLaunchAnimationController.
boolean dismissShadeDirectly = dismissShade && animController == null;
Runnable runnable = () -> {
mAssistManagerLazy.get().hideAssist();
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(
getActivityOptions(mDisplayId, adapter));
options.setDisallowEnterPictureInPictureWhileLaunching(
disallowEnterPictureInPictureWhileLaunching);
if (CameraIntents.isInsecureCameraIntent(intent)) {
// 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.
options.setRotationAnimationHint(
WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
}
if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
// Settings Panel is implemented as activity(not a dialog), so
// underlying app is paused and may enter picture-in-picture mode
// as a result.
// So we need to disable picture-in-picture mode here
// if it is volume panel.
options.setDisallowEnterPictureInPictureWhileLaunching(true);
}
try {
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.CURRENT.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);
}
};
executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
willLaunchResolverActivity, true /* deferred */, animate);
}
src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
launchCamera->launchAffordance
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 we are launching it when we are occluded already we don't want it to animate,
// nor setting these flags, since the occluded state doesn't change anymore, hence it's
// never reset.
Log.d(TAG, "launchCamera +++");
if (!isFullyCollapsed()) {
setLaunchingAffordance(true);//启动动画????
} else {
animate = false;
}
mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
mAffordanceHelper.launchAffordance(
animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
}
src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
......