diff options
author | Songchun Fan <schfan@google.com> | 2020-02-03 21:06:52 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-03 21:06:52 +0000 |
commit | bf3e455597b6972ff2a7f80f5aaab16a36f5880b (patch) | |
tree | 4be6b10c4175b3d094d3208df32b21973cca5e83 | |
parent | 0dcce3b875ced0b86dc9322e84f47a8c0375e41d (diff) | |
parent | f56f1c5c587ed5af452ed1b339218dabc12c9f93 (diff) |
Merge "Change app code path"
5 files changed, 57 insertions, 26 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index dfe9fe64657d..b6b27b6e514a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -954,6 +954,10 @@ public class PackageParser { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } + // Apk directory is directly nested under the current directory + if (files.length == 1 && files[0].isDirectory()) { + return parseClusterPackageLite(files[0], flags); + } String packageName = null; int versionCode = 0; @@ -1327,12 +1331,9 @@ public class PackageParser { } } - pkg.setCodePath(packageDir.getCanonicalPath()); + pkg.setCodePath(lite.codePath); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg; - } catch (IOException e) { - throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, - "Failed to get path: " + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 90a332ccb430..5be9c910744d 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -97,6 +97,10 @@ public class ApkLiteParseUtils { throw new PackageParser.PackageParserException( PackageManager.INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } + // Apk directory is directly nested under the current directory + if (files.length == 1 && files[0].isDirectory()) { + return parseClusterPackageLite(files[0], flags); + } String packageName = null; int versionCode = 0; diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java index 7506412f72cc..5c8c9a41a520 100644 --- a/core/java/android/content/pm/parsing/ApkParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkParseUtils.java @@ -205,11 +205,8 @@ public class ApkParseUtils { } } - return parsingPackage.setCodePath(packageDir.getCanonicalPath()) + return parsingPackage.setCodePath(lite.codePath) .setUse32BitAbi(lite.use32bitAbi); - } catch (IOException e) { - throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, - "Failed to get path: " + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 40c07e3694d9..d6fd4d040352 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -117,6 +117,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.dumpCriticalInfo; import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFiles; import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; +import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive; import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures; import android.Manifest; @@ -361,7 +362,6 @@ import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -651,6 +651,8 @@ public class PackageManagerService extends IPackageManager.Stub private static final String[] INSTANT_APP_BROADCAST_PERMISSION = new String[] { android.Manifest.permission.ACCESS_INSTANT_APPS }; + private static final String RANDOM_DIR_PREFIX = "~~"; + final ServiceThread mHandlerThread; final PackageHandler mHandler; @@ -2996,9 +2998,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - //delete tmp files - deleteTempPackageFiles(); - final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get(); // Remove any shared userIDs that have no associated packages @@ -3591,8 +3590,7 @@ public class PackageManagerService extends IPackageManager.Stub getNextCodePath(Environment.getDataAppDirectory(null), packageName); int ret = PackageManager.INSTALL_SUCCEEDED; try { - Os.mkdir(dstCodePath.getAbsolutePath(), 0755); - Os.chmod(dstCodePath.getAbsolutePath(), 0755); + makeDirRecursive(dstCodePath, 0755); for (File srcFile : compressedFiles) { final String srcFileName = srcFile.getName(); final String dstFileName = srcFileName.substring( @@ -9852,8 +9850,12 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mInstallLock") void removeCodePathLI(File codePath) { if (codePath.isDirectory()) { + File codePathParent = codePath.getParentFile(); try { mInstaller.rmPackageDir(codePath.getAbsolutePath()); + if (codePathParent.getName().startsWith(RANDOM_DIR_PREFIX)) { + mInstaller.rmPackageDir(codePathParent.getAbsolutePath()); + } } catch (InstallerException e) { Slog.w(TAG, "Failed to remove code path", e); } @@ -14926,7 +14928,9 @@ public class PackageManagerService extends IPackageManager.Stub final boolean onIncremental = mIncrementalManager != null && isIncrementalPath(beforeCodeFile.getAbsolutePath()); try { + makeDirRecursive(afterCodeFile.getParentFile(), 0775); if (onIncremental) { + // TODO(b/147371381): fix incremental installation mIncrementalManager.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath()); } else { @@ -15138,16 +15142,29 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * Given {@code targetDir}, returns {@code targetDir/~~[randomStrA]/[packageName]-[randomStrB].} + * Makes sure that {@code targetDir/~~[randomStrA]} directory doesn't exist. + * Notice that this method doesn't actually create any directory. + * + * @param targetDir Directory that is two-levels up from the result directory. + * @param packageName Name of the package whose code files are to be installed under the result + * directory. + * @return File object for the directory that should hold the code files of {@code packageName}. + */ private File getNextCodePath(File targetDir, String packageName) { - File result; SecureRandom random = new SecureRandom(); byte[] bytes = new byte[16]; + File firstLevelDir; do { random.nextBytes(bytes); - String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); - result = new File(targetDir, packageName + "-" + suffix); - } while (result.exists()); - return result; + String dirName = RANDOM_DIR_PREFIX + + Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); + firstLevelDir = new File(targetDir, dirName); + } while (firstLevelDir.exists()); + random.nextBytes(bytes); + String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP); + return new File(firstLevelDir, packageName + "-" + suffix); } static class PackageInstalledInfo { @@ -17142,12 +17159,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - private void deleteTempPackageFiles() { - // TODO: Is this used? - final FilenameFilter filter = - (dir, name) -> name.startsWith("vmdl") && name.endsWith(".tmp"); - } - @Override public void deletePackageAsUser(String packageName, int versionCode, IPackageDeleteObserver observer, int userId, int flags) { @@ -21477,7 +21488,7 @@ public class PackageManagerService extends IPackageManager.Stub final int absoluteCodePathCount = absoluteCodePaths.size(); for (int i = 0; i < absoluteCodePathCount; i++) { String absoluteCodePath = absoluteCodePaths.get(i); - if (absolutePath.startsWith(absoluteCodePath)) { + if (absoluteCodePath.startsWith(absolutePath)) { pathValid = true; break; } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index ded9a9c58c5e..71a5545c4131 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -83,6 +83,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; +import java.nio.file.Path; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.text.SimpleDateFormat; @@ -918,4 +919,21 @@ public class PackageManagerServiceUtils { } return packageSetting.getPermissionsState(); } + + /** + * Recursively create target directory + */ + public static void makeDirRecursive(File targetDir, int mode) throws ErrnoException { + final Path targetDirPath = targetDir.toPath(); + final int directoriesCount = targetDirPath.getNameCount(); + File currentDir; + for (int i = 1; i <= directoriesCount; i++) { + currentDir = targetDirPath.subpath(0, i).toFile(); + if (currentDir.exists()) { + continue; + } + Os.mkdir(currentDir.getAbsolutePath(), mode); + Os.chmod(currentDir.getAbsolutePath(), mode); + } + } } |