Try harder to find a camera app to pin.

Currently, the pinner service pins whatever Camera app is being pointed
to by MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA. This change updates
that logic to try pinning whatever is in
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE if the first intent
doesn't exist. If neither of those resolve to a single target, this
change reviews the targets in
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA and pins the Camera app with
the System flag, making the assumption that the System app is the one
that we'd want to pin if the user hasn't resolved the intent manually.

Bug: 111655213
Test: Results show from just after boot, with logging added to ensure all code paths are covered

Two camera apps installed (Snapchat chosen by manually resolving the double-tap intent).
Two launchers installed (Nova Launcher chosen by selecting it in Settings)

07-24 21:45:38.014  1158  6329 E carmen  : getting application info for intent: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x100 } defaultToSystemApp false
07-24 21:45:38.014  1158  6329 E carmen  : only one app for this intent: ResolveInfo{f871a08 com.teslacoilsw.launcher/.NovaLauncher m=0x108000}
07-24 21:45:38.014  1158  6329 E carmen  : getting application info for intent: Intent { act=android.media.action.STILL_IMAGE_CAMERA } defaultToSystemApp false
07-24 21:45:38.014  1158  6329 E carmen  : only one app for this intent: ResolveInfo{a4b5a1 com.snapchat.android/.LandingPageActivity m=0x108000}

$ adb shell dumpsys pinner

Camera uid=10162 active=false
  /data/app/com.snapchat.android-TXaPziuyDrKJhSP_OsPBhQ==/base.apk 76214272
  /data/app/com.snapchat.android-TXaPziuyDrKJhSP_OsPBhQ==/oat/arm/base.vdex 57143296
  /data/app/com.snapchat.android-TXaPziuyDrKJhSP_OsPBhQ==/oat/arm/base.odex 1462272
Home uid=10160 active=false
  /data/app/com.teslacoilsw.launcher-RxwR4RYHwo8fCUIe3yRTtA==/base.apk 6291456
  /data/app/com.teslacoilsw.launcher-RxwR4RYHwo8fCUIe3yRTtA==/oat/arm64/base.vdex 5488640
  /data/app/com.teslacoilsw.launcher-RxwR4RYHwo8fCUIe3yRTtA==/oat/arm64/base.odex 131072
Total size: 246603776

Two camera apps installed, neither resolved (double tapping power key shows disambiguation dialog).
Two launchers installed (Pixel Launcher chosen by selecting it in Settings)
Then reboot:

07-24 21:51:34.319  1186  6132 E carmen  : getting application info for intent: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x100 } defaultToSystemApp false
07-24 21:51:34.319  1186  6132 E carmen  : only one app for this intent: ResolveInfo{bb98d44 com.google.android.apps.nexuslauncher/.NexusLauncherActivity m=0x108000}
07-24 21:51:34.319  1186  6132 E carmen  : getting application info for intent: Intent { act=android.media.action.STILL_IMAGE_CAMERA } defaultToSystemApp false
07-24 21:51:34.319  1186  6132 E carmen  : returning null
07-24 21:51:34.319  1186  6132 E carmen  : getting application info for intent: Intent { act=android.media.action.STILL_IMAGE_CAMERA_SECURE } defaultToSystemApp false
07-24 21:51:34.319  1186  6132 E carmen  : only one app for this intent: ResolveInfo{da40e2d com.google.android.GoogleCamera/com.android.camera.SecureCameraActivity m=0x108000}

$ adb shell dumpsys pinner
Camera uid=10131 active=false
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/base.apk 70901760
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/oat/arm64/base.vdex 12369920
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/oat/arm64/base.odex 249856
Home uid=10059 active=false
  /system/priv-app/NexusLauncherPrebuilt/NexusLauncherPrebuilt.apk 5664768
  /data/dalvik-cache/arm64/system@priv-app@NexusLauncherPrebuilt@NexusLauncherPrebuilt.apk@classes.vdex 36864
  /data/dalvik-cache/arm64/system@priv-app@NexusLauncherPrebuilt@NexusLauncherPrebuilt.apk@classes.dex 90112
Total size: 189186048

Commenting out the _SECURE intent check, with two camera apps and neither one chosen:
07-24 22:18:31.314  1174  1198 E carmen  : getting application info for intent: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x100 } defaultToSystemApp false
07-24 22:18:31.314  1174  1198 E carmen  : only one app for this intent: ResolveInfo{e4399e1 com.google.android.apps.nexuslauncher/.NexusLauncherActivity m=0x108000}
07-24 22:18:31.350  1174  1198 E carmen  : getting application info for intent: Intent { act=android.media.action.STILL_IMAGE_CAMERA } defaultToSystemApp false
07-24 22:18:31.351  1174  1198 E carmen  : returning null
07-24 22:18:31.351  1174  1198 E carmen  : getting application info for intent: Intent { act=android.media.action.STILL_IMAGE_CAMERA } defaultToSystemApp true
07-24 22:18:31.351  1174  1198 E carmen  : multiple apps for this intent, choosing system app: ApplicationInfo{845c229 com.google.android.GoogleCamera}

