Merge "Slow progress towards APK clusters."
This commit is contained in:
@@ -413,6 +413,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
/**
|
||||
* Full path to the base APK for this application.
|
||||
*/
|
||||
// TODO: verify that nobody is doing codePath comparisons against this
|
||||
public String sourceDir;
|
||||
|
||||
/**
|
||||
|
||||
@@ -279,11 +279,11 @@ public class PackageParser {
|
||||
mMetrics = metrics;
|
||||
}
|
||||
|
||||
private static final boolean isPackageFilename(File file) {
|
||||
public static final boolean isPackageFilename(File file) {
|
||||
return isPackageFilename(file.getName());
|
||||
}
|
||||
|
||||
private static final boolean isPackageFilename(String name) {
|
||||
public static final boolean isPackageFilename(String name) {
|
||||
return name.endsWith(".apk");
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ public class PackageParser {
|
||||
* Note that this <em>does not</em> perform signature verification; that
|
||||
* must be done separately in {@link #collectCertificates(Package, int)}.
|
||||
*/
|
||||
public Package parseSplitPackage(File apkDir, int flags) throws PackageParserException {
|
||||
public Package parseClusterPackage(File apkDir, int flags) throws PackageParserException {
|
||||
final File[] files = apkDir.listFiles();
|
||||
if (ArrayUtils.isEmpty(files)) {
|
||||
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
|
||||
@@ -600,27 +600,23 @@ public class PackageParser {
|
||||
"Missing base APK in " + apkDir);
|
||||
}
|
||||
|
||||
// Always apply deterministic ordering based on splitName
|
||||
final int size = apks.size();
|
||||
|
||||
final String[] splitNames = apks.keySet().toArray(new String[size]);
|
||||
Arrays.sort(splitNames, sSplitNameComparator);
|
||||
|
||||
final File[] splitFiles = new File[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
splitFiles[i] = apks.get(splitNames[i]);
|
||||
}
|
||||
|
||||
final Package pkg = parseBaseApk(baseFile, flags);
|
||||
if (pkg == null) {
|
||||
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
|
||||
"Failed to parse base APK: " + baseFile);
|
||||
}
|
||||
|
||||
for (File splitFile : splitFiles) {
|
||||
parseSplitApk(pkg, splitFile, flags);
|
||||
// Always apply deterministic ordering based on splitName
|
||||
final int size = apks.size();
|
||||
final String[] splitNames = apks.keySet().toArray(new String[size]);
|
||||
Arrays.sort(splitNames, sSplitNameComparator);
|
||||
|
||||
for (String splitName : splitNames) {
|
||||
final File splitFile = apks.get(splitName);
|
||||
parseSplitApk(pkg, splitFile, splitName, flags);
|
||||
}
|
||||
|
||||
pkg.codePath = apkDir.getAbsolutePath();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
@@ -632,11 +628,12 @@ public class PackageParser {
|
||||
*/
|
||||
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
|
||||
final Package pkg = parseBaseApk(apkFile, flags);
|
||||
if (pkg != null) {
|
||||
return pkg;
|
||||
} else {
|
||||
if (pkg == null) {
|
||||
throw new PackageParserException(mParseError, "Failed to parse " + apkFile);
|
||||
}
|
||||
|
||||
pkg.codePath = apkFile.getAbsolutePath();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
private Package parseBaseApk(File apkFile, int flags) {
|
||||
@@ -723,19 +720,22 @@ public class PackageParser {
|
||||
parser.close();
|
||||
assmgr.close();
|
||||
|
||||
pkg.codePath = apkPath;
|
||||
pkg.baseCodePath = apkPath;
|
||||
pkg.mSignatures = null;
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
private void parseSplitApk(Package pkg, File apkFile, int flags) throws PackageParserException {
|
||||
final String apkPath = apkFile.getAbsolutePath();
|
||||
private void parseSplitApk(Package pkg, File apkFile, String splitName, int flags)
|
||||
throws PackageParserException {
|
||||
final String splitCodePath = apkFile.getAbsolutePath();
|
||||
mArchiveSourcePath = apkFile.getAbsolutePath();
|
||||
|
||||
// TODO: expand split APK parsing
|
||||
// TODO: extract splitName during parse
|
||||
pkg.splitNames = ArrayUtils.appendElement(String.class, pkg.splitNames, splitName);
|
||||
pkg.splitCodePaths = ArrayUtils.appendElement(String.class, pkg.splitCodePaths,
|
||||
apkFile.getAbsolutePath());
|
||||
splitCodePath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -748,7 +748,7 @@ public class PackageParser {
|
||||
|
||||
// TODO: extend to gather digest for split APKs
|
||||
try {
|
||||
final StrictJarFile jarFile = new StrictJarFile(pkg.codePath);
|
||||
final StrictJarFile jarFile = new StrictJarFile(pkg.baseCodePath);
|
||||
try {
|
||||
final ZipEntry je = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
|
||||
if (je != null) {
|
||||
@@ -773,7 +773,7 @@ public class PackageParser {
|
||||
pkg.mSignatures = null;
|
||||
pkg.mSigningKeys = null;
|
||||
|
||||
collectCertificates(pkg, new File(pkg.codePath), flags);
|
||||
collectCertificates(pkg, new File(pkg.baseCodePath), flags);
|
||||
|
||||
if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
|
||||
for (String splitCodePath : pkg.splitCodePaths) {
|
||||
@@ -3692,12 +3692,21 @@ public class PackageParser {
|
||||
public final static class Package {
|
||||
|
||||
public String packageName;
|
||||
/** Names of any split APKs, ordered by parsed splitName */
|
||||
public String[] splitNames;
|
||||
|
||||
// TODO: work towards making these paths invariant
|
||||
|
||||
/** Base APK */
|
||||
/**
|
||||
* Path where this package was found on disk. For monolithic packages
|
||||
* this is path to single base APK file; for cluster packages this is
|
||||
* path to the cluster directory.
|
||||
*/
|
||||
public String codePath;
|
||||
/** Split APKs, ordered by parsed splitName */
|
||||
|
||||
/** Path of base APK */
|
||||
public String baseCodePath;
|
||||
/** Paths of any split APKs, ordered by parsed splitName */
|
||||
public String[] splitCodePaths;
|
||||
|
||||
// For now we only support one application per package.
|
||||
@@ -3816,9 +3825,9 @@ public class PackageParser {
|
||||
applicationInfo.uid = -1;
|
||||
}
|
||||
|
||||
public Collection<String> getAllCodePaths() {
|
||||
public List<String> getAllCodePaths() {
|
||||
ArrayList<String> paths = new ArrayList<>();
|
||||
paths.add(codePath);
|
||||
paths.add(baseCodePath);
|
||||
if (!ArrayUtils.isEmpty(splitCodePaths)) {
|
||||
Collections.addAll(paths, splitCodePaths);
|
||||
}
|
||||
|
||||
@@ -384,16 +384,18 @@ public class FileUtils {
|
||||
return filePath.startsWith(dirPath);
|
||||
}
|
||||
|
||||
public static void deleteContents(File dir) {
|
||||
public static boolean deleteContents(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
boolean success = true;
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteContents(file);
|
||||
success &= deleteContents(file);
|
||||
}
|
||||
file.delete();
|
||||
success &= file.delete();
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,4 +413,23 @@ public class FileUtils {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
|
||||
final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
|
||||
return (result != null) ? result.getAbsolutePath() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (contains(beforeDir, file)) {
|
||||
final String splice = file.getAbsolutePath().substring(
|
||||
beforeDir.getAbsolutePath().length());
|
||||
return new File(afterDir, splice);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,4 +171,23 @@ public class SELinux {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively restores all files under the given path to their default
|
||||
* SELinux security context. If the system is not compiled with SELinux,
|
||||
* then {@code true} is automatically returned. If SELinux is compiled in,
|
||||
* but disabled, then {@code true} is returned.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,25 @@
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.content.pm.ContainerEncryptionParams;
|
||||
import android.content.pm.PackageInfoLite;
|
||||
import android.content.res.ObbInfo;
|
||||
|
||||
interface IMediaContainerService {
|
||||
String copyResourceToContainer(in Uri packageURI, String containerId, String key,
|
||||
String copyResourceToContainer(String packagePath, String containerId, String key,
|
||||
String resFileName, String publicResFileName, boolean isExternal,
|
||||
boolean isForwardLocked, in String abiOverride);
|
||||
int copyResource(in Uri packageURI, in ContainerEncryptionParams encryptionParams,
|
||||
boolean isForwardLocked, String abiOverride);
|
||||
int copyResource(String packagePath, in ContainerEncryptionParams encryptionParams,
|
||||
in ParcelFileDescriptor outStream);
|
||||
PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold,
|
||||
in String abiOverride);
|
||||
boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
|
||||
boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in String abiOverride);
|
||||
ObbInfo getObbInfo(in String filename);
|
||||
long calculateDirectorySize(in String directory);
|
||||
PackageInfoLite getMinimalPackageInfo(String packagePath, int flags, long threshold,
|
||||
String abiOverride);
|
||||
boolean checkInternalFreeStorage(String packagePath, boolean isForwardLocked, long threshold);
|
||||
boolean checkExternalFreeStorage(String packagePath, boolean isForwardLocked, String abiOverride);
|
||||
ObbInfo getObbInfo(String filename);
|
||||
long calculateDirectorySize(String directory);
|
||||
/** Return file system stats: [0] is total bytes, [1] is available bytes */
|
||||
long[] getFileSystemStats(in String path);
|
||||
void clearDirectory(in String directory);
|
||||
long calculateInstalledSize(in String packagePath, boolean isForwardLocked,
|
||||
in String abiOverride);
|
||||
long[] getFileSystemStats(String path);
|
||||
void clearDirectory(String directory);
|
||||
long calculateInstalledSize(String packagePath, boolean isForwardLocked, String abiOverride);
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ public class ArrayUtils
|
||||
* not found.
|
||||
*/
|
||||
public static <T> int indexOf(T[] array, T value) {
|
||||
if (array == null) return -1;
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] == null) {
|
||||
if (value == null) return i;
|
||||
@@ -161,6 +162,7 @@ public class ArrayUtils
|
||||
}
|
||||
|
||||
public static boolean contains(int[] array, int value) {
|
||||
if (array == null) return false;
|
||||
for (int element : array) {
|
||||
if (element == value) {
|
||||
return true;
|
||||
@@ -170,6 +172,7 @@ public class ArrayUtils
|
||||
}
|
||||
|
||||
public static boolean contains(long[] array, long value) {
|
||||
if (array == null) return false;
|
||||
for (long element : array) {
|
||||
if (element == value) {
|
||||
return true;
|
||||
@@ -325,4 +328,8 @@ public class ArrayUtils
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
public static long[] cloneOrNull(long[] array) {
|
||||
return (array != null) ? array.clone() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.content.res.ObbInfo;
|
||||
import android.content.res.ObbScanner;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Environment.UserEnvironment;
|
||||
@@ -45,7 +44,6 @@ import android.provider.Settings;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.StructStatVfs;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.app.IMediaContainerService;
|
||||
@@ -53,6 +51,9 @@ import com.android.internal.content.NativeLibraryHelper;
|
||||
import com.android.internal.content.NativeLibraryHelper.ApkHandle;
|
||||
import com.android.internal.content.PackageHelper;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.io.Streams;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -71,9 +72,6 @@ import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.io.Streams;
|
||||
|
||||
/*
|
||||
* This service copies a downloaded apk to a file passed in as
|
||||
* a ParcelFileDescriptor or to a newly created container specified
|
||||
@@ -101,14 +99,14 @@ public class DefaultContainerService extends IntentService {
|
||||
* @return Returns the new cache path where the resource has been copied into
|
||||
*
|
||||
*/
|
||||
public String copyResourceToContainer(final Uri packageURI, final String cid,
|
||||
@Override
|
||||
public String copyResourceToContainer(final String packagePath, final String cid,
|
||||
final String key, final String resFileName, final String publicResFileName,
|
||||
boolean isExternal, boolean isForwardLocked, String abiOverride) {
|
||||
if (packageURI == null || cid == null) {
|
||||
if (packagePath == null || cid == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (isExternal) {
|
||||
// Make sure the sdcard is mounted.
|
||||
String status = Environment.getExternalStorageState();
|
||||
@@ -120,11 +118,11 @@ public class DefaultContainerService extends IntentService {
|
||||
|
||||
ApkHandle handle = null;
|
||||
try {
|
||||
handle = ApkHandle.create(packageURI.getPath());
|
||||
return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
|
||||
handle = ApkHandle.create(packagePath);
|
||||
return copyResourceInner(packagePath, cid, key, resFileName, publicResFileName,
|
||||
isExternal, isForwardLocked, handle, abiOverride);
|
||||
} catch (IOException ioe) {
|
||||
Slog.w(TAG, "Problem opening APK: " + packageURI.getPath());
|
||||
Slog.w(TAG, "Problem opening APK: " + packagePath);
|
||||
return null;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(handle);
|
||||
@@ -142,9 +140,10 @@ public class DefaultContainerService extends IntentService {
|
||||
* @return returns status code according to those in
|
||||
* {@link PackageManager}
|
||||
*/
|
||||
public int copyResource(final Uri packageURI, ContainerEncryptionParams encryptionParams,
|
||||
ParcelFileDescriptor outStream) {
|
||||
if (packageURI == null || outStream == null) {
|
||||
@Override
|
||||
public int copyResource(final String packagePath,
|
||||
ContainerEncryptionParams encryptionParams, ParcelFileDescriptor outStream) {
|
||||
if (packagePath == null || outStream == null) {
|
||||
return PackageManager.INSTALL_FAILED_INVALID_URI;
|
||||
}
|
||||
|
||||
@@ -152,18 +151,18 @@ public class DefaultContainerService extends IntentService {
|
||||
= new ParcelFileDescriptor.AutoCloseOutputStream(outStream);
|
||||
|
||||
try {
|
||||
copyFile(packageURI, autoOut, encryptionParams);
|
||||
copyFile(packagePath, autoOut, encryptionParams);
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
} catch (FileNotFoundException e) {
|
||||
Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " FNF: "
|
||||
Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " FNF: "
|
||||
+ e.getMessage());
|
||||
return PackageManager.INSTALL_FAILED_INVALID_URI;
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " IO: "
|
||||
Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " IO: "
|
||||
+ e.getMessage());
|
||||
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
} catch (DigestException e) {
|
||||
Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " Security: "
|
||||
Slog.e(TAG, "Could not copy URI " + packagePath.toString() + " Security: "
|
||||
+ e.getMessage());
|
||||
return PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||
} finally {
|
||||
@@ -217,9 +216,9 @@ public class DefaultContainerService extends IntentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInternalFreeStorage(Uri packageUri, boolean isForwardLocked,
|
||||
public boolean checkInternalFreeStorage(String packagePath, boolean isForwardLocked,
|
||||
long threshold) throws RemoteException {
|
||||
final File apkFile = new File(packageUri.getPath());
|
||||
final File apkFile = new File(packagePath);
|
||||
try {
|
||||
return isUnderInternalThreshold(apkFile, isForwardLocked, threshold);
|
||||
} catch (IOException e) {
|
||||
@@ -228,9 +227,9 @@ public class DefaultContainerService extends IntentService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked,
|
||||
public boolean checkExternalFreeStorage(String packagePath, boolean isForwardLocked,
|
||||
String abiOverride) throws RemoteException {
|
||||
final File apkFile = new File(packageUri.getPath());
|
||||
final File apkFile = new File(packagePath);
|
||||
try {
|
||||
return isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
|
||||
} catch (IOException e) {
|
||||
@@ -238,6 +237,7 @@ public class DefaultContainerService extends IntentService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObbInfo getObbInfo(String filename) {
|
||||
try {
|
||||
return ObbScanner.getObbInfo(filename);
|
||||
@@ -347,11 +347,11 @@ public class DefaultContainerService extends IntentService {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
|
||||
private String copyResourceInner(String packagePath, String newCid, String key, String resFileName,
|
||||
String publicResFileName, boolean isExternal, boolean isForwardLocked,
|
||||
ApkHandle handle, String abiOverride) {
|
||||
// The .apk file
|
||||
String codePath = packageURI.getPath();
|
||||
String codePath = packagePath;
|
||||
File codeFile = new File(codePath);
|
||||
|
||||
String[] abiList = Build.SUPPORTED_ABIS;
|
||||
@@ -492,39 +492,13 @@ public class DefaultContainerService extends IntentService {
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFile(Uri pPackageURI, OutputStream outStream,
|
||||
private void copyFile(String packagePath, OutputStream outStream,
|
||||
ContainerEncryptionParams encryptionParams) throws FileNotFoundException, IOException,
|
||||
DigestException {
|
||||
String scheme = pPackageURI.getScheme();
|
||||
InputStream inStream = null;
|
||||
try {
|
||||
if (scheme == null || scheme.equals("file")) {
|
||||
final InputStream is = new FileInputStream(new File(pPackageURI.getPath()));
|
||||
inStream = new BufferedInputStream(is);
|
||||
} else if (scheme.equals("content")) {
|
||||
final ParcelFileDescriptor fd;
|
||||
try {
|
||||
fd = getContentResolver().openFileDescriptor(pPackageURI, "r");
|
||||
} catch (FileNotFoundException e) {
|
||||
Slog.e(TAG, "Couldn't open file descriptor from download service. "
|
||||
+ "Failed with exception " + e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (fd == null) {
|
||||
Slog.e(TAG, "Provider returned no file descriptor for " +
|
||||
pPackageURI.toString());
|
||||
throw new FileNotFoundException("provider returned no file descriptor");
|
||||
} else {
|
||||
if (localLOGV) {
|
||||
Slog.i(TAG, "Opened file descriptor from download service.");
|
||||
}
|
||||
inStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
|
||||
}
|
||||
} else {
|
||||
Slog.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
|
||||
throw new FileNotFoundException("Package URI is not 'file:' or 'content:'");
|
||||
}
|
||||
final InputStream is = new FileInputStream(new File(packagePath));
|
||||
inStream = new BufferedInputStream(is);
|
||||
|
||||
/*
|
||||
* If this resource is encrypted, get the decrypted stream version
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SELinux;
|
||||
import android.os.UserHandle;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.OsConstants;
|
||||
import android.system.StructStat;
|
||||
@@ -272,7 +273,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
};
|
||||
|
||||
mPm.installStage(mPackageName, this.sessionDir, localObserver, params.installFlags);
|
||||
mPm.installStage(mPackageName, this.sessionDir, localObserver, params, installerPackageName,
|
||||
installerUid, new UserHandle(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.server.pm;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,19 +34,17 @@ public class PackageKeySetData {
|
||||
|
||||
private long[] mDefinedKeySets;
|
||||
|
||||
private final Map<String, Long> mKeySetAliases;
|
||||
private final Map<String, Long> mKeySetAliases = new HashMap<String, Long>();
|
||||
|
||||
PackageKeySetData() {
|
||||
mProperSigningKeySet = KEYSET_UNASSIGNED;
|
||||
mKeySetAliases = new HashMap<String, Long>();
|
||||
}
|
||||
|
||||
PackageKeySetData(PackageKeySetData original) {
|
||||
mSigningKeySets = original.getSigningKeySets().clone();
|
||||
mUpgradeKeySets = original.getUpgradeKeySets().clone();
|
||||
mDefinedKeySets = original.getDefinedKeySets().clone();
|
||||
mKeySetAliases = new HashMap<String, Long>();
|
||||
mKeySetAliases.putAll(original.getAliases());
|
||||
mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets);
|
||||
mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets);
|
||||
mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets);
|
||||
mKeySetAliases.putAll(original.mKeySetAliases);
|
||||
}
|
||||
|
||||
protected void setProperSigningKeySet(long ks) {
|
||||
@@ -149,4 +146,4 @@ public class PackageKeySetData {
|
||||
/* should never be the case that mUpgradeKeySets.length == 0 */
|
||||
return (mUpgradeKeySets != null && mUpgradeKeySets.length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|
||||
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
|
||||
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
|
||||
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
|
||||
import static android.content.pm.PackageParser.isPackageFilename;
|
||||
import static android.os.Process.PACKAGE_INFO_GID;
|
||||
import static android.os.Process.SYSTEM_UID;
|
||||
import static android.system.OsConstants.S_IRGRP;
|
||||
@@ -46,6 +47,7 @@ import com.android.internal.content.PackageHelper;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.IntentResolver;
|
||||
@@ -92,6 +94,7 @@ import android.content.pm.ManifestDigest;
|
||||
import android.content.pm.PackageCleanItem;
|
||||
import android.content.pm.PackageInfo;
|
||||
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.PackageParserException;
|
||||
@@ -349,6 +352,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// LOCK HELD. Can be called with mInstallLock held.
|
||||
final Installer mInstaller;
|
||||
|
||||
/** Directory where installed third-party apps stored */
|
||||
final File mAppInstallDir;
|
||||
|
||||
/**
|
||||
@@ -361,6 +365,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// apps.
|
||||
final File mDrmAppPrivateInstallDir;
|
||||
|
||||
/** Directory where third-party apps are staged before install */
|
||||
final File mAppStagingDir;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
@@ -1143,17 +1148,18 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
if ((state != null) && !state.timeoutExtended()) {
|
||||
final InstallArgs args = state.getInstallArgs();
|
||||
Slog.i(TAG, "Verification timed out for " + args.packageURI.toString());
|
||||
final Uri fromUri = Uri.fromFile(args.fromFile);
|
||||
|
||||
Slog.i(TAG, "Verification timed out for " + fromUri);
|
||||
mPendingVerification.remove(verificationId);
|
||||
|
||||
int ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
|
||||
|
||||
if (getDefaultVerificationResponse() == PackageManager.VERIFICATION_ALLOW) {
|
||||
Slog.i(TAG, "Continuing with installation of "
|
||||
+ args.packageURI.toString());
|
||||
Slog.i(TAG, "Continuing with installation of " + fromUri);
|
||||
state.setVerifierResponse(Binder.getCallingUid(),
|
||||
PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
|
||||
broadcastPackageVerified(verificationId, args.packageURI,
|
||||
broadcastPackageVerified(verificationId, fromUri,
|
||||
PackageManager.VERIFICATION_ALLOW,
|
||||
state.getInstallArgs().getUser());
|
||||
try {
|
||||
@@ -1162,7 +1168,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
Slog.e(TAG, "Could not contact the ContainerService");
|
||||
}
|
||||
} else {
|
||||
broadcastPackageVerified(verificationId, args.packageURI,
|
||||
broadcastPackageVerified(verificationId, fromUri,
|
||||
PackageManager.VERIFICATION_REJECT,
|
||||
state.getInstallArgs().getUser());
|
||||
}
|
||||
@@ -1189,11 +1195,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
mPendingVerification.remove(verificationId);
|
||||
|
||||
final InstallArgs args = state.getInstallArgs();
|
||||
final Uri fromUri = Uri.fromFile(args.fromFile);
|
||||
|
||||
int ret;
|
||||
if (state.isInstallAllowed()) {
|
||||
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||
broadcastPackageVerified(verificationId, args.packageURI,
|
||||
broadcastPackageVerified(verificationId, fromUri,
|
||||
response.code, state.getInstallArgs().getUser());
|
||||
try {
|
||||
ret = args.copyApk(mContainerService, true);
|
||||
@@ -1528,14 +1535,14 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// overlay packages if they reside in VENDOR_OVERLAY_DIR.
|
||||
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
|
||||
mVendorOverlayInstallObserver = new AppDirObserver(
|
||||
vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
mVendorOverlayInstallObserver.startWatching();
|
||||
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
|
||||
|
||||
// Find base frameworks (resource packages without code).
|
||||
mFrameworkInstallObserver = new AppDirObserver(
|
||||
frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
mFrameworkInstallObserver.startWatching();
|
||||
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR
|
||||
@@ -1547,14 +1554,14 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
mPrivilegedInstallObserver = new AppDirObserver(
|
||||
privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
|
||||
mPrivilegedInstallObserver.startWatching();
|
||||
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR
|
||||
| PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
|
||||
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR
|
||||
| PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
|
||||
|
||||
// Collect ordinary system packages.
|
||||
File systemAppDir = new File(Environment.getRootDirectory(), "app");
|
||||
mSystemInstallObserver = new AppDirObserver(
|
||||
systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
mSystemInstallObserver.startWatching();
|
||||
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
|
||||
@@ -1567,7 +1574,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// failed to look up canonical path, continue with original one
|
||||
}
|
||||
mVendorInstallObserver = new AppDirObserver(
|
||||
vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
|
||||
mVendorInstallObserver.startWatching();
|
||||
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
|
||||
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
|
||||
@@ -1825,6 +1832,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
void cleanupInstallFailedPackage(PackageSetting ps) {
|
||||
Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
|
||||
removeDataDirsLI(ps.name);
|
||||
|
||||
// TODO: try cleaning up codePath directory contents first, since it
|
||||
// might be a cluster
|
||||
|
||||
if (ps.codePath != null) {
|
||||
if (!ps.codePath.delete()) {
|
||||
Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
|
||||
@@ -2071,15 +2082,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) == 0) {
|
||||
return null;
|
||||
}
|
||||
// App code is gone, so we aren't worried about split paths
|
||||
// Only data remains, so we aren't worried about code paths
|
||||
pkg = new PackageParser.Package(packageName);
|
||||
pkg.applicationInfo.packageName = packageName;
|
||||
pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
|
||||
pkg.applicationInfo.sourceDir = ps.codePathString;
|
||||
pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
|
||||
pkg.applicationInfo.dataDir =
|
||||
getDataPathForPackage(packageName, 0).getPath();
|
||||
pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
|
||||
pkg.applicationInfo.cpuAbi = ps.cpuAbiString;
|
||||
}
|
||||
return generatePackageInfo(pkg, flags, userId);
|
||||
@@ -4041,20 +4049,21 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
|
||||
PackageParser.Package opkg) {
|
||||
if (!opkg.mTrustedOverlay) {
|
||||
Slog.w(TAG, "Skipping target and overlay pair " + pkg.codePath + " and " +
|
||||
opkg.codePath + ": overlay not trusted");
|
||||
Slog.w(TAG, "Skipping target and overlay pair " + pkg.baseCodePath + " and " +
|
||||
opkg.baseCodePath + ": overlay not trusted");
|
||||
return false;
|
||||
}
|
||||
HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
|
||||
if (overlaySet == null) {
|
||||
Slog.e(TAG, "was about to create idmap for " + pkg.codePath + " and " +
|
||||
opkg.codePath + " but target package has no known overlays");
|
||||
Slog.e(TAG, "was about to create idmap for " + pkg.baseCodePath + " and " +
|
||||
opkg.baseCodePath + " but target package has no known overlays");
|
||||
return false;
|
||||
}
|
||||
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
|
||||
// TODO: generate idmap for split APKs
|
||||
if (mInstaller.idmap(pkg.codePath, opkg.codePath, sharedGid) != 0) {
|
||||
Slog.e(TAG, "Failed to generate idmap for " + pkg.codePath + " and " + opkg.codePath);
|
||||
if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid) != 0) {
|
||||
Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and "
|
||||
+ opkg.baseCodePath);
|
||||
return false;
|
||||
}
|
||||
PackageParser.Package[] overlayArray =
|
||||
@@ -4075,8 +4084,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
|
||||
String[] files = dir.list();
|
||||
if (files == null) {
|
||||
final File[] files = dir.listFiles();
|
||||
if (ArrayUtils.isEmpty(files)) {
|
||||
Log.d(TAG, "No files in app dir " + dir);
|
||||
return;
|
||||
}
|
||||
@@ -4086,10 +4095,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
+ " flags=0x" + Integer.toHexString(flags));
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i=0; i<files.length; i++) {
|
||||
File file = new File(dir, files[i]);
|
||||
if (!isPackageFilename(files[i])) {
|
||||
for (File file : files) {
|
||||
if (!isPackageFilename(file)) {
|
||||
// Ignore entries which are not apk's
|
||||
continue;
|
||||
}
|
||||
@@ -4258,7 +4265,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
+ ": new version " + pkg.mVersionCode
|
||||
+ " better than installed " + ps.versionCode);
|
||||
|
||||
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
|
||||
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
|
||||
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
|
||||
getAppInstructionSetFromSettings(ps));
|
||||
synchronized (mInstallLock) {
|
||||
@@ -4323,7 +4330,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
|
||||
+ ps.codePathString + ": new version " + pkg.mVersionCode
|
||||
+ " better than installed " + ps.versionCode);
|
||||
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
|
||||
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
|
||||
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
|
||||
getAppInstructionSetFromSettings(ps));
|
||||
synchronized (mInstallLock) {
|
||||
@@ -4343,29 +4350,27 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
final String codePath = pkg.codePath;
|
||||
final String baseCodePath = pkg.baseCodePath;
|
||||
final String[] splitCodePaths = pkg.splitCodePaths;
|
||||
|
||||
String resPath = null;
|
||||
String[] splitResPaths = null;
|
||||
// TODO: extend to support forward-locked splits
|
||||
String baseResPath = null;
|
||||
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
|
||||
if (ps != null && ps.resourcePathString != null) {
|
||||
resPath = ps.resourcePathString;
|
||||
splitResPaths = deriveSplitResPaths(pkg.splitCodePaths);
|
||||
baseResPath = ps.resourcePathString;
|
||||
} else {
|
||||
// Should not happen at all. Just log an error.
|
||||
Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName);
|
||||
}
|
||||
} else {
|
||||
resPath = pkg.codePath;
|
||||
splitResPaths = pkg.splitCodePaths;
|
||||
baseResPath = pkg.baseCodePath;
|
||||
}
|
||||
|
||||
// Set application objects path explicitly.
|
||||
pkg.applicationInfo.sourceDir = codePath;
|
||||
pkg.applicationInfo.publicSourceDir = resPath;
|
||||
pkg.applicationInfo.sourceDir = baseCodePath;
|
||||
pkg.applicationInfo.publicSourceDir = baseResPath;
|
||||
pkg.applicationInfo.splitSourceDirs = splitCodePaths;
|
||||
pkg.applicationInfo.splitPublicSourceDirs = splitResPaths;
|
||||
pkg.applicationInfo.splitPublicSourceDirs = splitCodePaths;
|
||||
|
||||
// Note that we invoke the following method only if we are about to unpack an application
|
||||
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
|
||||
@@ -6419,10 +6424,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean isPackageFilename(String name) {
|
||||
return name != null && name.endsWith(".apk");
|
||||
}
|
||||
|
||||
private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) {
|
||||
for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
|
||||
if (pkgInfo.permissions.get(i).info.name.equals(perm)) {
|
||||
@@ -7701,8 +7702,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
verificationParams.setInstallerUid(uid);
|
||||
|
||||
if (!"file".equals(packageURI.getScheme())) {
|
||||
throw new UnsupportedOperationException("Only file:// URIs are supported");
|
||||
}
|
||||
final File fromFile = new File(packageURI.getPath());
|
||||
|
||||
final Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||
msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
|
||||
msg.obj = new InstallParams(fromFile, observer, observer2, filteredFlags,
|
||||
installerPackageName, verificationParams, encryptionParams, user,
|
||||
packageAbiOverride);
|
||||
mHandler.sendMessage(msg);
|
||||
@@ -7820,11 +7826,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
void installStage(String basePackageName, File stageDir, IPackageInstallObserver2 observer,
|
||||
int flags) {
|
||||
// TODO: install stage!
|
||||
void installStage(String packageName, File stageDir, IPackageInstallObserver2 observer2,
|
||||
PackageInstallerParams params, String installerPackageName, int installerUid,
|
||||
UserHandle user) {
|
||||
Slog.e(TAG, "TODO: install stage!");
|
||||
try {
|
||||
observer.packageInstalled(basePackageName, null,
|
||||
observer2.packageInstalled(packageName, null,
|
||||
PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
@@ -8407,30 +8414,38 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
class InstallParams extends HandlerParams {
|
||||
/**
|
||||
* Location where install is coming from, before it has been
|
||||
* copied/renamed into place. This could be a single monolithic APK
|
||||
* file, or a cluster directory. This location may be untrusted.
|
||||
*/
|
||||
private final File mFromFile;
|
||||
|
||||
/**
|
||||
* Local copy of {@link #mFromFile}, if generated.
|
||||
*/
|
||||
private File mLocalFromFile;
|
||||
|
||||
final IPackageInstallObserver observer;
|
||||
final IPackageInstallObserver2 observer2;
|
||||
int flags;
|
||||
|
||||
private final Uri mPackageURI;
|
||||
final String installerPackageName;
|
||||
final VerificationParams verificationParams;
|
||||
private InstallArgs mArgs;
|
||||
private int mRet;
|
||||
private File mTempPackage;
|
||||
final ContainerEncryptionParams encryptionParams;
|
||||
final String packageAbiOverride;
|
||||
final String packageInstructionSetOverride;
|
||||
|
||||
InstallParams(Uri packageURI,
|
||||
IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
|
||||
int flags, String installerPackageName, VerificationParams verificationParams,
|
||||
ContainerEncryptionParams encryptionParams, UserHandle user,
|
||||
String packageAbiOverride) {
|
||||
InstallParams(File fromFile, IPackageInstallObserver observer,
|
||||
IPackageInstallObserver2 observer2, int flags, String installerPackageName,
|
||||
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
|
||||
UserHandle user, String packageAbiOverride) {
|
||||
super(user);
|
||||
this.mPackageURI = packageURI;
|
||||
this.flags = flags;
|
||||
mFromFile = Preconditions.checkNotNull(fromFile);
|
||||
this.observer = observer;
|
||||
this.observer2 = observer2;
|
||||
this.flags = flags;
|
||||
this.installerPackageName = installerPackageName;
|
||||
this.verificationParams = verificationParams;
|
||||
this.encryptionParams = encryptionParams;
|
||||
@@ -8443,7 +8458,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
public String toString() {
|
||||
return "InstallParams{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + mPackageURI + "}";
|
||||
+ " " + mFromFile + "}";
|
||||
}
|
||||
|
||||
public ManifestDigest getManifestDigest() {
|
||||
@@ -8543,76 +8558,55 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
Log.w(TAG, "Couldn't get low memory threshold; no free limit imposed");
|
||||
}
|
||||
|
||||
try {
|
||||
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
final File packageFile;
|
||||
if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
|
||||
mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
|
||||
if (mTempPackage != null) {
|
||||
ParcelFileDescriptor out;
|
||||
try {
|
||||
out = ParcelFileDescriptor.open(mTempPackage,
|
||||
ParcelFileDescriptor.MODE_READ_WRITE);
|
||||
} catch (FileNotFoundException e) {
|
||||
out = null;
|
||||
Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
|
||||
}
|
||||
|
||||
// Make a temporary file for decryption.
|
||||
ret = mContainerService
|
||||
.copyResource(mPackageURI, encryptionParams, out);
|
||||
if (encryptionParams != null) {
|
||||
// Make a temporary file for decryption.
|
||||
mLocalFromFile = createTempPackageFile(mDrmAppPrivateInstallDir);
|
||||
if (mLocalFromFile != null) {
|
||||
ParcelFileDescriptor out = null;
|
||||
try {
|
||||
out = ParcelFileDescriptor.open(mLocalFromFile,
|
||||
ParcelFileDescriptor.MODE_READ_WRITE);
|
||||
ret = mContainerService.copyResource(mFromFile.getAbsolutePath(),
|
||||
encryptionParams, out);
|
||||
} catch (FileNotFoundException e) {
|
||||
Slog.e(TAG, "Failed to create temporary file for: " + mFromFile);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(out);
|
||||
|
||||
packageFile = mTempPackage;
|
||||
|
||||
FileUtils.setPermissions(packageFile.getAbsolutePath(),
|
||||
FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP
|
||||
| FileUtils.S_IROTH,
|
||||
-1, -1);
|
||||
} else {
|
||||
packageFile = null;
|
||||
}
|
||||
} else {
|
||||
packageFile = new File(mPackageURI.getPath());
|
||||
}
|
||||
|
||||
if (packageFile != null) {
|
||||
// Remote call to find out default install location
|
||||
final String packageFilePath = packageFile.getAbsolutePath();
|
||||
pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
|
||||
lowThreshold, packageAbiOverride);
|
||||
|
||||
/*
|
||||
* If we have too little free space, try to free cache
|
||||
* before giving up.
|
||||
*/
|
||||
if (pkgLite.recommendedInstallLocation
|
||||
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
|
||||
final long size = mContainerService.calculateInstalledSize(
|
||||
packageFilePath, isForwardLocked(), packageAbiOverride);
|
||||
if (mInstaller.freeCache(size + lowThreshold) >= 0) {
|
||||
pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
|
||||
flags, lowThreshold, packageAbiOverride);
|
||||
}
|
||||
/*
|
||||
* The cache free must have deleted the file we
|
||||
* downloaded to install.
|
||||
*
|
||||
* TODO: fix the "freeCache" call to not delete
|
||||
* the file we care about.
|
||||
*/
|
||||
if (pkgLite.recommendedInstallLocation
|
||||
== PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
|
||||
pkgLite.recommendedInstallLocation
|
||||
= PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
}
|
||||
FileUtils.setPermissions(mLocalFromFile, 0644, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// Remote call to find out default install location
|
||||
final String fromPath = getFromFile().getAbsolutePath();
|
||||
pkgLite = mContainerService.getMinimalPackageInfo(fromPath, flags, lowThreshold,
|
||||
packageAbiOverride);
|
||||
|
||||
/*
|
||||
* If we have too little free space, try to free cache
|
||||
* before giving up.
|
||||
*/
|
||||
if (pkgLite.recommendedInstallLocation
|
||||
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
|
||||
final long size = mContainerService.calculateInstalledSize(
|
||||
fromPath, isForwardLocked(), packageAbiOverride);
|
||||
if (mInstaller.freeCache(size + lowThreshold) >= 0) {
|
||||
pkgLite = mContainerService.getMinimalPackageInfo(fromPath,
|
||||
flags, lowThreshold, packageAbiOverride);
|
||||
}
|
||||
/*
|
||||
* The cache free must have deleted the file we
|
||||
* downloaded to install.
|
||||
*
|
||||
* TODO: fix the "freeCache" call to not delete
|
||||
* the file we care about.
|
||||
*/
|
||||
if (pkgLite.recommendedInstallLocation
|
||||
== PackageHelper.RECOMMEND_FAILED_INVALID_URI) {
|
||||
pkgLite.recommendedInstallLocation
|
||||
= PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
} finally {
|
||||
mContext.revokeUriPermission(mPackageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8672,9 +8666,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final int requiredUid = mRequiredVerifierPackage == null ? -1
|
||||
: getPackageUid(mRequiredVerifierPackage, userIdentifier);
|
||||
if (requiredUid != -1 && isVerificationEnabled(userIdentifier, flags)) {
|
||||
// TODO: send verifier the install session instead of uri
|
||||
final Intent verification = new Intent(
|
||||
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
|
||||
verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
|
||||
verification.setDataAndType(Uri.fromFile(getFromFile()), PACKAGE_MIME_TYPE);
|
||||
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
|
||||
@@ -8802,10 +8797,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (mArgs != null) {
|
||||
processPendingInstall(mArgs, mRet);
|
||||
|
||||
if (mTempPackage != null) {
|
||||
if (!mTempPackage.delete()) {
|
||||
Slog.w(TAG, "Couldn't delete temporary file: " +
|
||||
mTempPackage.getAbsolutePath());
|
||||
if (mLocalFromFile != null) {
|
||||
if (!mLocalFromFile.delete()) {
|
||||
Slog.w(TAG, "Couldn't delete temporary file: " + mLocalFromFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8821,11 +8815,11 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
|
||||
}
|
||||
|
||||
public Uri getPackageUri() {
|
||||
if (mTempPackage != null) {
|
||||
return Uri.fromFile(mTempPackage);
|
||||
public File getFromFile() {
|
||||
if (mLocalFromFile != null) {
|
||||
return mLocalFromFile;
|
||||
} else {
|
||||
return mPackageURI;
|
||||
return mFromFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8856,8 +8850,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
this.packageName = packageName;
|
||||
this.uid = uid;
|
||||
if (srcArgs != null) {
|
||||
Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
|
||||
targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet);
|
||||
final String codePath = srcArgs.getCodePath();
|
||||
targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName, dataDir,
|
||||
instructionSet);
|
||||
} else {
|
||||
targetArgs = null;
|
||||
}
|
||||
@@ -8958,6 +8953,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
private InstallArgs createInstallArgs(InstallParams params) {
|
||||
// TODO: extend to support incoming zero-copy locations
|
||||
|
||||
if (installOnSd(params.flags) || params.isForwardLocked()) {
|
||||
return new AsecInstallArgs(params);
|
||||
} else {
|
||||
@@ -8965,14 +8962,18 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
|
||||
String nativeLibraryPath, String instructionSet) {
|
||||
/**
|
||||
* Create args that describe an existing installed package. Typically used
|
||||
* when cleaning up old installs, or used as a move source.
|
||||
*/
|
||||
private InstallArgs createInstallArgsForExisting(int flags, String codePath,
|
||||
String resourcePath, String nativeLibraryPath, String instructionSet) {
|
||||
final boolean isInAsec;
|
||||
if (installOnSd(flags)) {
|
||||
/* Apps on SD card are always in ASEC containers. */
|
||||
isInAsec = true;
|
||||
} else if (installForwardLocked(flags)
|
||||
&& !fullCodePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
|
||||
&& !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
|
||||
/*
|
||||
* Forward-locked apps are only in ASEC containers if they're the
|
||||
* new style
|
||||
@@ -8983,44 +8984,49 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
if (isInAsec) {
|
||||
return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
|
||||
return new AsecInstallArgs(codePath, resourcePath, nativeLibraryPath,
|
||||
instructionSet, installOnSd(flags), installForwardLocked(flags));
|
||||
} else {
|
||||
return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
|
||||
instructionSet);
|
||||
return new FileInstallArgs(codePath, resourcePath, nativeLibraryPath, instructionSet);
|
||||
}
|
||||
}
|
||||
|
||||
// Used by package mover
|
||||
private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir,
|
||||
String instructionSet) {
|
||||
private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName,
|
||||
String dataDir, String instructionSet) {
|
||||
final File codeFile = new File(codePath);
|
||||
if (installOnSd(flags) || installForwardLocked(flags)) {
|
||||
String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
|
||||
String cid = getNextCodePath(codePath, pkgName, "/"
|
||||
+ AsecInstallArgs.RES_FILE_NAME);
|
||||
return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags),
|
||||
return new AsecInstallArgs(codeFile, cid, instructionSet, installOnSd(flags),
|
||||
installForwardLocked(flags));
|
||||
} else {
|
||||
return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet);
|
||||
return new FileInstallArgs(codeFile, pkgName, dataDir, instructionSet);
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class InstallArgs {
|
||||
/**
|
||||
* Location where install is coming from, before it has been
|
||||
* copied/renamed into place. This could be a single monolithic APK
|
||||
* file, or a cluster directory. This location is typically untrusted.
|
||||
*/
|
||||
final File fromFile;
|
||||
|
||||
final IPackageInstallObserver observer;
|
||||
final IPackageInstallObserver2 observer2;
|
||||
// Always refers to PackageManager flags only
|
||||
final int flags;
|
||||
final Uri packageURI;
|
||||
final String installerPackageName;
|
||||
final ManifestDigest manifestDigest;
|
||||
final UserHandle user;
|
||||
final String instructionSet;
|
||||
final String abiOverride;
|
||||
|
||||
InstallArgs(Uri packageURI,
|
||||
IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
|
||||
int flags, String installerPackageName, ManifestDigest manifestDigest,
|
||||
UserHandle user, String instructionSet, String abiOverride) {
|
||||
this.packageURI = packageURI;
|
||||
InstallArgs(File fromFile, IPackageInstallObserver observer,
|
||||
IPackageInstallObserver2 observer2, int flags, String installerPackageName,
|
||||
ManifestDigest manifestDigest, UserHandle user, String instructionSet,
|
||||
String abiOverride) {
|
||||
this.fromFile = fromFile;
|
||||
this.flags = flags;
|
||||
this.observer = observer;
|
||||
this.observer2 = observer2;
|
||||
@@ -9031,24 +9037,23 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
this.abiOverride = abiOverride;
|
||||
}
|
||||
|
||||
abstract void createCopyFile();
|
||||
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
|
||||
abstract int doPreInstall(int status);
|
||||
abstract boolean doRename(int status, String pkgName, String oldCodePath);
|
||||
|
||||
abstract int doPostInstall(int status, int uid);
|
||||
|
||||
/** @see PackageSettingBase#codePathString */
|
||||
abstract String getCodePath();
|
||||
/** @see PackageSettingBase#resourcePathString */
|
||||
abstract String getResourcePath();
|
||||
/** @see PackageSettingBase#nativeLibraryPathString */
|
||||
abstract String getNativeLibraryPath();
|
||||
|
||||
// Need installer lock especially for dex file removal.
|
||||
abstract void cleanUpResourcesLI();
|
||||
abstract boolean doPostDeleteLI(boolean delete);
|
||||
abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
|
||||
|
||||
String[] getSplitCodePaths() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the source arguments are copied. This is used mostly
|
||||
* for MoveParams when it needs to read the source file to put it in the
|
||||
@@ -9078,20 +9083,27 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic to handle installation of non-ASEC applications, including copying
|
||||
* and renaming logic.
|
||||
*/
|
||||
class FileInstallArgs extends InstallArgs {
|
||||
// TODO: teach about handling cluster directories
|
||||
|
||||
File installDir;
|
||||
String codeFileName;
|
||||
String resourceFileName;
|
||||
String libraryPath;
|
||||
boolean created = false;
|
||||
|
||||
/** New install */
|
||||
FileInstallArgs(InstallParams params) {
|
||||
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
|
||||
params.installerPackageName, params.getManifestDigest(),
|
||||
params.getUser(), params.packageInstructionSetOverride,
|
||||
params.packageAbiOverride);
|
||||
super(params.getFromFile(), params.observer, params.observer2, params.flags,
|
||||
params.installerPackageName, params.getManifestDigest(), params.getUser(),
|
||||
params.packageInstructionSetOverride, params.packageAbiOverride);
|
||||
}
|
||||
|
||||
/** Existing install */
|
||||
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
|
||||
String instructionSet) {
|
||||
super(null, null, null, 0, null, null, null, instructionSet, null);
|
||||
@@ -9102,8 +9114,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
libraryPath = nativeLibraryPath;
|
||||
}
|
||||
|
||||
FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
|
||||
super(packageURI, null, null, 0, null, null, null, instructionSet, null);
|
||||
/** New install from existing */
|
||||
FileInstallArgs(File fromFile, String pkgName, String dataDir, String instructionSet) {
|
||||
super(fromFile, 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();
|
||||
@@ -9128,13 +9141,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
lowThreshold = dsm.getMemoryLowThreshold();
|
||||
}
|
||||
|
||||
try {
|
||||
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
|
||||
} finally {
|
||||
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
return imcs.checkInternalFreeStorage(fromFile.getAbsolutePath(), isFwdLocked(),
|
||||
lowThreshold);
|
||||
}
|
||||
|
||||
void createCopyFile() {
|
||||
@@ -9175,12 +9183,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// Copy the resource now
|
||||
int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
try {
|
||||
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
ret = imcs.copyResource(packageURI, null, out);
|
||||
ret = imcs.copyResource(fromFile.getAbsolutePath(), null, out);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(out);
|
||||
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
|
||||
if (isFwdLocked()) {
|
||||
@@ -9432,7 +9437,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return subStr1.substring(sidx+1, eidx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic to handle installation of ASEC applications, including copying and
|
||||
* renaming logic.
|
||||
*/
|
||||
class AsecInstallArgs extends InstallArgs {
|
||||
// TODO: teach about handling cluster directories
|
||||
|
||||
static final String RES_FILE_NAME = "pkg.apk";
|
||||
static final String PUBLIC_RES_FILE_NAME = "res.zip";
|
||||
|
||||
@@ -9441,13 +9452,14 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
String resourcePath;
|
||||
String libraryPath;
|
||||
|
||||
/** New install */
|
||||
AsecInstallArgs(InstallParams params) {
|
||||
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
|
||||
params.installerPackageName, params.getManifestDigest(),
|
||||
params.getUser(), params.packageInstructionSetOverride,
|
||||
params.packageAbiOverride);
|
||||
super(params.getFromFile(), params.observer, params.observer2, params.flags,
|
||||
params.installerPackageName, params.getManifestDigest(), params.getUser(),
|
||||
params.packageInstructionSetOverride, params.packageAbiOverride);
|
||||
}
|
||||
|
||||
/** Existing install */
|
||||
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
|
||||
String instructionSet, boolean isExternal, boolean isForwardLocked) {
|
||||
super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
|
||||
@@ -9469,9 +9481,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
setCachePath(PackageHelper.getSdDir(cid));
|
||||
}
|
||||
|
||||
AsecInstallArgs(Uri packageURI, String cid, String instructionSet,
|
||||
/** New install from existing */
|
||||
AsecInstallArgs(File fromFile, String cid, String instructionSet,
|
||||
boolean isExternal, boolean isForwardLocked) {
|
||||
super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
|
||||
super(fromFile, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
|
||||
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
|
||||
null, null, null, instructionSet, null);
|
||||
this.cid = cid;
|
||||
@@ -9482,13 +9495,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
|
||||
try {
|
||||
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
return imcs.checkExternalFreeStorage(packageURI, isFwdLocked(), abiOverride);
|
||||
} finally {
|
||||
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
return imcs.checkExternalFreeStorage(fromFile.getAbsolutePath(), isFwdLocked(),
|
||||
abiOverride);
|
||||
}
|
||||
|
||||
private final boolean isExternal() {
|
||||
@@ -9506,16 +9514,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
PackageHelper.destroySdDir(cid);
|
||||
}
|
||||
|
||||
final String newCachePath;
|
||||
try {
|
||||
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
|
||||
RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked(),
|
||||
abiOverride);
|
||||
} finally {
|
||||
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
final String newCachePath = imcs.copyResourceToContainer(fromFile.getAbsolutePath(),
|
||||
cid, getEncryptKey(), RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(),
|
||||
isFwdLocked(), abiOverride);
|
||||
|
||||
if (newCachePath != null) {
|
||||
setCachePath(newCachePath);
|
||||
@@ -10078,7 +10079,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// We didn't need to disable the .apk as a current system package,
|
||||
// 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 = createInstallArgs(0,
|
||||
res.removedInfo.args = createInstallArgsForExisting(0,
|
||||
deletedPackage.applicationInfo.sourceDir,
|
||||
deletedPackage.applicationInfo.publicSourceDir,
|
||||
deletedPackage.applicationInfo.nativeLibraryDir,
|
||||
@@ -10143,7 +10144,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// TODO: extend to move split APK dex files
|
||||
if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
|
||||
final String instructionSet = getAppInstructionSet(newPackage.applicationInfo);
|
||||
int retCode = mInstaller.movedex(oldCodePath, newPackage.codePath,
|
||||
int retCode = mInstaller.movedex(oldCodePath, newPackage.baseCodePath,
|
||||
instructionSet);
|
||||
if (retCode != 0) {
|
||||
/*
|
||||
@@ -10156,7 +10157,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
*/
|
||||
newPackage.mDexOptNeeded = true;
|
||||
mInstaller.rmdex(oldCodePath, instructionSet);
|
||||
mInstaller.rmdex(newPackage.codePath, instructionSet);
|
||||
mInstaller.rmdex(newPackage.baseCodePath, instructionSet);
|
||||
}
|
||||
}
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
@@ -10221,8 +10222,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void installPackageLI(InstallArgs args,
|
||||
boolean newInstall, PackageInstalledInfo res) {
|
||||
private void installPackageLI(InstallArgs args, boolean newInstall, PackageInstalledInfo res) {
|
||||
int pFlags = args.flags;
|
||||
String installerPackageName = args.installerPackageName;
|
||||
File tmpPackageFile = new File(args.getCodePath());
|
||||
@@ -10367,14 +10367,18 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
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 = args.getSplitCodePaths();
|
||||
pkg.applicationInfo.splitPublicSourceDirs = deriveSplitResPaths(
|
||||
pkg.applicationInfo.splitSourceDirs);
|
||||
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);
|
||||
@@ -10847,8 +10851,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
// Delete application code and resources
|
||||
if (deleteCodeAndResources && (outInfo != null)) {
|
||||
outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
|
||||
ps.resourcePathString, ps.nativeLibraryPathString,
|
||||
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
|
||||
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
|
||||
getAppInstructionSetFromSettings(ps));
|
||||
}
|
||||
return true;
|
||||
@@ -11253,7 +11257,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
publicSrcDir = applicationInfo.publicSourceDir;
|
||||
}
|
||||
}
|
||||
int res = mInstaller.getSizeInfo(packageName, userHandle, p.codePath, libDirPath,
|
||||
// TODO: extend to measure size of split APKs
|
||||
int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirPath,
|
||||
publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps),
|
||||
pStats);
|
||||
if (res < 0) {
|
||||
@@ -12843,9 +12848,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
} else {
|
||||
Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||
final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
|
||||
InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
|
||||
pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir,
|
||||
instructionSet);
|
||||
InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
|
||||
pkg.applicationInfo.sourceDir, pkg.applicationInfo.publicSourceDir,
|
||||
pkg.applicationInfo.nativeLibraryDir, instructionSet);
|
||||
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
|
||||
pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user);
|
||||
msg.obj = mp;
|
||||
@@ -12943,11 +12948,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
|
||||
pkg.codePath = newCodePath;
|
||||
pkg.baseCodePath = newCodePath;
|
||||
// Move dex files around
|
||||
if (moveDexFilesLI(oldCodePath, pkg) != PackageManager.INSTALL_SUCCEEDED) {
|
||||
// Moving of dex files failed. Set
|
||||
// error code and abort move.
|
||||
pkg.codePath = oldCodePath;
|
||||
pkg.baseCodePath = oldCodePath;
|
||||
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
|
||||
final String name;
|
||||
final String realName;
|
||||
|
||||
/**
|
||||
* Path where this package was found on disk. For monolithic packages
|
||||
* this is path to single base APK file; for cluster packages this is
|
||||
* path to the cluster directory.
|
||||
*/
|
||||
File codePath;
|
||||
String codePathString;
|
||||
File resourcePath;
|
||||
|
||||
Reference in New Issue
Block a user