summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSongchun Fan <schfan@google.com>2020-02-03 21:06:52 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-02-03 21:06:52 +0000
commitbf3e455597b6972ff2a7f80f5aaab16a36f5880b (patch)
tree4be6b10c4175b3d094d3208df32b21973cca5e83
parent0dcce3b875ced0b86dc9322e84f47a8c0375e41d (diff)
parentf56f1c5c587ed5af452ed1b339218dabc12c9f93 (diff)
Merge "Change app code path"
-rw-r--r--core/java/android/content/pm/PackageParser.java9
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java4
-rw-r--r--core/java/android/content/pm/parsing/ApkParseUtils.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java47
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java18
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);
+ }
+ }
}