diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index bb90fd7993ced..514b26e5866de 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -410,10 +410,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public int largestWidthLimitDp = 0;
+ /** {@hide} */
+ public String scanSourceDir;
+ /** {@hide} */
+ public String scanPublicSourceDir;
+
/**
* Full path to the base APK for this application.
*/
- // TODO: verify that nobody is doing codePath comparisons against this
public String sourceDir;
/**
@@ -779,11 +783,25 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
return true;
}
}
-
+
/**
* @hide
*/
@Override protected ApplicationInfo getApplicationInfo() {
return this;
}
+
+ /** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; }
+ /** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; }
+ /** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; }
+ /** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
+ /** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
+ /** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
+
+ /** {@hide} */ public String getCodePath() { return scanSourceDir; }
+ /** {@hide} */ public String getBaseCodePath() { return sourceDir; }
+ /** {@hide} */ public String[] getSplitCodePaths() { return splitSourceDirs; }
+ /** {@hide} */ public String getResourcePath() { return scanPublicSourceDir; }
+ /** {@hide} */ public String getBaseResourcePath() { return publicSourceDir; }
+ /** {@hide} */ public String[] getSplitResourcePaths() { return splitSourceDirs; }
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bb4712416a834..7651aeff82470 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -719,7 +719,12 @@ public class PackageParser {
*
* Note that this does not perform signature verification; that
* must be done separately in {@link #collectCertificates(Package, int)}.
+ *
+ * @deprecated external callers should move to
+ * {@link #parsePackage(File, int)}. Eventually this method will
+ * be marked private.
*/
+ @Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
final Package pkg = parseBaseApk(apkFile, flags);
if (pkg == null) {
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 4c34d461d29c2..fe47f5b84d3f0 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -371,6 +371,8 @@ public class FileUtils {
* attacks.
*/
public static boolean contains(File dir, File file) {
+ if (file == null) return false;
+
String dirPath = dir.getAbsolutePath();
String filePath = file.getAbsolutePath();
@@ -418,16 +420,27 @@ public class FileUtils {
}
public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
+ if (path == null) return null;
final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
return (result != null) ? result.getAbsolutePath() : null;
}
+ public static String[] rewriteAfterRename(File beforeDir, File afterDir, String[] paths) {
+ if (paths == null) return null;
+ final String[] result = new String[paths.length];
+ for (int i = 0; i < paths.length; i++) {
+ result[i] = rewriteAfterRename(beforeDir, afterDir, paths[i]);
+ }
+ return result;
+ }
+
/**
* Given a path under the "before" directory, rewrite it to live under the
* "after" directory. For example, {@code /before/foo/bar.txt} would become
* {@code /after/foo/bar.txt}.
*/
public static File rewriteAfterRename(File beforeDir, File afterDir, File file) {
+ if (file == null) return null;
if (contains(beforeDir, file)) {
final String splice = file.getAbsolutePath().substring(
beforeDir.getAbsolutePath().length());
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 71d12c6d045d2..84aa4279d837d 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -28,9 +28,15 @@ import java.io.FileDescriptor;
* {@hide}
*/
public class SELinux {
-
private static final String TAG = "SELinux";
+ /** Keep in sync with ./external/libselinux/include/selinux/android.h */
+ private static final int SELINUX_ANDROID_RESTORECON_NOCHANGE = 1;
+ private static final int SELINUX_ANDROID_RESTORECON_VERBOSE = 2;
+ private static final int SELINUX_ANDROID_RESTORECON_RECURSE = 4;
+ private static final int SELINUX_ANDROID_RESTORECON_FORCE = 8;
+ private static final int SELINUX_ANDROID_RESTORECON_DATADATA = 16;
+
/**
* Determine whether SELinux is disabled or enabled.
* @return a boolean indicating whether SELinux is enabled.
@@ -136,7 +142,7 @@ public class SELinux {
*/
public static boolean restorecon(String pathname) throws NullPointerException {
if (pathname == null) { throw new NullPointerException(); }
- return native_restorecon(pathname);
+ return native_restorecon(pathname, 0);
}
/**
@@ -149,7 +155,7 @@ public class SELinux {
* @param pathname The pathname of the file to be relabeled.
* @return a boolean indicating whether the relabeling succeeded.
*/
- private static native boolean native_restorecon(String pathname);
+ private static native boolean native_restorecon(String pathname, int flags);
/**
* Restores a file to its default SELinux security context.
@@ -164,10 +170,10 @@ public class SELinux {
*/
public static boolean restorecon(File file) throws NullPointerException {
try {
- return native_restorecon(file.getCanonicalPath());
+ return native_restorecon(file.getCanonicalPath(), 0);
} catch (IOException e) {
Slog.e(TAG, "Error getting canonical path. Restorecon failed for " +
- file.getPath(), e);
+ file.getPath(), e);
return false;
}
}
@@ -180,14 +186,13 @@ public class SELinux {
*
* @return a boolean indicating whether the relabeling succeeded.
*/
- public static boolean restoreconTree(File dir) {
- final File[] files = dir.listFiles();
- boolean success = true;
- if (files != null) {
- for (File file : files) {
- success &= restorecon(file);
- }
+ public static boolean restoreconRecursive(File file) {
+ try {
+ return native_restorecon(file.getCanonicalPath(), SELINUX_ANDROID_RESTORECON_RECURSE);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error getting canonical path. Restorecon failed for " +
+ file.getPath(), e);
+ return false;
}
- return success;
}
}
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 26405b59a3865..ffa569e7e0fa5 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -404,7 +404,7 @@ static jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextS
* Returns: boolean: (true) file label successfully restored, (false) otherwise
* Exceptions: none
*/
-static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) {
+static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr, jint flags) {
if (isSELinuxDisabled) {
return true;
}
@@ -415,7 +415,7 @@ static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) {
return false;
}
- int ret = selinux_android_restorecon(pathname.c_str(), 0);
+ int ret = selinux_android_restorecon(pathname.c_str(), flags);
ALOGV("restorecon(%s) => %d", pathname.c_str(), ret);
return (ret == 0);
}
@@ -434,7 +434,7 @@ static JNINativeMethod method_table[] = {
{ "getPidContext" , "(I)Ljava/lang/String;" , (void*)getPidCon },
{ "isSELinuxEnforced" , "()Z" , (void*)isSELinuxEnforced},
{ "isSELinuxEnabled" , "()Z" , (void*)isSELinuxEnabled },
- { "native_restorecon" , "(Ljava/lang/String;)Z" , (void*)native_restorecon},
+ { "native_restorecon" , "(Ljava/lang/String;I)Z" , (void*)native_restorecon},
{ "setBooleanValue" , "(Ljava/lang/String;Z)Z" , (void*)setBooleanValue },
{ "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
{ "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 7a21b92e7e7e6..67ed97cf51d01 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -499,19 +499,26 @@ public class DefaultContainerService extends IntentService {
private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target)
throws IOException, RemoteException {
- // TODO: extend to support copying all split APKs
+ copyFile(pkg.baseCodePath, "base.apk", target);
if (!ArrayUtils.isEmpty(pkg.splitNames)) {
- throw new UnsupportedOperationException("Copying split APKs not yet supported");
+ for (int i = 0; i < pkg.splitNames.length; i++) {
+ copyFile(pkg.splitCodePaths[i], "split_" + pkg.splitNames[i] + ".apk", target);
+ }
}
+ return PackageManager.INSTALL_SUCCEEDED;
+ }
+
+ private void copyFile(String sourcePath, String targetName,
+ IParcelFileDescriptorFactory target) throws IOException, RemoteException {
+ Slog.d(TAG, "Copying " + sourcePath + " to " + targetName);
InputStream in = null;
OutputStream out = null;
try {
- in = new FileInputStream(pkg.baseCodePath);
+ in = new FileInputStream(sourcePath);
out = new ParcelFileDescriptor.AutoCloseOutputStream(
- target.open(null, ParcelFileDescriptor.MODE_READ_WRITE));
+ target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE));
Streams.copy(in, out);
- return PackageManager.INSTALL_SUCCEEDED;
} finally {
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(in);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 3c996b6d15f78..b31a3d6d2c7ab 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2925,7 +2925,8 @@ public class BackupManagerService extends IBackupManager.Stub {
private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) {
// Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
- final String appSourceDir = pkg.applicationInfo.sourceDir;
+ // TODO: handle backing up split APKs
+ final String appSourceDir = pkg.applicationInfo.getBaseCodePath();
final String apkDir = new File(appSourceDir).getParent();
FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
apkDir, appSourceDir, output);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index c011cf99f5767..8067bd9f85a3e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -344,11 +344,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final ApkLite info;
try {
- info = PackageParser.parseApkLite(new File(app.sourceDir),
+ info = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
PackageParser.PARSE_GET_SIGNATURES);
} catch (PackageParserException e) {
throw new InstallFailedException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse existing base " + app.sourceDir + ": " + e);
+ "Failed to parse existing base " + app.getBaseCodePath() + ": " + e);
}
assertPackageConsistent("Existing base", info.packageName, info.versionCode,
@@ -379,7 +379,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
*/
private void spliceExistingFilesIntoStage() throws InstallFailedException {
final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
- final File existingDir = new File(app.sourceDir).getParentFile();
+ final File existingDir = new File(app.getBaseCodePath());
try {
linkTreeIgnoringExisting(existingDir, sessionDir);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c80f316a0dd69..a660fbb87049e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -30,8 +30,10 @@ import static android.content.pm.PackageParser.isApkFile;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.EEXIST;
import static android.system.OsConstants.O_EXCL;
import static android.system.OsConstants.O_RDWR;
+import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.S_IRGRP;
import static android.system.OsConstants.S_IROTH;
import static android.system.OsConstants.S_IRWXU;
@@ -103,6 +105,7 @@ import android.content.pm.PackageInfoLite;
import android.content.pm.PackageInstallerParams;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageParser;
import android.content.pm.PackageStats;
@@ -146,6 +149,7 @@ import android.security.KeyStore;
import android.security.SystemKeyStore;
import android.system.ErrnoException;
import android.system.Os;
+import android.system.OsConstants;
import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -190,6 +194,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -375,6 +380,8 @@ public class PackageManagerService extends IPackageManager.Stub {
/** Directory where third-party apps are staged before install */
final File mAppStagingDir;
+ private final Random mTempFileRandom = new Random();
+
// ----------------------------------------------------------------
// Lock for state used when installing and doing other long running
@@ -4085,7 +4092,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
int i = 0;
for (PackageParser.Package p : overlayArray) {
- pkg.applicationInfo.resourceDirs[i++] = p.applicationInfo.sourceDir;
+ pkg.applicationInfo.resourceDirs[i++] = p.baseCodePath;
}
return true;
}
@@ -4184,8 +4191,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private PackageParser.Package scanPackageLI(File scanFile,
int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
- String scanPath = scanFile.getPath();
- if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath);
+ if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
@@ -4198,7 +4204,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final PackageParser.Package pkg;
try {
- pkg = pp.parseMonolithicPackage(scanFile, parseFlags);
+ pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
mLastScanError = e.error;
return null;
@@ -4357,27 +4363,29 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- final String baseCodePath = pkg.baseCodePath;
- final String[] splitCodePaths = pkg.splitCodePaths;
-
// TODO: extend to support forward-locked splits
- String baseResPath = null;
+ String resourcePath = null;
+ String baseResourcePath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
- baseResPath = ps.resourcePathString;
+ resourcePath = ps.resourcePathString;
+ baseResourcePath = ps.resourcePathString;
} else {
// Should not happen at all. Just log an error.
Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
}
} else {
- baseResPath = pkg.baseCodePath;
+ resourcePath = pkg.codePath;
+ baseResourcePath = pkg.baseCodePath;
}
// Set application objects path explicitly.
- pkg.applicationInfo.sourceDir = baseCodePath;
- pkg.applicationInfo.publicSourceDir = baseResPath;
- pkg.applicationInfo.splitSourceDirs = splitCodePaths;
- pkg.applicationInfo.splitPublicSourceDirs = splitCodePaths;
+ pkg.applicationInfo.setCodePath(pkg.codePath);
+ pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+ pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+ pkg.applicationInfo.setResourcePath(resourcePath);
+ pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
+ pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
@@ -4906,8 +4914,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
final File scanFile = new File(pkg.codePath);
- if (pkg.applicationInfo.sourceDir == null ||
- pkg.applicationInfo.publicSourceDir == null) {
+ if (pkg.applicationInfo.getCodePath() == null ||
+ pkg.applicationInfo.getResourcePath() == null) {
// Bail out. The resource and code paths haven't been set.
Slog.w(TAG, " Code and resource paths haven't been set correctly");
mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
@@ -4978,8 +4986,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Initialize package source and resource directories
- File destCodeFile = new File(pkg.applicationInfo.sourceDir);
- File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
+ File destCodeFile = new File(pkg.applicationInfo.getCodePath());
+ File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
@@ -6137,19 +6145,22 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageSetting pkgSetting) {
// "bundled" here means system-installed with no overriding update
final boolean bundledApk = isSystemApp(pkg) && !isUpdatedSystemApp(pkg);
- final String apkName = getApkName(pkg.applicationInfo.sourceDir);
- final File libDir;
+ final File codeFile = new File(pkg.applicationInfo.getCodePath());
+ final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
+ final String nativeLibraryPath;
if (bundledApk) {
// If "/system/lib64/apkname" exists, assume that is the per-package
// native library directory to use; otherwise use "/system/lib/apkname".
- String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+ String apkRoot = calculateApkRoot(pkg.applicationInfo.getCodePath());
File lib64 = new File(apkRoot, LIB64_DIR_NAME);
File packLib64 = new File(lib64, apkName);
- libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
+ File libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
+ nativeLibraryPath = (new File(libDir, apkName)).getAbsolutePath();
} else {
- libDir = mAppLibInstallDir;
+ // We're installing an upgrade; use directory found during scan
+ // TODO: consider deriving this based on instructionSet
+ nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
}
- final String nativeLibraryPath = (new File(libDir, apkName)).getPath();
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
// pkgSetting might be null during rescan following uninstall of updates
// to a bundled app, so accommodate that possibility. The settings in
@@ -6161,8 +6172,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Deduces the required ABI of an upgraded system app.
private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) {
- final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
- final String apkName = getApkName(pkg.applicationInfo.sourceDir);
+ final String apkRoot = calculateApkRoot(pkg.applicationInfo.getCodePath());
+ final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
// This is of the form "/system/lib64/", "/vendor/lib64/"
// or similar.
@@ -8973,7 +8984,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return new AsecInstallArgs(codeFile, cid, instructionSet, installOnSd(flags),
installForwardLocked(flags));
} else {
- return new FileInstallArgs(codeFile, pkgName, instructionSet);
+ return new FileInstallArgs(codeFile, instructionSet);
}
}
@@ -9013,7 +9024,12 @@ public class PackageManagerService extends IPackageManager.Stub {
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
abstract int doPreInstall(int status);
- abstract boolean doRename(int status, String pkgName, String oldCodePath);
+
+ /**
+ * Rename package into final resting place. All paths on the given
+ * scanned package should be updated to reflect the rename.
+ */
+ abstract boolean doRename(int status, PackageParser.Package pkg, String oldCodePath);
abstract int doPostInstall(int status, int uid);
/** @see PackageSettingBase#codePathString */
@@ -9062,13 +9078,15 @@ public class PackageManagerService extends IPackageManager.Stub {
* and renaming logic.
*/
class FileInstallArgs extends InstallArgs {
- // TODO: teach about handling cluster directories
+ private File codeFile;
+ private File resourceFile;
+ private File nativeLibraryFile;
- File installDir;
- String codeFileName;
- String resourceFileName;
- String libraryPath;
- boolean created = false;
+ // Example topology:
+ // /data/app/com.example/base.apk
+ // /data/app/com.example/split_foo.apk
+ // /data/app/com.example/native/arm/libfoo.so
+ // /data/app/com.example/dalvik/arm/base.apk@classes.dex
/** New install */
FileInstallArgs(InstallParams params) {
@@ -9076,27 +9094,23 @@ public class PackageManagerService extends IPackageManager.Stub {
params.flags, params.installerPackageName, params.getManifestDigest(),
params.getUser(), params.packageInstructionSetOverride,
params.packageAbiOverride);
+ if (isFwdLocked()) {
+ throw new IllegalArgumentException("Forward locking only supported in ASEC");
+ }
}
/** Existing install */
- FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
+ FileInstallArgs(String codePath, String resourcePath, String nativeLibraryPath,
String instructionSet) {
super(null, false, null, null, 0, null, null, null, instructionSet, null);
- File codeFile = new File(fullCodePath);
- installDir = codeFile.getParentFile();
- codeFileName = fullCodePath;
- resourceFileName = fullResourcePath;
- libraryPath = nativeLibraryPath;
+ this.codeFile = (codePath != null) ? new File(codePath) : null;
+ this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
+ this.nativeLibraryFile = (nativeLibraryPath != null) ? new File(nativeLibraryPath) : null;
}
/** New install from existing */
- FileInstallArgs(File originFile, String pkgName, String instructionSet) {
+ FileInstallArgs(File originFile, String instructionSet) {
super(originFile, true, null, null, 0, null, null, null, instructionSet, null);
- installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
- String apkName = getNextCodePath(null, pkgName, ".apk");
- codeFileName = new File(installDir, apkName + ".apk").getPath();
- resourceFileName = getResourcePathFromCodePath();
- libraryPath = new File(mAppLibInstallDir, pkgName).getPath();
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -9120,70 +9134,38 @@ public class PackageManagerService extends IPackageManager.Stub {
lowThreshold);
}
- void createCopyFile() {
- installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
- codeFileName = createTempPackageFile(installDir).getPath();
- resourceFileName = getResourcePathFromCodePath();
- libraryPath = getLibraryPathFromCodePath();
- created = true;
- }
-
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
- if (temp) {
- // Generate temp file name
- createCopyFile();
- }
- // Get a ParcelFileDescriptor to write to the output file
- final File codeFile = new File(codeFileName);
- if (!created) {
- try {
- codeFile.createNewFile();
- // Set permissions
- if (!setPermissions()) {
- // Failed setting permissions.
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
- } catch (IOException e) {
- Slog.w(TAG, "Failed to create file " + codeFile);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
+ try {
+ final File tempDir = createTempPackageDir(mAppInstallDir);
+ codeFile = tempDir;
+ resourceFile = tempDir;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to create copy file: " + e);
+ return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
- // TODO: extend to support copying into clusters
final IParcelFileDescriptorFactory target = new IParcelFileDescriptorFactory.Stub() {
@Override
public ParcelFileDescriptor open(String name, int mode) throws RemoteException {
+ if (!FileUtils.isValidExtFilename(name)) {
+ throw new IllegalArgumentException("Invalid filename: " + name);
+ }
try {
- return ParcelFileDescriptor.open(codeFile,
- ParcelFileDescriptor.MODE_READ_WRITE);
- } catch (FileNotFoundException e) {
- throw new RemoteException(e.getMessage());
+ final File file = new File(codeFile, name);
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(),
+ O_RDWR | O_CREAT, 0644);
+ Os.chmod(file.getAbsolutePath(), 0644);
+ return new ParcelFileDescriptor(fd);
+ } catch (ErrnoException e) {
+ throw new RemoteException("Failed to open: " + e.getMessage());
}
}
};
- // Copy the resource now
int ret = imcs.copyPackage(originFile.getAbsolutePath(), target);
-
- if (isFwdLocked()) {
- final File destResourceFile = new File(getResourcePath());
-
- // Copy the public files
- try {
- PackageHelper.extractPublicFiles(codeFileName, destResourceFile);
- } catch (IOException e) {
- Slog.e(TAG, "Couldn't create a new zip file for the public parts of a"
- + " forward-locked app.");
- destResourceFile.delete();
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
- }
-
- final File nativeLibraryFile = new File(getNativeLibraryPath());
- Slog.i(TAG, "Copying native libraries to " + nativeLibraryFile.getPath());
- if (nativeLibraryFile.exists()) {
- NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
- nativeLibraryFile.delete();
+ if (ret != PackageManager.INSTALL_SUCCEEDED) {
+ Slog.e(TAG, "Failed to copy package");
+ return ret;
}
String[] abiList = (abiOverride != null) ?
@@ -9197,11 +9179,24 @@ public class PackageManagerService extends IPackageManager.Stub {
abiList = Build.SUPPORTED_32_BIT_ABIS;
}
- int copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryFile, abiList);
- if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- return copyRet;
+ // TODO: refactor to avoid double findSupportedAbi()
+ final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList);
+ if (abiIndex < 0 && abiIndex != PackageManager.NO_NATIVE_LIBRARIES) {
+ return abiIndex;
+ } else if (abiIndex >= 0) {
+ final File baseLibFile = new File(codeFile, LIB_DIR_NAME);
+ baseLibFile.mkdir();
+ Os.chmod(baseLibFile.getAbsolutePath(), 0755);
+
+ final String abi = Build.SUPPORTED_ABIS[abiIndex];
+ final String instructionSet = VMRuntime.getInstructionSet(abi);
+ nativeLibraryFile = new File(baseLibFile, instructionSet);
+ nativeLibraryFile.mkdir();
+ Os.chmod(nativeLibraryFile.getAbsolutePath(), 0755);
+
+ copyNativeLibrariesForInternalApp(handle, nativeLibraryFile, abiList);
}
- } catch (IOException e) {
+ } catch (IOException | ErrnoException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
@@ -9218,51 +9213,44 @@ public class PackageManagerService extends IPackageManager.Stub {
return status;
}
- boolean doRename(int status, final String pkgName, String oldCodePath) {
+ boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
cleanUp();
return false;
} else {
- final File oldCodeFile = new File(getCodePath());
- final File oldResourceFile = new File(getResourcePath());
- final File oldLibraryFile = new File(getNativeLibraryPath());
+ final File beforeCodeFile = codeFile;
+ final File afterCodeFile = new File(mAppInstallDir,
+ getNextCodePath(oldCodePath, pkg.packageName, null));
- // Rename APK file based on packageName
- final String apkName = getNextCodePath(oldCodePath, pkgName, ".apk");
- final File newCodeFile = new File(installDir, apkName + ".apk");
- if (!oldCodeFile.renameTo(newCodeFile)) {
+ Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
+ if (!beforeCodeFile.renameTo(afterCodeFile)) {
return false;
}
- codeFileName = newCodeFile.getPath();
-
- // Rename public resource file if it's forward-locked.
- final File newResFile = new File(getResourcePathFromCodePath());
- if (isFwdLocked() && !oldResourceFile.renameTo(newResFile)) {
- return false;
- }
- resourceFileName = newResFile.getPath();
-
- // Rename library path
- final File newLibraryFile = new File(getLibraryPathFromCodePath());
- if (newLibraryFile.exists()) {
- NativeLibraryHelper.removeNativeBinariesFromDirLI(newLibraryFile);
- newLibraryFile.delete();
- }
- if (!oldLibraryFile.renameTo(newLibraryFile)) {
- Slog.e(TAG, "Cannot rename native library directory "
- + oldLibraryFile.getPath() + " to " + newLibraryFile.getPath());
- return false;
- }
- libraryPath = newLibraryFile.getPath();
-
- // Attempt to set permissions
- if (!setPermissions()) {
+ if (!SELinux.restoreconRecursive(afterCodeFile)) {
return false;
}
- if (!SELinux.restorecon(newCodeFile)) {
- return false;
- }
+ // Reflect the rename internally
+ codeFile = afterCodeFile;
+ resourceFile = afterCodeFile;
+ nativeLibraryFile = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+ nativeLibraryFile);
+
+ // Reflect the rename in scanned details
+ pkg.codePath = afterCodeFile.getAbsolutePath();
+ pkg.baseCodePath = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+ pkg.baseCodePath);
+ pkg.splitCodePaths = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
+ pkg.splitCodePaths);
+
+ // Reflect the rename in app info
+ pkg.applicationInfo.setCodePath(pkg.codePath);
+ pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
+ pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
+ pkg.applicationInfo.setResourcePath(pkg.codePath);
+ pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
+ pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
+ pkg.applicationInfo.nativeLibraryDir = getNativeLibraryPath();
return true;
}
@@ -9275,120 +9263,71 @@ public class PackageManagerService extends IPackageManager.Stub {
return status;
}
- private String getResourcePathFromCodePath() {
- final String codePath = getCodePath();
- if (isFwdLocked()) {
- final StringBuilder sb = new StringBuilder();
-
- sb.append(mAppInstallDir.getPath());
- sb.append('/');
- sb.append(getApkName(codePath));
- sb.append(".zip");
-
- /*
- * If our APK is a temporary file, mark the resource as a
- * temporary file as well so it can be cleaned up after
- * catastrophic failure.
- */
- if (codePath.endsWith(".tmp")) {
- sb.append(".tmp");
- }
-
- return sb.toString();
- } else {
- return codePath;
- }
- }
-
- private String getLibraryPathFromCodePath() {
- return new File(mAppLibInstallDir, getApkName(getCodePath())).getPath();
- }
-
@Override
String getCodePath() {
- return codeFileName;
+ return (codeFile != null) ? codeFile.getAbsolutePath() : null;
}
@Override
String getResourcePath() {
- return resourceFileName;
+ return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
}
@Override
String getNativeLibraryPath() {
- if (libraryPath == null) {
- libraryPath = getLibraryPathFromCodePath();
- }
- return libraryPath;
+ return (nativeLibraryFile != null) ? nativeLibraryFile.getAbsolutePath() : null;
}
private boolean cleanUp() {
- boolean ret = true;
- String sourceDir = getCodePath();
- String publicSourceDir = getResourcePath();
- if (sourceDir != null) {
- File sourceFile = new File(sourceDir);
- if (!sourceFile.exists()) {
- Slog.w(TAG, "Package source " + sourceDir + " does not exist.");
- ret = false;
- }
- // Delete application's code and resources
- sourceFile.delete();
- }
- if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) {
- final File publicSourceFile = new File(publicSourceDir);
- if (!publicSourceFile.exists()) {
- Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist.");
- }
- if (publicSourceFile.exists()) {
- publicSourceFile.delete();
- }
+ if (codeFile == null || !codeFile.exists()) {
+ return false;
}
- if (libraryPath != null) {
- File nativeLibraryFile = new File(libraryPath);
- NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
- if (!nativeLibraryFile.delete()) {
- Slog.w(TAG, "Couldn't delete native library directory " + libraryPath);
- }
+ if (codeFile.isDirectory()) {
+ FileUtils.deleteContents(codeFile);
+ }
+ codeFile.delete();
+
+ if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
+ resourceFile.delete();
}
- return ret;
+ if (nativeLibraryFile != null && !FileUtils.contains(codeFile, nativeLibraryFile)) {
+ FileUtils.deleteContents(nativeLibraryFile);
+ nativeLibraryFile.delete();
+ }
+
+ return true;
}
void cleanUpResourcesLI() {
- String sourceDir = getCodePath();
- if (cleanUp()) {
+ // Try enumerating all code paths before deleting
+ List allCodePaths = Collections.EMPTY_LIST;
+ if (codeFile != null && codeFile.exists()) {
+ try {
+ final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
+ allCodePaths = pkg.getAllCodePaths();
+ } catch (PackageParserException e) {
+ // Ignored; we tried our best
+ }
+ }
+
+ cleanUp();
+
+ if (!allCodePaths.isEmpty()) {
if (instructionSet == null) {
throw new IllegalStateException("instructionSet == null");
}
- int retCode = mInstaller.rmdex(sourceDir, instructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package: "
- + " at location "
- + sourceDir + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
- }
- }
- }
- private boolean setPermissions() {
- // TODO Do this in a more elegant way later on. for now just a hack
- if (!isFwdLocked()) {
- final int filePermissions =
- FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
- |FileUtils.S_IROTH;
- int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1);
- if (retCode != 0) {
- Slog.e(TAG, "Couldn't set new package file permissions for " +
- getCodePath()
- + ". The return code was: " + retCode);
- // TODO Define new internal error
- return false;
+ for (String codePath : allCodePaths) {
+ int retCode = mInstaller.rmdex(codePath, instructionSet);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove dex file for package: "
+ + " at location " + codePath + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
+ }
}
- return true;
}
- return true;
}
boolean doPostDeleteLI(boolean delete) {
@@ -9538,9 +9477,8 @@ public class PackageManagerService extends IPackageManager.Stub {
return status;
}
- boolean doRename(int status, final String pkgName,
- String oldCodePath) {
- String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME);
+ boolean doRename(int status, PackageParser.Package pkg, String oldCodePath) {
+ String newCacheId = getNextCodePath(oldCodePath, pkg.packageName, "/" + RES_FILE_NAME);
String newCachePath = null;
if (PackageHelper.isContainerMounted(cid)) {
// Unmount the container
@@ -9580,6 +9518,20 @@ public class PackageManagerService extends IPackageManager.Stub {
" at new path: " + newCachePath);
cid = newCacheId;
setCachePath(newCachePath);
+
+ // TODO: extend to support split APKs
+ pkg.codePath = getCodePath();
+ pkg.baseCodePath = getCodePath();
+ pkg.splitCodePaths = null;
+
+ pkg.applicationInfo.setCodePath(getCodePath());
+ pkg.applicationInfo.setBaseCodePath(getCodePath());
+ pkg.applicationInfo.setSplitCodePaths(null);
+ pkg.applicationInfo.setResourcePath(getResourcePath());
+ pkg.applicationInfo.setBaseResourcePath(getResourcePath());
+ pkg.applicationInfo.setSplitResourcePaths(null);
+ pkg.applicationInfo.nativeLibraryDir = getNativeLibraryPath();
+
return true;
}
@@ -9716,7 +9668,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (oldCodePath != null) {
String subStr = oldCodePath;
// Drop the suffix right away
- if (subStr.endsWith(suffix)) {
+ if (suffix != null && subStr.endsWith(suffix)) {
subStr = subStr.substring(0, subStr.length() - suffix.length());
}
// If oldCodePath already contains prefix find out the
@@ -9747,7 +9699,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Utility method used to ignore ADD/REMOVE events
// by directory observer.
private static boolean ignoreCodePath(String fullPathStr) {
- String apkName = getApkName(fullPathStr);
+ String apkName = deriveCodePathName(fullPathStr);
int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX);
if (idx != -1 && ((idx+1) < apkName.length())) {
// Make sure the package ends with a numeral
@@ -9763,33 +9715,21 @@ public class PackageManagerService extends IPackageManager.Stub {
// Utility method that returns the relative package path with respect
// to the installation directory. Like say for /data/data/com.test-1.apk
// string com.test-1 is returned.
- static String getApkName(String codePath) {
+ static String deriveCodePathName(String codePath) {
if (codePath == null) {
return null;
}
- int sidx = codePath.lastIndexOf("/");
- int eidx = codePath.lastIndexOf(".");
- if (eidx == -1) {
- eidx = codePath.length();
- } else if (eidx == 0) {
- Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name");
+ final File codeFile = new File(codePath);
+ final String name = codeFile.getName();
+ if (codeFile.isDirectory()) {
+ return name;
+ } else if (name.endsWith(".apk") || name.endsWith(".tmp")) {
+ final int lastDot = name.lastIndexOf('.');
+ return name.substring(0, lastDot);
+ } else {
+ Slog.w(TAG, "Odd, " + codePath + " doesn't look like an APK");
return null;
}
- return codePath.substring(sidx+1, eidx);
- }
-
- private static String[] deriveSplitResPaths(String[] splitCodePaths) {
- String[] splitResPaths = null;
- if (!ArrayUtils.isEmpty(splitCodePaths)) {
- splitResPaths = new String[splitCodePaths.length];
- for (int i = 0; i < splitCodePaths.length; i++) {
- final String splitCodePath = splitCodePaths[i];
- final String resName = getApkName(splitCodePath) + ".zip";
- splitResPaths[i] = new File(new File(splitCodePath).getParentFile(),
- resName).getAbsolutePath();
- }
- }
- return splitResPaths;
}
class PackageInstalledInfo {
@@ -10058,8 +9998,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// which means we are replacing another update that is already
// installed. We need to make sure to delete the older one's .apk.
res.removedInfo.args = createInstallArgsForExisting(0,
- deletedPackage.applicationInfo.sourceDir,
- deletedPackage.applicationInfo.publicSourceDir,
+ deletedPackage.applicationInfo.getCodePath(),
+ deletedPackage.applicationInfo.getResourcePath(),
deletedPackage.applicationInfo.nativeLibraryDir,
getAppInstructionSet(deletedPackage.applicationInfo));
} else {
@@ -10223,7 +10163,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final PackageParser.Package pkg;
try {
- pkg = pp.parseMonolithicPackage(tmpPackageFile, parseFlags);
+ pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParserException e) {
res.returnCode = e.error;
return;
@@ -10341,22 +10281,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return;
}
- if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
+ if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return;
}
- // Set application objects path explicitly after the rename
- // TODO: derive split paths from original scan after rename
- pkg.codePath = args.getCodePath();
- pkg.baseCodePath = args.getCodePath();
- pkg.splitCodePaths = null;
- pkg.applicationInfo.sourceDir = args.getCodePath();
- pkg.applicationInfo.publicSourceDir = args.getResourcePath();
- pkg.applicationInfo.splitSourceDirs = null;
- pkg.applicationInfo.splitPublicSourceDirs = null;
- pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
-
if (replace) {
replacePackageLI(pkg, parseFlags, scanMode, args.user,
installerPackageName, res, args.abiOverride);
@@ -10436,36 +10365,57 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final void deleteTempPackageFilesInDirectory(File directory,
FilenameFilter filter) {
- final String[] tmpFilesList = directory.list(filter);
- if (tmpFilesList == null) {
- return;
- }
- for (int i = 0; i < tmpFilesList.length; i++) {
- final File tmpFile = new File(directory, tmpFilesList[i]);
- tmpFile.delete();
+ final File[] files = directory.listFiles(filter);
+ if (!ArrayUtils.isEmpty(files)) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ FileUtils.deleteContents(file);
+ file.delete();
+ } else if (file.isFile()) {
+ file.delete();
+ }
+ }
}
}
- private File createTempPackageFile(File installDir) {
- File tmpPackageFile;
- try {
- tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir);
- } catch (IOException e) {
- Slog.e(TAG, "Couldn't create temp file for downloaded package file.");
- return null;
- }
- try {
- FileUtils.setPermissions(
- tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR,
- -1, -1);
- if (!SELinux.restorecon(tmpPackageFile)) {
- return null;
+ private File createTempPackageDir(File installDir) throws IOException {
+ int n = 0;
+ while (n++ < 32) {
+ final File file = new File(installDir, "vmdl" + mTempFileRandom.nextInt() + ".tmp");
+ try {
+ Os.mkdir(file.getAbsolutePath(), 0755);
+ Os.chmod(file.getAbsolutePath(), 0755);
+ if (!SELinux.restorecon(file)) {
+ throw new IOException("Failed to restorecon");
+ }
+ return file;
+ } catch (ErrnoException e) {
+ if (e.errno == EEXIST) continue;
+ throw e.rethrowAsIOException();
}
- } catch (IOException e) {
- Slog.e(TAG, "Trouble getting the canoncical path for a temp file.");
- return null;
}
- return tmpPackageFile;
+ throw new IOException("Failed to create temp directory");
+ }
+
+ private File createTempPackageFile(File installDir) throws IOException {
+ int n = 0;
+ while (n++ < 32) {
+ final File file = new File(installDir, "vmdl" + mTempFileRandom.nextInt() + ".tmp");
+ try {
+ final FileDescriptor fd = Os.open(file.getAbsolutePath(),
+ O_RDWR | O_CREAT | O_EXCL, 0644);
+ IoUtils.closeQuietly(fd);
+ Os.chmod(file.getAbsolutePath(), 0644);
+ if (!SELinux.restorecon(file)) {
+ throw new IOException("Failed to restorecon");
+ }
+ return file;
+ } catch (ErrnoException e) {
+ if (e.errno == EEXIST) continue;
+ throw e.rethrowAsIOException();
+ }
+ }
+ throw new IOException("Failed to create temp file");
}
@Override
@@ -11254,7 +11204,7 @@ public class PackageManagerService extends IPackageManager.Stub {
libDirPath = ps.nativeLibraryPathString;
}
if (p != null && (isExternal(p) || isForwardLocked(p))) {
- String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
+ String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath());
if (secureContainerId != null) {
asecPath = PackageHelper.getSdFilesystem(secureContainerId);
}
@@ -11268,7 +11218,7 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
if (isForwardLocked(p)) {
- publicSrcDir = applicationInfo.publicSourceDir;
+ publicSrcDir = applicationInfo.getBaseResourcePath();
}
}
// TODO: extend to measure size of split APKs
@@ -12862,7 +12812,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Message msg = mHandler.obtainMessage(INIT_COPY);
final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
- pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir,
+ pkg.applicationInfo.getCodePath(), pkg.applicationInfo.getResourcePath(),
pkg.applicationInfo.nativeLibraryDir, instructionSet);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
instructionSet, pkg.applicationInfo.uid, user);
@@ -12889,10 +12839,11 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, " Package " + mp.packageName
+ " doesn't exist. Aborting move");
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
- } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) {
+ } else if (!mp.srcArgs.getCodePath().equals(
+ pkg.applicationInfo.getCodePath())) {
Slog.w(TAG, "Package " + mp.packageName + " code path changed from "
+ mp.srcArgs.getCodePath() + " to "
- + pkg.applicationInfo.sourceDir
+ + pkg.applicationInfo.getCodePath()
+ " Aborting move and returning error");
returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
} else {
@@ -12916,10 +12867,10 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " doesn't exist. Aborting move");
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
} else if (!mp.srcArgs.getCodePath().equals(
- pkg.applicationInfo.sourceDir)) {
+ pkg.applicationInfo.getCodePath())) {
Slog.w(TAG, "Package " + mp.packageName
+ " code path changed from " + mp.srcArgs.getCodePath()
- + " to " + pkg.applicationInfo.sourceDir
+ + " to " + pkg.applicationInfo.getCodePath()
+ " Aborting move and returning error");
returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
} else {
@@ -12974,14 +12925,19 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
- pkg.applicationInfo.sourceDir = newCodePath;
- pkg.applicationInfo.publicSourceDir = newResPath;
+ pkg.applicationInfo.setCodePath(newCodePath);
+ pkg.applicationInfo.setBaseCodePath(newCodePath);
+ pkg.applicationInfo.setSplitCodePaths(null);
+ pkg.applicationInfo.setResourcePath(newResPath);
+ pkg.applicationInfo.setBaseResourcePath(newResPath);
+ pkg.applicationInfo.setSplitResourcePaths(null);
pkg.applicationInfo.nativeLibraryDir = newNativePath;
+
PackageSetting ps = (PackageSetting) pkg.mExtras;
- ps.codePath = new File(pkg.applicationInfo.sourceDir);
+ ps.codePath = new File(pkg.applicationInfo.getCodePath());
ps.codePathString = ps.codePath.getPath();
ps.resourcePath = new File(
- pkg.applicationInfo.publicSourceDir);
+ pkg.applicationInfo.getResourcePath());
ps.resourcePathString = ps.resourcePath.getPath();
ps.nativeLibraryPathString = newNativePath;
// Set the application info flag
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index dfc396d33abaa..ff075e39d1e9d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -683,8 +683,8 @@ final class Settings {
p.pkg = pkg;
// pkg.mSetEnabled = p.getEnabled(userId);
// pkg.mSetStopped = p.getStopped(userId);
- final String codePath = pkg.applicationInfo.sourceDir;
- final String resourcePath = pkg.applicationInfo.publicSourceDir;
+ final String codePath = pkg.applicationInfo.getCodePath();
+ final String resourcePath = pkg.applicationInfo.getResourcePath();
// Update code path if needed
if (!codePath.equalsIgnoreCase(p.codePathString)) {
Slog.w(PackageManagerService.TAG, "Code path for pkg : " + p.pkg.packageName +