Using an implicit intent at the moment of picture-taking usually goes unnoticed. But immediately after installing a new camera, this behavior becomes incredibly frustrating to users as they are presented with a puzzling resolver dialog (or in the case of the secure camera, the authenticator). And if, at this moment, the user chooses to make one of the options a default, it's almost impossible to figure out how to change this setting. As a result, many OEMs simply hardcode the camera gesture to launch a specific preinstalled camera, but this is poorly supported by AOSP, leading to duplicate implementations and bugs. This patch routes all camera intents in System UI through a single utility class, creating a convenient spot to insert a resource that contains the OEM's default preinstalled camera app. Note that this does not affect implicit intent resolution in any way; any app may create a chooser for, e.g., MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA and allow the user to pick from the available cameras. Bugreport/dumpsys output to look for: $ adb shell dumpsys activity service com.android.systemui | grep -C3 'Camera gesture' | tail -3 Camera gesture intents: Insecure camera: Intent { act=android.media.action.STILL_IMAGE_CAMERA } Secure camera: Intent { act=android.media.action.STILL_IMAGE_CAMERA_SECURE flg=0x800000 } Override package: null Bug: 171807357 Fixes: 154218868 Test: atest SystemUITests Change-Id: I2c0033e52c8a3963768d29f2e76e555d405aaa7e
3.8 KiB
3.8 KiB
How double-click power launches the camera
as of august 2020
Sequence of events
- PhoneWindowManager.java is responsible for all power button presses (see
interceptPowerKeyDown
). - Even though PWMgr has a lot of logic to detect all manner of power button multipresses and gestures, it also checks with GestureLauncherService, which is also offered the chance to intercept the power key.
- GLS is responsible for the camera timeout, and if it detects one, it forwards it to the StatusBarManagerService (which hands it off to SystemUI).
- Inside SystemUI, onCameraLaunchDetected looks at the keyguard state and determines
- whether the camera is even allowed
- whether the screen is on; if not, we need to delay until that happens
- whether the device is locked (defined as "keyguard is showing").
- If the device is unlocked (no keyguard), the camera is launched immediately. Callsite in onCameraLaunchGestureDetected.
- If the keyguard is up, however, KeyguardBottomAreaView.launchCamera takes over to handle the "secure camera" (a different intent, usually directing to the same app, but giving that app the cue to not allow access to the photo roll, etc).
- If the intent would have to launch a resolver (the user has multiple cameras installed and hasn’t chosen one to always launch for the
SECURE_CAMERA_INTENT
),- In order to show the resolver, the lockscreen "bouncer" (authentication method) is first presented.
- Otherwise (just one secure camera), it is launched (with some window animation gymnastics).
Which intent launches?
- If the keyguard is not showing (device is unlocked)
CameraIntents.getInsecureCameraIntent()
, defined to beMediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
.- Callsite in StatusBar.java.
- If the keyguard is showing (device locked)
- KeyguardBottomAreaView.getCameraIntent() is consulted, which allows the "keyguard right button" (which we don’t actually show) to control the camera intent. The default implementation returns one of
CameraIntents.getInsecureCameraIntent()
orCameraIntents.getSecureCameraIntent()
, which areMediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
andMediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
, respectively. - Callsite in KeyguardBottomAreaView.java.
- KeyguardBottomAreaView.getCameraIntent() is consulted, which allows the "keyguard right button" (which we don’t actually show) to control the camera intent. The default implementation returns one of
- Note that starting in Android 12, as required by some OEMs, if the special string resource
config_cameraGesturePackage
is nonempty, this will be treated as a package name to be added to the insecure camera intent, constraining the invocation to that single app and typically preventing implicit intent resolution. This package must be on the device or the camera gesture will no longer work properly.