Check app install source before checking for DO.

Check if the non system apps were installed from an allowed app store
before looking for the distraction optimized activities in their
manifest.  This prevents unauthorized apps faking DO behavior.

Bug: 109941605
Test: Test if sideloaded apps with DO activities are not added to the
allowed to run in a restricted state list.

Change-Id: I20f1560d1f26910216dcacc0333d2ae3b6fd1f27
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 45e6e0b..ac64148 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -51,6 +51,9 @@
           Format of each entry is either to specify package name to whitelist the whole package
           or use format of "packagename/activity_classname" for tagging each activities.-->
     <string name="activityBlacklist"></string>
+    <!-- List of play store package names that are allowed sources of app installation-->
+    <string-array translateble="false" name="allowedAppInstallSources">
+    </string-array>
     <!-- Default home activity -->
     <string name="defaultHomeActivity"><!--com.your.package/com.your.package.Activity--></string>
     <!--  The com.android.car.VmsPublisherService will bind to this list of clients -->
diff --git a/service/src/com/android/car/pm/CarPackageManagerService.java b/service/src/com/android/car/pm/CarPackageManagerService.java
index 930a9e4..3f3f051 100644
--- a/service/src/com/android/car/pm/CarPackageManagerService.java
+++ b/service/src/com/android/car/pm/CarPackageManagerService.java
@@ -40,6 +40,7 @@
 import android.content.pm.Signature;
 import android.content.res.Resources;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -92,6 +93,8 @@
     // Store the white list and black list strings from the resource file.
     private String mConfiguredWhitelist;
     private String mConfiguredBlacklist;
+    private final List<String> mAllowedAppInstallSources;
+
     /**
      * Hold policy set from policy service or client.
      * Key: packageName of policy service
@@ -152,8 +155,11 @@
         mEnableActivityBlocking = res.getBoolean(R.bool.enableActivityBlockingForSafety);
         String blockingActivity = res.getString(R.string.activityBlockingActivity);
         mActivityBlockingActivity = ComponentName.unflattenFromString(blockingActivity);
+        mAllowedAppInstallSources = Arrays.asList(
+                res.getStringArray(R.array.allowedAppInstallSources));
     }
 
+
     @Override
     public void setAppBlockingPolicy(String packageName, CarAppBlockingPolicy policy, int flags) {
         if (DBG_POLICY_SET) {
@@ -583,7 +589,31 @@
                 }
             } else {
                 /* 2. If app is not listed in the config.xml check their Manifest meta-data to
-                  see if they have any Distraction Optimized(DO) activities */
+                  see if they have any Distraction Optimized(DO) activities.
+                  For non system apps, we check if the app install source was a permittable
+                  source. This prevents side-loaded apps to fake DO.  Bypass the check
+                  for debug builds for development convenience. */
+                if (!isDebugBuild()
+                        && !info.applicationInfo.isSystemApp()
+                        && !info.applicationInfo.isUpdatedSystemApp()) {
+                    try {
+                        if (mAllowedAppInstallSources != null) {
+                            String installerName = mPackageManager.getInstallerPackageName(
+                                    info.packageName);
+                            if (installerName == null || (installerName != null
+                                    && !mAllowedAppInstallSources.contains(installerName))) {
+                                Log.w(CarLog.TAG_PACKAGE,
+                                        info.packageName + " not installed from permitted sources "
+                                                + installerName == null ? "NULL" : installerName);
+                                continue;
+                            }
+                        }
+                    } catch (IllegalArgumentException e) {
+                        Log.w(CarLog.TAG_PACKAGE, info.packageName + " not installed!");
+                        continue;
+                    }
+                }
+
                 try {
                     activities = CarAppMetadataReader.findDistractionOptimizedActivities(
                             mContext,
@@ -622,6 +652,10 @@
         }
     }
 
+    private boolean isDebugBuild() {
+        return Build.IS_USERDEBUG || Build.IS_ENG;
+    }
+
     /**
      * Generate a map of blacklisted packages and activities of the form {pkgName, Blacklisted
      * activities}.  The blacklist information comes from a configuration XML resource.