Use a 16 byte random suffix for installed apk directory name

This prevents apps (both normal and ephemeral) from learning what
applications are installed by checking for the existence of
/data/app/com.example.package-1. /data/app and /data/ephemeral-app are
already 771 and so cannot be ls'd but because the directory names are
guessable it is still possible to learn if known packages are installed.

Apps can still learn if a package is installed and where via the
standard APIs but not by directly using the filesystem. This is
important for ephemeral apps since normal apps should not be aware of
installed ephemeral apps (unless needed) and ephemeral apps shouldn't be
aware of other ephemeral apps.

Test: adb install --ephemeral, verify the code directory has random
suffix
Test: runtest -c android.content.pm.PackageManagerTests frameworks-core
Test: cts-tradefed run commandAndExit cts -m CtsAppSecurityTestCases
Change-Id: Id4883f5cfb9664307cf8518e2db3fef0e2d632d0
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 09b6177..97caa7d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -209,6 +209,7 @@
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Base64;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.ExceptionUtils;
@@ -286,6 +287,7 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.SecureRandom;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
@@ -337,7 +339,7 @@
  *
  * <pre>
  * $ runtest -c android.content.pm.PackageManagerTests frameworks-core
- * $ cts-tradefed run commandAndExit cts -m AppSecurityTests
+ * $ cts-tradefed run commandAndExit cts -m CtsAppSecurityHostTestCases
  * </pre>
  */
 public class PackageManagerService extends IPackageManager.Stub {
@@ -14261,11 +14263,13 @@
     }
 
     private File getNextCodePath(File targetDir, String packageName) {
-        int suffix = 1;
         File result;
+        SecureRandom random = new SecureRandom();
+        byte[] bytes = new byte[16];
         do {
+            random.nextBytes(bytes);
+            String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
             result = new File(targetDir, packageName + "-" + suffix);
-            suffix++;
         } while (result.exists());
         return result;
     }