$ adb shell dumpsys pinner
Camera uid=10131 active=false
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/base.apk 70901760
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/oat/arm64/base.vdex 11657216
  /data/app/com.google.android.GoogleCamera-03j4UhJ73NQ42OkVl_VgHw==/oat/arm64/base.odex 397312
Home uid=10059 active=true
  /system/priv-app/NexusLauncherPrebuilt/NexusLauncherPrebuilt.apk 5664768
  /data/dalvik-cache/arm64/system@priv-app@NexusLauncherPrebuilt@NexusLauncherPrebuilt.apk@classes.vdex 36864
  /data/dalvik-cache/arm64/system@priv-app@NexusLauncherPrebuilt@NexusLauncherPrebuilt.apk@classes.dex 90112
Total size: 188616704

Change-Id: Ib90c91ac394adf269aaa8d3603af84a9ad4375f9
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index f5b29e9..a05a3e7 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -69,6 +69,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.List;
 import java.util.ArrayList;
 
 import java.util.zip.ZipFile;
@@ -345,31 +346,76 @@
     }
 
     private ApplicationInfo getCameraInfo(int userHandle) {
-        //  find the camera via an intent
-        //  use INTENT_ACTION_STILL_IMAGE_CAMERA instead of _SECURE.  On a
-        //  device without a fbe enabled, the _SECURE intent will never get set.
         Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
-        return getApplicationInfoForIntent(cameraIntent, userHandle);
+        ApplicationInfo info = getApplicationInfoForIntent(cameraIntent, userHandle,
+            false /* defaultToSystemApp */);
+
+        // If the STILL_IMAGE_CAMERA intent doesn't resolve, try the _SECURE intent.
+        // We don't use _SECURE first because it will never get set on a device
+        // without File-based Encryption. But if the user has only set the intent
+        // before unlocking their device, we may still be able to identify their
+        // preference using this intent.
+        if (info == null) {
+            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+            info = getApplicationInfoForIntent(cameraIntent, userHandle,
+                false /* defaultToSystemApp */);
+        }
+
+        // If the _SECURE intent doesn't resolve, try the original intent but request
+        // the system app for camera if there was more than one result.
+        if (info == null) {
+            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+            info = getApplicationInfoForIntent(cameraIntent, userHandle,
+                true /* defaultToSystemApp */);
+        }
+        return info;
     }
 
     private ApplicationInfo getHomeInfo(int userHandle) {
         Intent intent = mAmInternal.getHomeIntent();
-        return getApplicationInfoForIntent(intent, userHandle);
+        return getApplicationInfoForIntent(intent, userHandle, false);
     }
 
-    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle) {
+    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle,
+            boolean defaultToSystemApp) {
         if (intent == null) {
             return null;
         }
-        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(intent,
+
+        ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivityAsUser(intent,
                 MATCH_FLAGS, userHandle);
-        if (info == null) {
+
+        // If this intent can resolve to only one app, choose that one.
+        // Otherwise, if we've requested to default to the system app, return it;
+        // if we have not requested that default, return null if there's more than one option.
+        // If there's more than one system app, return null since we don't know which to pick.
+        if (resolveInfo == null) {
             return null;
         }
-        if (isResolverActivity(info.activityInfo)) {
-            return null;
+
+        if (!isResolverActivity(resolveInfo.activityInfo)) {
+            return resolveInfo.activityInfo.applicationInfo;
         }
-        return info.activityInfo.applicationInfo;
+
+        if (defaultToSystemApp) {
+            List<ResolveInfo> infoList = mContext.getPackageManager()
+                .queryIntentActivitiesAsUser(intent, MATCH_FLAGS, userHandle);
+            ApplicationInfo systemAppInfo = null;
+            for (ResolveInfo info : infoList) {
+                if ((info.activityInfo.applicationInfo.flags
+                      & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                    if (systemAppInfo == null) {
+                        systemAppInfo = info.activityInfo.applicationInfo;
+                    } else {
+                        // If there's more than one system app, return null due to ambiguity.
+                        return null;
+                    }
+                }
+            }
+            return systemAppInfo;
+        }
+
+        return null;
     }
 
     private void sendPinAppsMessage(int userHandle) {