Merge "Allow native shared libraries in ASEC containers" into gingerbread
This commit is contained in:
@ -3181,6 +3181,7 @@ public final class ActivityThread {
|
|||||||
instrApp.sourceDir = ii.sourceDir;
|
instrApp.sourceDir = ii.sourceDir;
|
||||||
instrApp.publicSourceDir = ii.publicSourceDir;
|
instrApp.publicSourceDir = ii.publicSourceDir;
|
||||||
instrApp.dataDir = ii.dataDir;
|
instrApp.dataDir = ii.dataDir;
|
||||||
|
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
|
||||||
LoadedApk pi = getPackageInfo(instrApp,
|
LoadedApk pi = getPackageInfo(instrApp,
|
||||||
appContext.getClassLoader(), false, true);
|
appContext.getClassLoader(), false, true);
|
||||||
ContextImpl instrContext = new ContextImpl();
|
ContextImpl instrContext = new ContextImpl();
|
||||||
|
@ -19,6 +19,7 @@ package android.app;
|
|||||||
import dalvik.system.PathClassLoader;
|
import dalvik.system.PathClassLoader;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
class ApplicationLoaders
|
class ApplicationLoaders
|
||||||
{
|
{
|
||||||
@ -27,8 +28,7 @@ class ApplicationLoaders
|
|||||||
return gApplicationLoaders;
|
return gApplicationLoaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassLoader getClassLoader(String zip, String appDataDir,
|
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
|
||||||
ClassLoader parent)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This is the parent we use if they pass "null" in. In theory
|
* This is the parent we use if they pass "null" in. In theory
|
||||||
@ -49,13 +49,13 @@ class ApplicationLoaders
|
|||||||
* new ClassLoader for the zip archive.
|
* new ClassLoader for the zip archive.
|
||||||
*/
|
*/
|
||||||
if (parent == baseParent) {
|
if (parent == baseParent) {
|
||||||
ClassLoader loader = (ClassLoader)mLoaders.get(zip);
|
ClassLoader loader = mLoaders.get(zip);
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
PathClassLoader pathClassloader =
|
PathClassLoader pathClassloader =
|
||||||
new PathClassLoader(zip, appDataDir + "/lib", parent);
|
new PathClassLoader(zip, libPath, parent);
|
||||||
|
|
||||||
mLoaders.put(zip, pathClassloader);
|
mLoaders.put(zip, pathClassloader);
|
||||||
return pathClassloader;
|
return pathClassloader;
|
||||||
@ -65,7 +65,7 @@ class ApplicationLoaders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final HashMap mLoaders = new HashMap();
|
private final Map<String, ClassLoader> mLoaders = new HashMap<String, ClassLoader>();
|
||||||
|
|
||||||
private static final ApplicationLoaders gApplicationLoaders
|
private static final ApplicationLoaders gApplicationLoaders
|
||||||
= new ApplicationLoaders();
|
= new ApplicationLoaders();
|
||||||
|
@ -72,6 +72,7 @@ final class LoadedApk {
|
|||||||
private final String mResDir;
|
private final String mResDir;
|
||||||
private final String[] mSharedLibraries;
|
private final String[] mSharedLibraries;
|
||||||
private final String mDataDir;
|
private final String mDataDir;
|
||||||
|
private final String mLibDir;
|
||||||
private final File mDataDirFile;
|
private final File mDataDirFile;
|
||||||
private final ClassLoader mBaseClassLoader;
|
private final ClassLoader mBaseClassLoader;
|
||||||
private final boolean mSecurityViolation;
|
private final boolean mSecurityViolation;
|
||||||
@ -108,6 +109,7 @@ final class LoadedApk {
|
|||||||
mSharedLibraries = aInfo.sharedLibraryFiles;
|
mSharedLibraries = aInfo.sharedLibraryFiles;
|
||||||
mDataDir = aInfo.dataDir;
|
mDataDir = aInfo.dataDir;
|
||||||
mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
|
mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
|
||||||
|
mLibDir = aInfo.nativeLibraryDir;
|
||||||
mBaseClassLoader = baseLoader;
|
mBaseClassLoader = baseLoader;
|
||||||
mSecurityViolation = securityViolation;
|
mSecurityViolation = securityViolation;
|
||||||
mIncludeCode = includeCode;
|
mIncludeCode = includeCode;
|
||||||
@ -140,6 +142,7 @@ final class LoadedApk {
|
|||||||
mSharedLibraries = null;
|
mSharedLibraries = null;
|
||||||
mDataDir = null;
|
mDataDir = null;
|
||||||
mDataDirFile = null;
|
mDataDirFile = null;
|
||||||
|
mLibDir = null;
|
||||||
mBaseClassLoader = null;
|
mBaseClassLoader = null;
|
||||||
mSecurityViolation = false;
|
mSecurityViolation = false;
|
||||||
mIncludeCode = true;
|
mIncludeCode = true;
|
||||||
@ -279,11 +282,12 @@ final class LoadedApk {
|
|||||||
* create the class loader.
|
* create the class loader.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ActivityThread.localLOGV) Slog.v(ActivityThread.TAG, "Class path: " + zip);
|
if (ActivityThread.localLOGV)
|
||||||
|
Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + mLibDir);
|
||||||
|
|
||||||
mClassLoader =
|
mClassLoader =
|
||||||
ApplicationLoaders.getDefault().getClassLoader(
|
ApplicationLoaders.getDefault().getClassLoader(
|
||||||
zip, mDataDir, mBaseClassLoader);
|
zip, mLibDir, mBaseClassLoader);
|
||||||
initializeJavaContextClassLoader();
|
initializeJavaContextClassLoader();
|
||||||
} else {
|
} else {
|
||||||
if (mBaseClassLoader == null) {
|
if (mBaseClassLoader == null) {
|
||||||
|
@ -290,14 +290,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int FLAG_FORWARD_LOCK = 1<<29;
|
public static final int FLAG_FORWARD_LOCK = 1<<29;
|
||||||
|
|
||||||
/**
|
|
||||||
* Value for {@link #flags}: Set to true if the application is
|
|
||||||
* native-debuggable, i.e. embeds a gdbserver binary in its .apk
|
|
||||||
*
|
|
||||||
* {@hide}
|
|
||||||
*/
|
|
||||||
public static final int FLAG_NATIVE_DEBUGGABLE = 1<<28;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value for {@link #flags}: set to <code>true</code> if the application
|
* Value for {@link #flags}: set to <code>true</code> if the application
|
||||||
* has reported that it is heavy-weight, and thus can not participate in
|
* has reported that it is heavy-weight, and thus can not participate in
|
||||||
@ -360,6 +352,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public String dataDir;
|
public String dataDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full path to the directory where native JNI libraries are stored.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public String nativeLibraryDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The kernel user-ID that has been assigned to this application;
|
* The kernel user-ID that has been assigned to this application;
|
||||||
* currently this is not a unique ID (multiple applications can have
|
* currently this is not a unique ID (multiple applications can have
|
||||||
@ -452,6 +451,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
flags = orig.flags;
|
flags = orig.flags;
|
||||||
sourceDir = orig.sourceDir;
|
sourceDir = orig.sourceDir;
|
||||||
publicSourceDir = orig.publicSourceDir;
|
publicSourceDir = orig.publicSourceDir;
|
||||||
|
nativeLibraryDir = orig.nativeLibraryDir;
|
||||||
resourceDirs = orig.resourceDirs;
|
resourceDirs = orig.resourceDirs;
|
||||||
sharedLibraryFiles = orig.sharedLibraryFiles;
|
sharedLibraryFiles = orig.sharedLibraryFiles;
|
||||||
dataDir = orig.dataDir;
|
dataDir = orig.dataDir;
|
||||||
@ -483,6 +483,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
dest.writeInt(flags);
|
dest.writeInt(flags);
|
||||||
dest.writeString(sourceDir);
|
dest.writeString(sourceDir);
|
||||||
dest.writeString(publicSourceDir);
|
dest.writeString(publicSourceDir);
|
||||||
|
dest.writeString(nativeLibraryDir);
|
||||||
dest.writeStringArray(resourceDirs);
|
dest.writeStringArray(resourceDirs);
|
||||||
dest.writeStringArray(sharedLibraryFiles);
|
dest.writeStringArray(sharedLibraryFiles);
|
||||||
dest.writeString(dataDir);
|
dest.writeString(dataDir);
|
||||||
@ -514,6 +515,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
flags = source.readInt();
|
flags = source.readInt();
|
||||||
sourceDir = source.readString();
|
sourceDir = source.readString();
|
||||||
publicSourceDir = source.readString();
|
publicSourceDir = source.readString();
|
||||||
|
nativeLibraryDir = source.readString();
|
||||||
resourceDirs = source.readStringArray();
|
resourceDirs = source.readStringArray();
|
||||||
sharedLibraryFiles = source.readStringArray();
|
sharedLibraryFiles = source.readStringArray();
|
||||||
dataDir = source.readString();
|
dataDir = source.readString();
|
||||||
|
@ -51,6 +51,13 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public String dataDir;
|
public String dataDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full path to the directory where the native JNI libraries are stored.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public String nativeLibraryDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether or not this instrumentation will handle profiling.
|
* Specifies whether or not this instrumentation will handle profiling.
|
||||||
*/
|
*/
|
||||||
@ -68,6 +75,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
sourceDir = orig.sourceDir;
|
sourceDir = orig.sourceDir;
|
||||||
publicSourceDir = orig.publicSourceDir;
|
publicSourceDir = orig.publicSourceDir;
|
||||||
dataDir = orig.dataDir;
|
dataDir = orig.dataDir;
|
||||||
|
nativeLibraryDir = orig.nativeLibraryDir;
|
||||||
handleProfiling = orig.handleProfiling;
|
handleProfiling = orig.handleProfiling;
|
||||||
functionalTest = orig.functionalTest;
|
functionalTest = orig.functionalTest;
|
||||||
}
|
}
|
||||||
@ -88,6 +96,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
dest.writeString(sourceDir);
|
dest.writeString(sourceDir);
|
||||||
dest.writeString(publicSourceDir);
|
dest.writeString(publicSourceDir);
|
||||||
dest.writeString(dataDir);
|
dest.writeString(dataDir);
|
||||||
|
dest.writeString(nativeLibraryDir);
|
||||||
dest.writeInt((handleProfiling == false) ? 0 : 1);
|
dest.writeInt((handleProfiling == false) ? 0 : 1);
|
||||||
dest.writeInt((functionalTest == false) ? 0 : 1);
|
dest.writeInt((functionalTest == false) ? 0 : 1);
|
||||||
}
|
}
|
||||||
@ -108,6 +117,7 @@ public class InstrumentationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
sourceDir = source.readString();
|
sourceDir = source.readString();
|
||||||
publicSourceDir = source.readString();
|
publicSourceDir = source.readString();
|
||||||
dataDir = source.readString();
|
dataDir = source.readString();
|
||||||
|
nativeLibraryDir = source.readString();
|
||||||
handleProfiling = source.readInt() != 0;
|
handleProfiling = source.readInt() != 0;
|
||||||
functionalTest = source.readInt() != 0;
|
functionalTest = source.readInt() != 0;
|
||||||
}
|
}
|
||||||
|
296
core/java/com/android/internal/content/NativeLibraryHelper.java
Normal file
296
core/java/com/android/internal/content/NativeLibraryHelper.java
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
package com.android.internal.content;
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.FileUtils;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
import android.util.Config;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipException;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native libraries helper.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class NativeLibraryHelper {
|
||||||
|
private static final String TAG = "NativeHelper";
|
||||||
|
|
||||||
|
private static final boolean DEBUG_NATIVE = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following constants are returned by listPackageSharedLibsForAbiLI
|
||||||
|
* to indicate if native shared libraries were found in the package.
|
||||||
|
* Values are:
|
||||||
|
* PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
|
||||||
|
* PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
|
||||||
|
* PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
|
||||||
|
* in package (and not installed)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
|
||||||
|
private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
|
||||||
|
private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
|
||||||
|
|
||||||
|
// Directory in the APK that holds all the native shared libraries.
|
||||||
|
private static final String APK_LIB = "lib/";
|
||||||
|
private static final int APK_LIB_LENGTH = APK_LIB.length();
|
||||||
|
|
||||||
|
// Prefix that native shared libraries must have.
|
||||||
|
private static final String LIB_PREFIX = "lib";
|
||||||
|
private static final int LIB_PREFIX_LENGTH = LIB_PREFIX.length();
|
||||||
|
|
||||||
|
// Suffix that the native shared libraries must have.
|
||||||
|
private static final String LIB_SUFFIX = ".so";
|
||||||
|
private static final int LIB_SUFFIX_LENGTH = LIB_SUFFIX.length();
|
||||||
|
|
||||||
|
// Name of the GDB binary.
|
||||||
|
private static final String GDBSERVER = "gdbserver";
|
||||||
|
|
||||||
|
// the minimum length of a valid native shared library of the form
|
||||||
|
// lib/<something>/lib<name>.so.
|
||||||
|
private static final int MIN_ENTRY_LENGTH = APK_LIB_LENGTH + 2 + LIB_PREFIX_LENGTH + 1
|
||||||
|
+ LIB_SUFFIX_LENGTH;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
|
||||||
|
* and add them to a list to be installed later.
|
||||||
|
*
|
||||||
|
* NOTE: this method may throw an IOException if the library cannot
|
||||||
|
* be copied to its final destination, e.g. if there isn't enough
|
||||||
|
* room left on the data partition, or a ZipException if the package
|
||||||
|
* file is malformed.
|
||||||
|
*/
|
||||||
|
private static int listPackageSharedLibsForAbiLI(ZipFile zipFile,
|
||||||
|
String cpuAbi, List<Pair<ZipEntry, String>> libEntries) throws IOException,
|
||||||
|
ZipException {
|
||||||
|
final int cpuAbiLen = cpuAbi.length();
|
||||||
|
boolean hasNativeLibraries = false;
|
||||||
|
boolean installedNativeLibraries = false;
|
||||||
|
|
||||||
|
if (DEBUG_NATIVE) {
|
||||||
|
Slog.d(TAG, "Checking " + zipFile.getName() + " for shared libraries of CPU ABI type "
|
||||||
|
+ cpuAbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
ZipEntry entry = entries.nextElement();
|
||||||
|
|
||||||
|
// skip directories
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String entryName = entry.getName();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the entry looks like lib/<something>/lib<name>.so
|
||||||
|
* here, but don't check the ABI just yet.
|
||||||
|
*
|
||||||
|
* - must be sufficiently long
|
||||||
|
* - must end with LIB_SUFFIX, i.e. ".so"
|
||||||
|
* - must start with APK_LIB, i.e. "lib/"
|
||||||
|
*/
|
||||||
|
if (entryName.length() < MIN_ENTRY_LENGTH || !entryName.endsWith(LIB_SUFFIX)
|
||||||
|
|| !entryName.startsWith(APK_LIB)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// file name must start with LIB_PREFIX, i.e. "lib"
|
||||||
|
int lastSlash = entryName.lastIndexOf('/');
|
||||||
|
|
||||||
|
if (lastSlash < 0
|
||||||
|
|| !entryName.regionMatches(lastSlash + 1, LIB_PREFIX, 0, LIB_PREFIX_LENGTH)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNativeLibraries = true;
|
||||||
|
|
||||||
|
// check the cpuAbi now, between lib/ and /lib<name>.so
|
||||||
|
if (lastSlash != APK_LIB_LENGTH + cpuAbiLen
|
||||||
|
|| !entryName.regionMatches(APK_LIB_LENGTH, cpuAbi, 0, cpuAbiLen))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract the library file name, ensure it doesn't contain
|
||||||
|
* weird characters. we're guaranteed here that it doesn't contain
|
||||||
|
* a directory separator though.
|
||||||
|
*/
|
||||||
|
String libFileName = entryName.substring(lastSlash+1);
|
||||||
|
if (!FileUtils.isFilenameSafe(new File(libFileName))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
installedNativeLibraries = true;
|
||||||
|
|
||||||
|
if (DEBUG_NATIVE) {
|
||||||
|
Log.d(TAG, "Caching shared lib " + entry.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
libEntries.add(Pair.create(entry, libFileName));
|
||||||
|
}
|
||||||
|
if (!hasNativeLibraries)
|
||||||
|
return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
|
||||||
|
|
||||||
|
if (!installedNativeLibraries)
|
||||||
|
return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
|
||||||
|
|
||||||
|
return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the gdbserver executable program in a package at
|
||||||
|
* lib/<cpuAbi>/gdbserver and add it to the list of binaries
|
||||||
|
* to be copied out later.
|
||||||
|
*
|
||||||
|
* Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
|
||||||
|
* or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
|
||||||
|
*/
|
||||||
|
private static int listPackageGdbServerLI(ZipFile zipFile, String cpuAbi,
|
||||||
|
List<Pair<ZipEntry, String>> nativeFiles) throws IOException, ZipException {
|
||||||
|
final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
|
||||||
|
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
ZipEntry entry = entries.nextElement();
|
||||||
|
// skip directories
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String entryName = entry.getName();
|
||||||
|
|
||||||
|
if (!entryName.equals(apkGdbServerPath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.LOGD) {
|
||||||
|
Log.d(TAG, "Found gdbserver: " + entry.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String installGdbServerPath = APK_LIB + GDBSERVER;
|
||||||
|
nativeFiles.add(Pair.create(entry, installGdbServerPath));
|
||||||
|
|
||||||
|
return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
|
||||||
|
}
|
||||||
|
return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Examine shared libraries stored in the APK as
|
||||||
|
* lib/<cpuAbi>/lib<name>.so and add them to a list to be copied
|
||||||
|
* later.
|
||||||
|
*
|
||||||
|
* This function will first try the main CPU ABI defined by Build.CPU_ABI
|
||||||
|
* (which corresponds to ro.product.cpu.abi), and also try an alternate
|
||||||
|
* one if ro.product.cpu.abi2 is defined.
|
||||||
|
*/
|
||||||
|
public static int listPackageNativeBinariesLI(ZipFile zipFile,
|
||||||
|
List<Pair<ZipEntry, String>> nativeFiles) throws ZipException, IOException {
|
||||||
|
String cpuAbi = Build.CPU_ABI;
|
||||||
|
|
||||||
|
int result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi, nativeFiles);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some architectures are capable of supporting several CPU ABIs
|
||||||
|
* for example, 'armeabi-v7a' also supports 'armeabi' native code
|
||||||
|
* this is indicated by the definition of the ro.product.cpu.abi2
|
||||||
|
* system property.
|
||||||
|
*
|
||||||
|
* only scan the package twice in case of ABI mismatch
|
||||||
|
*/
|
||||||
|
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
||||||
|
final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2", null);
|
||||||
|
if (cpuAbi2 != null) {
|
||||||
|
result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi2, nativeFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
||||||
|
Slog.w(TAG, "Native ABI mismatch from package file");
|
||||||
|
return PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
|
||||||
|
cpuAbi = cpuAbi2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Debuggable packages may have gdbserver embedded, so add it to
|
||||||
|
* the list to the list of items to be extracted (as lib/gdbserver)
|
||||||
|
* into the application's native library directory later.
|
||||||
|
*/
|
||||||
|
if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
|
||||||
|
listPackageGdbServerLI(zipFile, cpuAbi, nativeFiles);
|
||||||
|
}
|
||||||
|
return PackageManager.INSTALL_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int copyNativeBinariesLI(File scanFile, File sharedLibraryDir) {
|
||||||
|
/*
|
||||||
|
* Check all the native files that need to be copied and add
|
||||||
|
* that to the container size.
|
||||||
|
*/
|
||||||
|
ZipFile zipFile;
|
||||||
|
try {
|
||||||
|
zipFile = new ZipFile(scanFile);
|
||||||
|
|
||||||
|
List<Pair<ZipEntry, String>> nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
|
||||||
|
|
||||||
|
NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
|
||||||
|
|
||||||
|
final int N = nativeFiles.size();
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
final Pair<ZipEntry, String> entry = nativeFiles.get(i);
|
||||||
|
|
||||||
|
File destFile = new File(sharedLibraryDir, entry.second);
|
||||||
|
copyNativeBinaryLI(zipFile, entry.first, sharedLibraryDir, destFile);
|
||||||
|
}
|
||||||
|
} catch (ZipException e) {
|
||||||
|
Slog.w(TAG, "Failed to extract data from package file", e);
|
||||||
|
return PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Slog.w(TAG, "Failed to cache package shared libs", e);
|
||||||
|
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PackageManager.INSTALL_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copyNativeBinaryLI(ZipFile zipFile, ZipEntry entry,
|
||||||
|
File binaryDir, File binaryFile) throws IOException {
|
||||||
|
InputStream inputStream = zipFile.getInputStream(entry);
|
||||||
|
try {
|
||||||
|
File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
|
||||||
|
String tempFilePath = tempFile.getPath();
|
||||||
|
// XXX package manager can't change owner, so the executable files for
|
||||||
|
// now need to be left as world readable and owned by the system.
|
||||||
|
if (!FileUtils.copyToFile(inputStream, tempFile)
|
||||||
|
|| !tempFile.setLastModified(entry.getTime())
|
||||||
|
|| FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR | FileUtils.S_IWUSR
|
||||||
|
| FileUtils.S_IRGRP | FileUtils.S_IXUSR | FileUtils.S_IXGRP
|
||||||
|
| FileUtils.S_IXOTH | FileUtils.S_IROTH, -1, -1) != 0
|
||||||
|
|| !tempFile.renameTo(binaryFile)) {
|
||||||
|
// Failed to properly write file.
|
||||||
|
tempFile.delete();
|
||||||
|
throw new IOException("Couldn't create cached binary " + binaryFile + " in "
|
||||||
|
+ binaryDir);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -56,22 +56,22 @@ public class PackageHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String createSdDir(File tmpPackageFile, String cid,
|
public static String createSdDir(long sizeBytes, String cid,
|
||||||
String sdEncKey, int uid) {
|
String sdEncKey, int uid) {
|
||||||
// Create mount point via MountService
|
// Create mount point via MountService
|
||||||
IMountService mountService = getMountService();
|
IMountService mountService = getMountService();
|
||||||
long len = tmpPackageFile.length();
|
int sizeMb = (int) (sizeBytes >> 20);
|
||||||
int mbLen = (int) (len >> 20);
|
if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) {
|
||||||
if ((len - (mbLen * 1024 * 1024)) > 0) {
|
sizeMb++;
|
||||||
mbLen++;
|
|
||||||
}
|
}
|
||||||
// Add buffer size
|
// Add buffer size
|
||||||
mbLen++;
|
sizeMb++;
|
||||||
if (localLOGV) Log.i(TAG, "Size of container " + mbLen + " MB " + len + " bytes");
|
if (localLOGV)
|
||||||
|
Log.i(TAG, "Size of container " + sizeMb + " MB " + sizeBytes + " bytes");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
int rc = mountService.createSecureContainer(
|
int rc = mountService.createSecureContainer(
|
||||||
cid, mbLen, "fat", sdEncKey, uid);
|
cid, sizeMb, "fat", sdEncKey, uid);
|
||||||
if (rc != StorageResultCode.OperationSucceeded) {
|
if (rc != StorageResultCode.OperationSucceeded) {
|
||||||
Log.e(TAG, "Failed to create secure container " + cid);
|
Log.e(TAG, "Failed to create secure container " + cid);
|
||||||
return null;
|
return null;
|
||||||
|
@ -358,6 +358,7 @@ public class PackageManagerTests extends AndroidTestCase {
|
|||||||
assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
||||||
assertEquals(srcPath, drmInstallPath);
|
assertEquals(srcPath, drmInstallPath);
|
||||||
assertEquals(publicSrcPath, appInstallPath);
|
assertEquals(publicSrcPath, appInstallPath);
|
||||||
|
assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
|
||||||
} else {
|
} else {
|
||||||
assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
||||||
int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
|
int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
|
||||||
@ -365,10 +366,12 @@ public class PackageManagerTests extends AndroidTestCase {
|
|||||||
assertEquals(srcPath, appInstallPath);
|
assertEquals(srcPath, appInstallPath);
|
||||||
assertEquals(publicSrcPath, appInstallPath);
|
assertEquals(publicSrcPath, appInstallPath);
|
||||||
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
|
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
|
||||||
|
assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
|
||||||
} else if (rLoc == INSTALL_LOC_SD){
|
} else if (rLoc == INSTALL_LOC_SD){
|
||||||
assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
|
assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
|
||||||
assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
|
assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
|
||||||
assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
|
assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
|
||||||
|
assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
|
||||||
} else {
|
} else {
|
||||||
// TODO handle error. Install should have failed.
|
// TODO handle error. Install should have failed.
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
package com.android.defcontainer;
|
package com.android.defcontainer;
|
||||||
|
|
||||||
import com.android.internal.app.IMediaContainerService;
|
import com.android.internal.app.IMediaContainerService;
|
||||||
|
import com.android.internal.content.NativeLibraryHelper;
|
||||||
import com.android.internal.content.PackageHelper;
|
import com.android.internal.content.PackageHelper;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
@ -37,6 +39,7 @@ import android.os.StatFs;
|
|||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -44,6 +47,11 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipException;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@ -59,6 +67,8 @@ public class DefaultContainerService extends IntentService {
|
|||||||
private static final String TAG = "DefContainer";
|
private static final String TAG = "DefContainer";
|
||||||
private static final boolean localLOGV = true;
|
private static final boolean localLOGV = true;
|
||||||
|
|
||||||
|
private static final String LIB_DIR_NAME = "lib";
|
||||||
|
|
||||||
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
|
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
|
||||||
/*
|
/*
|
||||||
* Creates a new container and copies resource there.
|
* Creates a new container and copies resource there.
|
||||||
@ -194,18 +204,51 @@ public class DefaultContainerService extends IntentService {
|
|||||||
Log.w(TAG, "Make sure sdcard is mounted.");
|
Log.w(TAG, "Make sure sdcard is mounted.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Create new container at newCachePath
|
|
||||||
|
// The .apk file
|
||||||
String codePath = packageURI.getPath();
|
String codePath = packageURI.getPath();
|
||||||
File codeFile = new File(codePath);
|
File codeFile = new File(codePath);
|
||||||
String newCachePath = null;
|
|
||||||
|
// Calculate size of container needed to hold base APK.
|
||||||
|
long sizeBytes = codeFile.length();
|
||||||
|
|
||||||
|
// Check all the native files that need to be copied and add that to the container size.
|
||||||
|
ZipFile zipFile;
|
||||||
|
List<Pair<ZipEntry, String>> nativeFiles;
|
||||||
|
try {
|
||||||
|
zipFile = new ZipFile(codeFile);
|
||||||
|
|
||||||
|
nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
|
||||||
|
|
||||||
|
NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
|
||||||
|
|
||||||
|
final int N = nativeFiles.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
final Pair<ZipEntry, String> entry = nativeFiles.get(i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that PackageHelper.createSdDir adds a 1MB padding on
|
||||||
|
* our claimed size, so we don't have to worry about block
|
||||||
|
* alignment here.
|
||||||
|
*/
|
||||||
|
sizeBytes += entry.first.getSize();
|
||||||
|
}
|
||||||
|
} catch (ZipException e) {
|
||||||
|
Log.w(TAG, "Failed to extract data from package file", e);
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "Failed to cache package shared libs", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Create new container
|
// Create new container
|
||||||
if ((newCachePath = PackageHelper.createSdDir(codeFile,
|
String newCachePath = null;
|
||||||
newCid, key, Process.myUid())) == null) {
|
if ((newCachePath = PackageHelper.createSdDir(sizeBytes, newCid, key, Process.myUid())) == null) {
|
||||||
Log.e(TAG, "Failed to create container " + newCid);
|
Log.e(TAG, "Failed to create container " + newCid);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (localLOGV) Log.i(TAG, "Created container for " + newCid
|
if (localLOGV)
|
||||||
+ " at path : " + newCachePath);
|
Log.i(TAG, "Created container for " + newCid + " at path : " + newCachePath);
|
||||||
File resFile = new File(newCachePath, resFileName);
|
File resFile = new File(newCachePath, resFileName);
|
||||||
if (!FileUtils.copyFile(new File(codePath), resFile)) {
|
if (!FileUtils.copyFile(new File(codePath), resFile)) {
|
||||||
Log.e(TAG, "Failed to copy " + codePath + " to " + resFile);
|
Log.e(TAG, "Failed to copy " + codePath + " to " + resFile);
|
||||||
@ -213,6 +256,32 @@ public class DefaultContainerService extends IntentService {
|
|||||||
PackageHelper.destroySdDir(newCid);
|
PackageHelper.destroySdDir(newCid);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
|
||||||
|
sharedLibraryDir.mkdir();
|
||||||
|
|
||||||
|
final int N = nativeFiles.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
final Pair<ZipEntry, String> entry = nativeFiles.get(i);
|
||||||
|
|
||||||
|
InputStream is = zipFile.getInputStream(entry.first);
|
||||||
|
try {
|
||||||
|
File destFile = new File(sharedLibraryDir, entry.second);
|
||||||
|
if (!FileUtils.copyToFile(is, destFile)) {
|
||||||
|
throw new IOException("Couldn't copy native binary "
|
||||||
|
+ entry.first.getName() + " to " + entry.second);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Couldn't copy native file to container", e);
|
||||||
|
PackageHelper.destroySdDir(newCid);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
|
if (localLOGV) Log.i(TAG, "Copied " + codePath + " to " + resFile);
|
||||||
if (!PackageHelper.finalizeSdDir(newCid)) {
|
if (!PackageHelper.finalizeSdDir(newCid)) {
|
||||||
Log.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
|
Log.e(TAG, "Failed to finalize " + newCid + " at path " + newCachePath);
|
||||||
|
@ -18,6 +18,7 @@ package com.android.server;
|
|||||||
|
|
||||||
import com.android.internal.app.IMediaContainerService;
|
import com.android.internal.app.IMediaContainerService;
|
||||||
import com.android.internal.app.ResolverActivity;
|
import com.android.internal.app.ResolverActivity;
|
||||||
|
import com.android.internal.content.NativeLibraryHelper;
|
||||||
import com.android.internal.content.PackageHelper;
|
import com.android.internal.content.PackageHelper;
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
import com.android.internal.util.FastXmlSerializer;
|
||||||
import com.android.internal.util.JournaledFile;
|
import com.android.internal.util.JournaledFile;
|
||||||
@ -112,6 +113,7 @@ import java.util.Enumeration;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -188,6 +190,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
"com.android.defcontainer",
|
"com.android.defcontainer",
|
||||||
"com.android.defcontainer.DefaultContainerService");
|
"com.android.defcontainer.DefaultContainerService");
|
||||||
|
|
||||||
|
private static final String LIB_DIR_NAME = "lib";
|
||||||
|
|
||||||
static final String mTempContainerPrefix = "smdl2tmp";
|
static final String mTempContainerPrefix = "smdl2tmp";
|
||||||
|
|
||||||
final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
|
final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
|
||||||
@ -678,13 +682,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isFwdLocked(int flags) {
|
|
||||||
if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final IPackageManager main(Context context, boolean factoryTest) {
|
public static final IPackageManager main(Context context, boolean factoryTest) {
|
||||||
PackageManagerService m = new PackageManagerService(context, factoryTest);
|
PackageManagerService m = new PackageManagerService(context, factoryTest);
|
||||||
ServiceManager.addService("package", m);
|
ServiceManager.addService("package", m);
|
||||||
@ -1497,6 +1494,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
|
ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString;
|
||||||
ps.pkg.applicationInfo.sourceDir = ps.codePathString;
|
ps.pkg.applicationInfo.sourceDir = ps.codePathString;
|
||||||
ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
|
ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath();
|
||||||
|
ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
|
||||||
ps.pkg.mSetEnabled = ps.enabled;
|
ps.pkg.mSetEnabled = ps.enabled;
|
||||||
}
|
}
|
||||||
return generatePackageInfo(ps.pkg, flags);
|
return generatePackageInfo(ps.pkg, flags);
|
||||||
@ -2376,8 +2374,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
PackageParser.Package p = i.next();
|
PackageParser.Package p = i.next();
|
||||||
if (p.applicationInfo != null
|
if (p.applicationInfo != null
|
||||||
&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
|
&& (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
|
||||||
&& (!mSafeMode || (p.applicationInfo.flags
|
&& (!mSafeMode || isSystemApp(p))) {
|
||||||
&ApplicationInfo.FLAG_SYSTEM) != 0)) {
|
|
||||||
finalList.add(PackageParser.generateApplicationInfo(p, flags));
|
finalList.add(PackageParser.generateApplicationInfo(p, flags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2621,9 +2618,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
+ "reverting from " + ps.codePathString
|
+ "reverting from " + ps.codePathString
|
||||||
+ ": new version " + pkg.mVersionCode
|
+ ": new version " + pkg.mVersionCode
|
||||||
+ " better than installed " + ps.versionCode);
|
+ " better than installed " + ps.versionCode);
|
||||||
InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
|
InstallArgs args = new FileInstallArgs(ps.codePathString,
|
||||||
|
ps.resourcePathString, ps.nativeLibraryPathString);
|
||||||
args.cleanUpResourcesLI();
|
args.cleanUpResourcesLI();
|
||||||
removeNativeBinariesLI(pkg);
|
|
||||||
mSettings.enableSystemPackageLP(ps.name);
|
mSettings.enableSystemPackageLP(ps.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2663,8 +2660,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
|
return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setApplicationInfoPaths(PackageParser.Package pkg,
|
private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath,
|
||||||
String destCodePath, String destResPath) {
|
String destResPath) {
|
||||||
pkg.mPath = pkg.mScanPath = destCodePath;
|
pkg.mPath = pkg.mScanPath = destCodePath;
|
||||||
pkg.applicationInfo.sourceDir = destCodePath;
|
pkg.applicationInfo.sourceDir = destCodePath;
|
||||||
pkg.applicationInfo.publicSourceDir = destResPath;
|
pkg.applicationInfo.publicSourceDir = destResPath;
|
||||||
@ -3146,10 +3143,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (dataPath.exists()) {
|
if (dataPath.exists()) {
|
||||||
mOutPermissions[1] = 0;
|
mOutPermissions[1] = 0;
|
||||||
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
|
FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
|
||||||
if (mOutPermissions[1] == pkg.applicationInfo.uid
|
|
||||||
|| !Process.supportsProcesses()) {
|
// If we have mismatched owners for the data path, we have a
|
||||||
pkg.applicationInfo.dataDir = dataPath.getPath();
|
// problem (unless we're running in the simulator.)
|
||||||
} else {
|
if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) {
|
||||||
boolean recovered = false;
|
boolean recovered = false;
|
||||||
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
|
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
|
||||||
// If this is a system app, we can at least delete its
|
// If this is a system app, we can at least delete its
|
||||||
@ -3186,6 +3183,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
|
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
|
||||||
+ pkg.applicationInfo.uid + "/fs_"
|
+ pkg.applicationInfo.uid + "/fs_"
|
||||||
+ mOutPermissions[1];
|
+ mOutPermissions[1];
|
||||||
|
pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
|
||||||
String msg = "Package " + pkg.packageName
|
String msg = "Package " + pkg.packageName
|
||||||
+ " has mismatched uid: "
|
+ " has mismatched uid: "
|
||||||
+ mOutPermissions[1] + " on disk, "
|
+ mOutPermissions[1] + " on disk, "
|
||||||
@ -3230,31 +3228,37 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the data dir to the default "/data/data/<package name>/lib"
|
||||||
|
* if we got here without anyone telling us different (e.g., apps
|
||||||
|
* stored on SD card have their native libraries stored in the ASEC
|
||||||
|
* container with the APK).
|
||||||
|
*/
|
||||||
|
if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
|
||||||
|
pkg.applicationInfo.nativeLibraryDir = new File(dataPath, LIB_DIR_NAME).getPath();
|
||||||
|
}
|
||||||
|
|
||||||
pkgSetting.uidError = uidError;
|
pkgSetting.uidError = uidError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform shared library installation and dex validation and
|
// If we're running in the simulator, we don't need to unpack anything.
|
||||||
// optimization, if this is not a system app.
|
|
||||||
if (mInstaller != null) {
|
if (mInstaller != null) {
|
||||||
String path = scanFile.getPath();
|
String path = scanFile.getPath();
|
||||||
if (scanFileNewer) {
|
/* Note: We don't want to unpack the native binaries for
|
||||||
// Note: We don't want to unpack the native binaries for
|
* system applications, unless they have been updated
|
||||||
// system applications, unless they have been updated
|
* (the binaries are already under /system/lib).
|
||||||
// (the binaries are already under /system/lib).
|
* Also, don't unpack libs for apps on the external card
|
||||||
//
|
* since they should have their libraries in the ASEC
|
||||||
// In other words, we're going to unpack the binaries
|
* container already.
|
||||||
// only for non-system apps and system app upgrades.
|
*
|
||||||
//
|
* In other words, we're going to unpack the binaries
|
||||||
int flags = pkg.applicationInfo.flags;
|
* only for non-system apps and system app upgrades.
|
||||||
if ((flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
|
*/
|
||||||
(flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
|
if ((!isSystemApp(pkg) || isUpdatedSystemApp(pkg)) && !isExternal(pkg)) {
|
||||||
Log.i(TAG, path + " changed; unpacking");
|
Log.i(TAG, path + " changed; unpacking");
|
||||||
int err = cachePackageSharedLibsLI(pkg, scanFile);
|
File sharedLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
|
||||||
if (err != PackageManager.INSTALL_SUCCEEDED) {
|
sharedLibraryDir.mkdir();
|
||||||
mLastScanError = err;
|
NativeLibraryHelper.copyNativeBinariesLI(scanFile, sharedLibraryDir);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pkg.mScanPath = path;
|
pkg.mScanPath = path;
|
||||||
|
|
||||||
@ -3517,6 +3521,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
a.info.sourceDir = pkg.applicationInfo.sourceDir;
|
a.info.sourceDir = pkg.applicationInfo.sourceDir;
|
||||||
a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
|
a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
|
||||||
a.info.dataDir = pkg.applicationInfo.dataDir;
|
a.info.dataDir = pkg.applicationInfo.dataDir;
|
||||||
|
a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
|
||||||
mInstrumentation.put(a.getComponentName(), a);
|
mInstrumentation.put(a.getComponentName(), a);
|
||||||
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
|
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
@ -3557,266 +3562,30 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following constants are returned by cachePackageSharedLibsForAbiLI
|
|
||||||
// to indicate if native shared libraries were found in the package.
|
|
||||||
// Values are:
|
|
||||||
// PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
|
|
||||||
// PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
|
|
||||||
// PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
|
|
||||||
// in package (and not installed)
|
|
||||||
//
|
|
||||||
private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
|
|
||||||
private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
|
|
||||||
private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
|
|
||||||
|
|
||||||
// Return the path of the directory that will contain the native binaries
|
// Return the path of the directory that will contain the native binaries
|
||||||
// of a given installed package. This is relative to the data path.
|
// of a given installed package. This is relative to the data path.
|
||||||
//
|
//
|
||||||
private static File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
|
private File getNativeBinaryDirForPackage(PackageParser.Package pkg) {
|
||||||
return new File(pkg.applicationInfo.dataDir + "/lib");
|
final String nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
|
||||||
}
|
if (nativeLibraryDir != null) {
|
||||||
|
return new File(nativeLibraryDir);
|
||||||
// Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
|
} else {
|
||||||
// and automatically copy them to /data/data/<appname>/lib if present.
|
// Fall back for old packages
|
||||||
//
|
return new File(pkg.applicationInfo.dataDir, LIB_DIR_NAME);
|
||||||
// NOTE: this method may throw an IOException if the library cannot
|
|
||||||
// be copied to its final destination, e.g. if there isn't enough
|
|
||||||
// room left on the data partition, or a ZipException if the package
|
|
||||||
// file is malformed.
|
|
||||||
//
|
|
||||||
private int cachePackageSharedLibsForAbiLI(PackageParser.Package pkg,
|
|
||||||
File scanFile, String cpuAbi) throws IOException, ZipException {
|
|
||||||
File sharedLibraryDir = getNativeBinaryDirForPackage(pkg);
|
|
||||||
final String apkLib = "lib/";
|
|
||||||
final int apkLibLen = apkLib.length();
|
|
||||||
final int cpuAbiLen = cpuAbi.length();
|
|
||||||
final String libPrefix = "lib";
|
|
||||||
final int libPrefixLen = libPrefix.length();
|
|
||||||
final String libSuffix = ".so";
|
|
||||||
final int libSuffixLen = libSuffix.length();
|
|
||||||
boolean hasNativeLibraries = false;
|
|
||||||
boolean installedNativeLibraries = false;
|
|
||||||
|
|
||||||
// the minimum length of a valid native shared library of the form
|
|
||||||
// lib/<something>/lib<name>.so.
|
|
||||||
final int minEntryLen = apkLibLen + 2 + libPrefixLen + 1 + libSuffixLen;
|
|
||||||
|
|
||||||
ZipFile zipFile = new ZipFile(scanFile);
|
|
||||||
Enumeration<ZipEntry> entries =
|
|
||||||
(Enumeration<ZipEntry>) zipFile.entries();
|
|
||||||
|
|
||||||
while (entries.hasMoreElements()) {
|
|
||||||
ZipEntry entry = entries.nextElement();
|
|
||||||
// skip directories
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String entryName = entry.getName();
|
|
||||||
|
|
||||||
// check that the entry looks like lib/<something>/lib<name>.so
|
|
||||||
// here, but don't check the ABI just yet.
|
|
||||||
//
|
|
||||||
// - must be sufficiently long
|
|
||||||
// - must end with libSuffix, i.e. ".so"
|
|
||||||
// - must start with apkLib, i.e. "lib/"
|
|
||||||
if (entryName.length() < minEntryLen ||
|
|
||||||
!entryName.endsWith(libSuffix) ||
|
|
||||||
!entryName.startsWith(apkLib) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// file name must start with libPrefix, i.e. "lib"
|
|
||||||
int lastSlash = entryName.lastIndexOf('/');
|
|
||||||
|
|
||||||
if (lastSlash < 0 ||
|
|
||||||
!entryName.regionMatches(lastSlash+1, libPrefix, 0, libPrefixLen) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasNativeLibraries = true;
|
|
||||||
|
|
||||||
// check the cpuAbi now, between lib/ and /lib<name>.so
|
|
||||||
//
|
|
||||||
if (lastSlash != apkLibLen + cpuAbiLen ||
|
|
||||||
!entryName.regionMatches(apkLibLen, cpuAbi, 0, cpuAbiLen) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// extract the library file name, ensure it doesn't contain
|
|
||||||
// weird characters. we're guaranteed here that it doesn't contain
|
|
||||||
// a directory separator though.
|
|
||||||
String libFileName = entryName.substring(lastSlash+1);
|
|
||||||
if (!FileUtils.isFilenameSafe(new File(libFileName))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
installedNativeLibraries = true;
|
|
||||||
|
|
||||||
// Always extract the shared library
|
|
||||||
String sharedLibraryFilePath = sharedLibraryDir.getPath() +
|
|
||||||
File.separator + libFileName;
|
|
||||||
File sharedLibraryFile = new File(sharedLibraryFilePath);
|
|
||||||
|
|
||||||
if (Config.LOGD) {
|
|
||||||
Log.d(TAG, "Caching shared lib " + entry.getName());
|
|
||||||
}
|
|
||||||
if (mInstaller == null) {
|
|
||||||
sharedLibraryDir.mkdir();
|
|
||||||
}
|
|
||||||
cacheNativeBinaryLI(pkg, zipFile, entry, sharedLibraryDir,
|
|
||||||
sharedLibraryFile);
|
|
||||||
}
|
|
||||||
if (!hasNativeLibraries)
|
|
||||||
return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
|
|
||||||
|
|
||||||
if (!installedNativeLibraries)
|
|
||||||
return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
|
|
||||||
|
|
||||||
return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the gdbserver executable program in a package at
|
|
||||||
// lib/<cpuAbi>/gdbserver and copy it to /data/data/<name>/lib/gdbserver
|
|
||||||
//
|
|
||||||
// Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
|
|
||||||
// or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
|
|
||||||
//
|
|
||||||
private int cachePackageGdbServerLI(PackageParser.Package pkg,
|
|
||||||
File scanFile, String cpuAbi) throws IOException, ZipException {
|
|
||||||
File installGdbServerDir = getNativeBinaryDirForPackage(pkg);
|
|
||||||
final String GDBSERVER = "gdbserver";
|
|
||||||
final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
|
|
||||||
|
|
||||||
ZipFile zipFile = new ZipFile(scanFile);
|
|
||||||
Enumeration<ZipEntry> entries =
|
|
||||||
(Enumeration<ZipEntry>) zipFile.entries();
|
|
||||||
|
|
||||||
while (entries.hasMoreElements()) {
|
|
||||||
ZipEntry entry = entries.nextElement();
|
|
||||||
// skip directories
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String entryName = entry.getName();
|
|
||||||
|
|
||||||
if (!entryName.equals(apkGdbServerPath)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String installGdbServerPath = installGdbServerDir.getPath() +
|
|
||||||
"/" + GDBSERVER;
|
|
||||||
File installGdbServerFile = new File(installGdbServerPath);
|
|
||||||
|
|
||||||
if (Config.LOGD) {
|
|
||||||
Log.d(TAG, "Caching gdbserver " + entry.getName());
|
|
||||||
}
|
|
||||||
if (mInstaller == null) {
|
|
||||||
installGdbServerDir.mkdir();
|
|
||||||
}
|
|
||||||
cacheNativeBinaryLI(pkg, zipFile, entry, installGdbServerDir,
|
|
||||||
installGdbServerFile);
|
|
||||||
|
|
||||||
return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
|
|
||||||
}
|
|
||||||
return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract shared libraries stored in the APK as lib/<cpuAbi>/lib<name>.so
|
|
||||||
// and copy them to /data/data/<appname>/lib.
|
|
||||||
//
|
|
||||||
// This function will first try the main CPU ABI defined by Build.CPU_ABI
|
|
||||||
// (which corresponds to ro.product.cpu.abi), and also try an alternate
|
|
||||||
// one if ro.product.cpu.abi2 is defined.
|
|
||||||
//
|
|
||||||
private int cachePackageSharedLibsLI(PackageParser.Package pkg, File scanFile) {
|
|
||||||
// Remove all native binaries from a directory. This is used when upgrading
|
|
||||||
// a package: in case the new .apk doesn't contain a native binary that was
|
|
||||||
// in the old one (and thus installed), we need to remove it from
|
|
||||||
// /data/data/<appname>/lib
|
|
||||||
//
|
|
||||||
// The simplest way to do that is to remove all files in this directory,
|
|
||||||
// since it is owned by "system", applications are not supposed to write
|
|
||||||
// anything there.
|
|
||||||
removeNativeBinariesLI(pkg);
|
|
||||||
|
|
||||||
String cpuAbi = Build.CPU_ABI;
|
|
||||||
try {
|
|
||||||
int result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi);
|
|
||||||
|
|
||||||
// some architectures are capable of supporting several CPU ABIs
|
|
||||||
// for example, 'armeabi-v7a' also supports 'armeabi' native code
|
|
||||||
// this is indicated by the definition of the ro.product.cpu.abi2
|
|
||||||
// system property.
|
|
||||||
//
|
|
||||||
// only scan the package twice in case of ABI mismatch
|
|
||||||
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
|
||||||
final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2",null);
|
|
||||||
if (cpuAbi2 != null) {
|
|
||||||
result = cachePackageSharedLibsForAbiLI(pkg, scanFile, cpuAbi2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
|
|
||||||
Slog.w(TAG,"Native ABI mismatch from package file");
|
|
||||||
return PackageManager.INSTALL_FAILED_INVALID_APK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
|
|
||||||
cpuAbi = cpuAbi2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for debuggable packages, also extract gdbserver from lib/<abi>
|
// Convenience call for removeNativeBinariesLI(File)
|
||||||
// into /data/data/<appname>/lib too.
|
private void removeNativeBinariesLI(PackageParser.Package pkg) {
|
||||||
if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES &&
|
File nativeLibraryDir = getNativeBinaryDirForPackage(pkg);
|
||||||
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
|
removeNativeBinariesLI(nativeLibraryDir);
|
||||||
int result2 = cachePackageGdbServerLI(pkg, scanFile, cpuAbi);
|
|
||||||
if (result2 == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
|
|
||||||
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_NATIVE_DEBUGGABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ZipException e) {
|
|
||||||
Slog.w(TAG, "Failed to extract data from package file", e);
|
|
||||||
return PackageManager.INSTALL_FAILED_INVALID_APK;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Slog.w(TAG, "Failed to cache package shared libs", e);
|
|
||||||
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
|
||||||
}
|
|
||||||
return PackageManager.INSTALL_SUCCEEDED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheNativeBinaryLI(PackageParser.Package pkg,
|
|
||||||
ZipFile zipFile, ZipEntry entry,
|
|
||||||
File binaryDir,
|
|
||||||
File binaryFile) throws IOException {
|
|
||||||
InputStream inputStream = zipFile.getInputStream(entry);
|
|
||||||
try {
|
|
||||||
File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
|
|
||||||
String tempFilePath = tempFile.getPath();
|
|
||||||
// XXX package manager can't change owner, so the executable files for
|
|
||||||
// now need to be left as world readable and owned by the system.
|
|
||||||
if (! FileUtils.copyToFile(inputStream, tempFile) ||
|
|
||||||
! tempFile.setLastModified(entry.getTime()) ||
|
|
||||||
FileUtils.setPermissions(tempFilePath,
|
|
||||||
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
|
|
||||||
|FileUtils.S_IXUSR|FileUtils.S_IXGRP|FileUtils.S_IXOTH
|
|
||||||
|FileUtils.S_IROTH, -1, -1) != 0 ||
|
|
||||||
! tempFile.renameTo(binaryFile)) {
|
|
||||||
// Failed to properly write file.
|
|
||||||
tempFile.delete();
|
|
||||||
throw new IOException("Couldn't create cached binary "
|
|
||||||
+ binaryFile + " in " + binaryDir);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the native binaries of a given package. This simply
|
// Remove the native binaries of a given package. This simply
|
||||||
// gets rid of the files in the 'lib' sub-directory.
|
// gets rid of the files in the 'lib' sub-directory.
|
||||||
private void removeNativeBinariesLI(PackageParser.Package pkg) {
|
public void removeNativeBinariesLI(File binaryDir) {
|
||||||
File binaryDir = getNativeBinaryDirForPackage(pkg);
|
|
||||||
|
|
||||||
if (DEBUG_NATIVE) {
|
if (DEBUG_NATIVE) {
|
||||||
Slog.w(TAG,"Deleting native binaries from: " + binaryDir.getPath());
|
Slog.w(TAG, "Deleting native binaries from: " + binaryDir.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just remove any file in the directory. Since the directory
|
// Just remove any file in the directory. Since the directory
|
||||||
@ -3826,13 +3595,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (binaryDir.exists()) {
|
if (binaryDir.exists()) {
|
||||||
File[] binaries = binaryDir.listFiles();
|
File[] binaries = binaryDir.listFiles();
|
||||||
if (binaries != null) {
|
if (binaries != null) {
|
||||||
for (int nn=0; nn < binaries.length; nn++) {
|
for (int nn = 0; nn < binaries.length; nn++) {
|
||||||
if (DEBUG_NATIVE) {
|
if (DEBUG_NATIVE) {
|
||||||
Slog.d(TAG," Deleting " + binaries[nn].getName());
|
Slog.d(TAG, " Deleting " + binaries[nn].getName());
|
||||||
}
|
}
|
||||||
if (!binaries[nn].delete()) {
|
if (!binaries[nn].delete()) {
|
||||||
Slog.w(TAG,"Could not delete native binary: " +
|
Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath());
|
||||||
binaries[nn].getPath());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4144,11 +3912,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
|| (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
|
|| (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
|
||||||
== PackageManager.SIGNATURE_MATCH);
|
== PackageManager.SIGNATURE_MATCH);
|
||||||
if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
|
if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
|
||||||
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
|
if (isSystemApp(pkg)) {
|
||||||
// For updated system applications, the signatureOrSystem permission
|
// For updated system applications, the signatureOrSystem permission
|
||||||
// is granted only if it had been defined by the original application.
|
// is granted only if it had been defined by the original application.
|
||||||
if ((pkg.applicationInfo.flags
|
if (isUpdatedSystemApp(pkg)) {
|
||||||
& ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
|
|
||||||
PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
|
PackageSetting sysPs = mSettings.getDisabledSystemPkg(pkg.packageName);
|
||||||
if(sysPs.grantedPermissions.contains(perm)) {
|
if(sysPs.grantedPermissions.contains(perm)) {
|
||||||
allowed = true;
|
allowed = true;
|
||||||
@ -4936,7 +4703,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
// App explictly prefers external. Let policy decide
|
// App explictly prefers external. Let policy decide
|
||||||
} else {
|
} else {
|
||||||
// Prefer previous location
|
// Prefer previous location
|
||||||
if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
|
if (isExternal(pkg)) {
|
||||||
return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
|
return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
|
||||||
}
|
}
|
||||||
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
|
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
|
||||||
@ -5048,16 +4815,16 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
final InstallArgs srcArgs;
|
final InstallArgs srcArgs;
|
||||||
final InstallArgs targetArgs;
|
final InstallArgs targetArgs;
|
||||||
int mRet;
|
int mRet;
|
||||||
MoveParams(InstallArgs srcArgs,
|
|
||||||
IPackageMoveObserver observer,
|
MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
|
||||||
int flags, String packageName) {
|
String packageName, String dataDir) {
|
||||||
this.srcArgs = srcArgs;
|
this.srcArgs = srcArgs;
|
||||||
this.observer = observer;
|
this.observer = observer;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
if (srcArgs != null) {
|
if (srcArgs != null) {
|
||||||
Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
|
Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
|
||||||
targetArgs = createInstallArgs(packageUri, flags, packageName);
|
targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
|
||||||
} else {
|
} else {
|
||||||
targetArgs = null;
|
targetArgs = null;
|
||||||
}
|
}
|
||||||
@ -5113,21 +4880,22 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
|
private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
|
||||||
|
String nativeLibraryPath) {
|
||||||
if (installOnSd(flags)) {
|
if (installOnSd(flags)) {
|
||||||
return new SdInstallArgs(fullCodePath, fullResourcePath);
|
return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
|
||||||
} else {
|
} else {
|
||||||
return new FileInstallArgs(fullCodePath, fullResourcePath);
|
return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstallArgs createInstallArgs(Uri packageURI, int flags,
|
// Used by package mover
|
||||||
String pkgName) {
|
private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
|
||||||
if (installOnSd(flags)) {
|
if (installOnSd(flags)) {
|
||||||
String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
|
String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
|
||||||
return new SdInstallArgs(packageURI, cid);
|
return new SdInstallArgs(packageURI, cid);
|
||||||
} else {
|
} else {
|
||||||
return new FileInstallArgs(packageURI, pkgName);
|
return new FileInstallArgs(packageURI, pkgName, dataDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5154,6 +4922,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
abstract int doPostInstall(int status);
|
abstract int doPostInstall(int status);
|
||||||
abstract String getCodePath();
|
abstract String getCodePath();
|
||||||
abstract String getResourcePath();
|
abstract String getResourcePath();
|
||||||
|
abstract String getNativeLibraryPath();
|
||||||
// Need installer lock especially for dex file removal.
|
// Need installer lock especially for dex file removal.
|
||||||
abstract void cleanUpResourcesLI();
|
abstract void cleanUpResourcesLI();
|
||||||
abstract boolean doPostDeleteLI(boolean delete);
|
abstract boolean doPostDeleteLI(boolean delete);
|
||||||
@ -5164,6 +4933,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
File installDir;
|
File installDir;
|
||||||
String codeFileName;
|
String codeFileName;
|
||||||
String resourceFileName;
|
String resourceFileName;
|
||||||
|
String libraryPath;
|
||||||
boolean created = false;
|
boolean created = false;
|
||||||
|
|
||||||
FileInstallArgs(InstallParams params) {
|
FileInstallArgs(InstallParams params) {
|
||||||
@ -5171,21 +4941,22 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
params.flags, params.installerPackageName);
|
params.flags, params.installerPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInstallArgs(String fullCodePath, String fullResourcePath) {
|
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
|
||||||
super(null, null, 0, null);
|
super(null, null, 0, null);
|
||||||
File codeFile = new File(fullCodePath);
|
File codeFile = new File(fullCodePath);
|
||||||
installDir = codeFile.getParentFile();
|
installDir = codeFile.getParentFile();
|
||||||
codeFileName = fullCodePath;
|
codeFileName = fullCodePath;
|
||||||
resourceFileName = fullResourcePath;
|
resourceFileName = fullResourcePath;
|
||||||
|
libraryPath = nativeLibraryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInstallArgs(Uri packageURI, String pkgName) {
|
FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
|
||||||
super(packageURI, null, 0, null);
|
super(packageURI, null, 0, null);
|
||||||
boolean fwdLocked = isFwdLocked(flags);
|
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
|
||||||
installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
|
|
||||||
String apkName = getNextCodePath(null, pkgName, ".apk");
|
String apkName = getNextCodePath(null, pkgName, ".apk");
|
||||||
codeFileName = new File(installDir, apkName + ".apk").getPath();
|
codeFileName = new File(installDir, apkName + ".apk").getPath();
|
||||||
resourceFileName = getResourcePathFromCodePath();
|
resourceFileName = getResourcePathFromCodePath();
|
||||||
|
libraryPath = new File(dataDir, LIB_DIR_NAME).getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
|
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
|
||||||
@ -5197,8 +4968,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createCopyFile() {
|
void createCopyFile() {
|
||||||
boolean fwdLocked = isFwdLocked(flags);
|
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
|
||||||
installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
|
|
||||||
codeFileName = createTempPackageFile(installDir).getPath();
|
codeFileName = createTempPackageFile(installDir).getPath();
|
||||||
resourceFileName = getResourcePathFromCodePath();
|
resourceFileName = getResourcePathFromCodePath();
|
||||||
created = true;
|
created = true;
|
||||||
@ -5226,8 +4996,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
ParcelFileDescriptor out = null;
|
ParcelFileDescriptor out = null;
|
||||||
try {
|
try {
|
||||||
out = ParcelFileDescriptor.open(codeFile,
|
out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE);
|
||||||
ParcelFileDescriptor.MODE_READ_WRITE);
|
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
|
Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName);
|
||||||
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||||
@ -5241,6 +5010,11 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
} finally {
|
} finally {
|
||||||
try { if (out != null) out.close(); } catch (IOException e) {}
|
try { if (out != null) out.close(); } catch (IOException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!temp) {
|
||||||
|
NativeLibraryHelper.copyNativeBinariesLI(codeFile, new File(libraryPath));
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5296,6 +5070,11 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getNativeLibraryPath() {
|
||||||
|
return libraryPath;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean cleanUp() {
|
private boolean cleanUp() {
|
||||||
boolean ret = true;
|
boolean ret = true;
|
||||||
String sourceDir = getCodePath();
|
String sourceDir = getCodePath();
|
||||||
@ -5332,11 +5111,14 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
// we don't consider this to be a failure of the core package deletion
|
// we don't consider this to be a failure of the core package deletion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (libraryPath != null) {
|
||||||
|
removeNativeBinariesLI(new File(libraryPath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setPermissions() {
|
private boolean setPermissions() {
|
||||||
// TODO Do this in a more elegant way later on. for now just a hack
|
// TODO Do this in a more elegant way later on. for now just a hack
|
||||||
if (!isFwdLocked(flags)) {
|
if (!isFwdLocked()) {
|
||||||
final int filePermissions =
|
final int filePermissions =
|
||||||
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
|
FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP
|
||||||
|FileUtils.S_IROTH;
|
|FileUtils.S_IROTH;
|
||||||
@ -5354,35 +5136,42 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean doPostDeleteLI(boolean delete) {
|
boolean doPostDeleteLI(boolean delete) {
|
||||||
|
// XXX err, shouldn't we respect the delete flag?
|
||||||
cleanUpResourcesLI();
|
cleanUpResourcesLI();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isFwdLocked() {
|
||||||
|
return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SdInstallArgs extends InstallArgs {
|
class SdInstallArgs extends InstallArgs {
|
||||||
String cid;
|
|
||||||
String cachePath;
|
|
||||||
static final String RES_FILE_NAME = "pkg.apk";
|
static final String RES_FILE_NAME = "pkg.apk";
|
||||||
|
|
||||||
|
String cid;
|
||||||
|
String packagePath;
|
||||||
|
String libraryPath;
|
||||||
|
|
||||||
SdInstallArgs(InstallParams params) {
|
SdInstallArgs(InstallParams params) {
|
||||||
super(params.packageURI, params.observer,
|
super(params.packageURI, params.observer,
|
||||||
params.flags, params.installerPackageName);
|
params.flags, params.installerPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
SdInstallArgs(String fullCodePath, String fullResourcePath) {
|
SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
|
||||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
||||||
// Extract cid from fullCodePath
|
// Extract cid from fullCodePath
|
||||||
int eidx = fullCodePath.lastIndexOf("/");
|
int eidx = fullCodePath.lastIndexOf("/");
|
||||||
String subStr1 = fullCodePath.substring(0, eidx);
|
String subStr1 = fullCodePath.substring(0, eidx);
|
||||||
int sidx = subStr1.lastIndexOf("/");
|
int sidx = subStr1.lastIndexOf("/");
|
||||||
cid = subStr1.substring(sidx+1, eidx);
|
cid = subStr1.substring(sidx+1, eidx);
|
||||||
cachePath = subStr1;
|
setCachePath(subStr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SdInstallArgs(String cid) {
|
SdInstallArgs(String cid) {
|
||||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
||||||
this.cid = cid;
|
this.cid = cid;
|
||||||
cachePath = PackageHelper.getSdDir(cid);
|
setCachePath(PackageHelper.getSdDir(cid));
|
||||||
}
|
}
|
||||||
|
|
||||||
SdInstallArgs(Uri packageURI, String cid) {
|
SdInstallArgs(Uri packageURI, String cid) {
|
||||||
@ -5402,21 +5191,30 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (temp) {
|
if (temp) {
|
||||||
createCopyFile();
|
createCopyFile();
|
||||||
}
|
}
|
||||||
cachePath = imcs.copyResourceToContainer(
|
String newCachePath = imcs.copyResourceToContainer(
|
||||||
packageURI, cid,
|
packageURI, cid,
|
||||||
getEncryptKey(), RES_FILE_NAME);
|
getEncryptKey(), RES_FILE_NAME);
|
||||||
return (cachePath == null) ? PackageManager.INSTALL_FAILED_CONTAINER_ERROR :
|
if (newCachePath != null) {
|
||||||
PackageManager.INSTALL_SUCCEEDED;
|
setCachePath(newCachePath);
|
||||||
|
return PackageManager.INSTALL_SUCCEEDED;
|
||||||
|
} else {
|
||||||
|
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getCodePath() {
|
String getCodePath() {
|
||||||
return cachePath + "/" + RES_FILE_NAME;
|
return packagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
String getResourcePath() {
|
String getResourcePath() {
|
||||||
return cachePath + "/" + RES_FILE_NAME;
|
return packagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getNativeLibraryPath() {
|
||||||
|
return libraryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
int doPreInstall(int status) {
|
int doPreInstall(int status) {
|
||||||
@ -5426,8 +5224,11 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
} else {
|
} else {
|
||||||
boolean mounted = PackageHelper.isContainerMounted(cid);
|
boolean mounted = PackageHelper.isContainerMounted(cid);
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
cachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), Process.SYSTEM_UID);
|
String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(),
|
||||||
if (cachePath == null) {
|
Process.SYSTEM_UID);
|
||||||
|
if (newCachePath != null) {
|
||||||
|
setCachePath(newCachePath);
|
||||||
|
} else {
|
||||||
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5473,13 +5274,19 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Succesfully renamed " + cid +
|
Log.i(TAG, "Succesfully renamed " + cid +
|
||||||
" at path: " + cachePath + " to " + newCacheId +
|
" to " + newCacheId +
|
||||||
" at new path: " + newCachePath);
|
" at new path: " + newCachePath);
|
||||||
cid = newCacheId;
|
cid = newCacheId;
|
||||||
cachePath = newCachePath;
|
setCachePath(newCachePath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setCachePath(String newCachePath) {
|
||||||
|
File cachePath = new File(newCachePath);
|
||||||
|
libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
|
||||||
|
packagePath = new File(cachePath, RES_FILE_NAME).getPath();
|
||||||
|
}
|
||||||
|
|
||||||
int doPostInstall(int status) {
|
int doPostInstall(int status) {
|
||||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||||
cleanUp();
|
cleanUp();
|
||||||
@ -5695,7 +5502,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
|
boolean sysPkg = (isSystemApp(oldPackage));
|
||||||
if (sysPkg) {
|
if (sysPkg) {
|
||||||
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
|
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
|
||||||
} else {
|
} else {
|
||||||
@ -5855,7 +5662,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
!ps.codePathString.equals(oldPkgSetting.codePathString)) {
|
!ps.codePathString.equals(oldPkgSetting.codePathString)) {
|
||||||
int installFlags = 0;
|
int installFlags = 0;
|
||||||
res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
|
res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
|
||||||
oldPkgSetting.resourcePathString);
|
oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6006,6 +5813,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
// Set application objects path explicitly after the rename
|
// Set application objects path explicitly after the rename
|
||||||
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
|
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
|
||||||
|
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
|
||||||
if (replace) {
|
if (replace) {
|
||||||
replacePackageLI(pkg, parseFlags, scanMode,
|
replacePackageLI(pkg, parseFlags, scanMode,
|
||||||
installerPackageName, res);
|
installerPackageName, res);
|
||||||
@ -6020,8 +5828,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
int retCode = 0;
|
int retCode = 0;
|
||||||
// TODO Gross hack but fix later. Ideally move this to be a post installation
|
// TODO Gross hack but fix later. Ideally move this to be a post installation
|
||||||
// check after alloting uid.
|
// check after alloting uid.
|
||||||
if ((newPackage.applicationInfo.flags
|
if (isForwardLocked(newPackage)) {
|
||||||
& ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
|
|
||||||
File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
|
File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir);
|
||||||
try {
|
try {
|
||||||
extractPublicFiles(newPackage, destResourceFile);
|
extractPublicFiles(newPackage, destResourceFile);
|
||||||
@ -6056,12 +5863,20 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return PackageManager.INSTALL_SUCCEEDED;
|
return PackageManager.INSTALL_SUCCEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isForwardLocked(PackageParser.Package pkg) {
|
private static boolean isForwardLocked(PackageParser.Package pkg) {
|
||||||
return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
|
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExternal(PackageParser.Package pkg) {
|
private static boolean isExternal(PackageParser.Package pkg) {
|
||||||
return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
|
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isSystemApp(PackageParser.Package pkg) {
|
||||||
|
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
|
||||||
|
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractPublicFiles(PackageParser.Package newPackage,
|
private void extractPublicFiles(PackageParser.Package newPackage,
|
||||||
@ -6291,7 +6106,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
// we don't consider this to be a failure of the core package deletion
|
// we don't consider this to be a failure of the core package deletion
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//for emulator
|
// for simulator
|
||||||
PackageParser.Package pkg = mPackages.get(packageName);
|
PackageParser.Package pkg = mPackages.get(packageName);
|
||||||
File dataDir = new File(pkg.applicationInfo.dataDir);
|
File dataDir = new File(pkg.applicationInfo.dataDir);
|
||||||
dataDir.delete();
|
dataDir.delete();
|
||||||
@ -6374,7 +6189,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
// Reinstate the old system package
|
// Reinstate the old system package
|
||||||
mSettings.enableSystemPackageLP(p.packageName);
|
mSettings.enableSystemPackageLP(p.packageName);
|
||||||
// Remove any native libraries.
|
// Remove any native libraries. XXX needed?
|
||||||
removeNativeBinariesLI(p);
|
removeNativeBinariesLI(p);
|
||||||
}
|
}
|
||||||
// Install the system package
|
// Install the system package
|
||||||
@ -6410,12 +6225,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
// Delete application code and resources
|
// Delete application code and resources
|
||||||
if (deleteCodeAndResources) {
|
if (deleteCodeAndResources) {
|
||||||
// TODO can pick up from PackageSettings as well
|
// TODO can pick up from PackageSettings as well
|
||||||
int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ?
|
int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0;
|
||||||
PackageManager.INSTALL_EXTERNAL : 0;
|
installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
|
||||||
installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
|
outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir,
|
||||||
PackageManager.INSTALL_FORWARD_LOCK : 0;
|
applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir);
|
||||||
outInfo.args = createInstallArgs(installFlags,
|
|
||||||
applicationInfo.sourceDir, applicationInfo.publicSourceDir);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -6460,7 +6273,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean ret = false;
|
boolean ret = false;
|
||||||
if ( (p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
|
if (isSystemApp(p)) {
|
||||||
Log.i(TAG, "Removing system package:"+p.packageName);
|
Log.i(TAG, "Removing system package:"+p.packageName);
|
||||||
// When an updated system application is deleted we delete the existing resources as well and
|
// When an updated system application is deleted we delete the existing resources as well and
|
||||||
// fall back to existing code in system partition
|
// fall back to existing code in system partition
|
||||||
@ -7160,10 +6973,14 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
pw.print(" pkg="); pw.println(ps.pkg);
|
pw.print(" pkg="); pw.println(ps.pkg);
|
||||||
pw.print(" codePath="); pw.println(ps.codePathString);
|
pw.print(" codePath="); pw.println(ps.codePathString);
|
||||||
pw.print(" resourcePath="); pw.println(ps.resourcePathString);
|
pw.print(" resourcePath="); pw.println(ps.resourcePathString);
|
||||||
|
pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
|
||||||
pw.print(" obbPath="); pw.println(ps.obbPathString);
|
pw.print(" obbPath="); pw.println(ps.obbPathString);
|
||||||
if (ps.pkg != null) {
|
if (ps.pkg != null) {
|
||||||
pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
|
pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
|
||||||
pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
|
pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
|
||||||
|
if (ps.pkg.mOperationPending) {
|
||||||
|
pw.println(" mOperationPending=true");
|
||||||
|
}
|
||||||
pw.print(" supportsScreens=[");
|
pw.print(" supportsScreens=[");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
if ((ps.pkg.applicationInfo.flags &
|
if ((ps.pkg.applicationInfo.flags &
|
||||||
@ -7211,9 +7028,6 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
|
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
|
||||||
pw.print(" installStatus="); pw.print(ps.installStatus);
|
pw.print(" installStatus="); pw.print(ps.installStatus);
|
||||||
pw.print(" enabled="); pw.println(ps.enabled);
|
pw.print(" enabled="); pw.println(ps.enabled);
|
||||||
if (ps.pkg.mOperationPending) {
|
|
||||||
pw.println(" mOperationPending=true");
|
|
||||||
}
|
|
||||||
if (ps.disabledComponents.size() > 0) {
|
if (ps.disabledComponents.size() > 0) {
|
||||||
pw.println(" disabledComponents:");
|
pw.println(" disabledComponents:");
|
||||||
for (String s : ps.disabledComponents) {
|
for (String s : ps.disabledComponents) {
|
||||||
@ -7730,6 +7544,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
String codePathString;
|
String codePathString;
|
||||||
File resourcePath;
|
File resourcePath;
|
||||||
String resourcePathString;
|
String resourcePathString;
|
||||||
|
String nativeLibraryPathString;
|
||||||
String obbPathString;
|
String obbPathString;
|
||||||
private long timeStamp;
|
private long timeStamp;
|
||||||
private String timeStampString = "0";
|
private String timeStampString = "0";
|
||||||
@ -8282,8 +8097,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
|
private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) {
|
||||||
p.pkg = pkg;
|
p.pkg = pkg;
|
||||||
pkg.mSetEnabled = p.enabled;
|
pkg.mSetEnabled = p.enabled;
|
||||||
String codePath = pkg.applicationInfo.sourceDir;
|
final String codePath = pkg.applicationInfo.sourceDir;
|
||||||
String resourcePath = pkg.applicationInfo.publicSourceDir;
|
final String resourcePath = pkg.applicationInfo.publicSourceDir;
|
||||||
// Update code path if needed
|
// Update code path if needed
|
||||||
if (!codePath.equalsIgnoreCase(p.codePathString)) {
|
if (!codePath.equalsIgnoreCase(p.codePathString)) {
|
||||||
Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
|
Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName +
|
||||||
@ -8298,6 +8113,12 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
p.resourcePath = new File(resourcePath);
|
p.resourcePath = new File(resourcePath);
|
||||||
p.resourcePathString = resourcePath;
|
p.resourcePathString = resourcePath;
|
||||||
}
|
}
|
||||||
|
// Update the native library path if needed
|
||||||
|
final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir;
|
||||||
|
if (nativeLibraryPath != null
|
||||||
|
&& !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
|
||||||
|
p.nativeLibraryPathString = nativeLibraryPath;
|
||||||
|
}
|
||||||
// Update version code if needed
|
// Update version code if needed
|
||||||
if (pkg.mVersionCode != p.versionCode) {
|
if (pkg.mVersionCode != p.versionCode) {
|
||||||
p.versionCode = pkg.mVersionCode;
|
p.versionCode = pkg.mVersionCode;
|
||||||
@ -8668,6 +8489,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
||||||
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
||||||
}
|
}
|
||||||
|
if (pkg.nativeLibraryPathString != null) {
|
||||||
|
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
|
||||||
|
}
|
||||||
if (pkg.sharedUser == null) {
|
if (pkg.sharedUser == null) {
|
||||||
serializer.attribute(null, "userId",
|
serializer.attribute(null, "userId",
|
||||||
Integer.toString(pkg.userId));
|
Integer.toString(pkg.userId));
|
||||||
@ -8707,6 +8531,9 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
||||||
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
||||||
}
|
}
|
||||||
|
if (pkg.nativeLibraryPathString != null) {
|
||||||
|
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
|
||||||
|
}
|
||||||
serializer.attribute(null, "flags",
|
serializer.attribute(null, "flags",
|
||||||
Integer.toString(pkg.pkgFlags));
|
Integer.toString(pkg.pkgFlags));
|
||||||
serializer.attribute(null, "ts", pkg.getTimeStampStr());
|
serializer.attribute(null, "ts", pkg.getTimeStampStr());
|
||||||
@ -9111,6 +8938,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
String sharedIdStr = null;
|
String sharedIdStr = null;
|
||||||
String codePathStr = null;
|
String codePathStr = null;
|
||||||
String resourcePathStr = null;
|
String resourcePathStr = null;
|
||||||
|
String nativeLibraryPathStr = null;
|
||||||
String obbPathStr = null;
|
String obbPathStr = null;
|
||||||
String systemStr = null;
|
String systemStr = null;
|
||||||
String installerPackageName = null;
|
String installerPackageName = null;
|
||||||
@ -9129,6 +8957,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
|
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
|
||||||
codePathStr = parser.getAttributeValue(null, "codePath");
|
codePathStr = parser.getAttributeValue(null, "codePath");
|
||||||
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
|
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
|
||||||
|
nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
|
||||||
obbPathStr = parser.getAttributeValue(null, "obbPath");
|
obbPathStr = parser.getAttributeValue(null, "obbPath");
|
||||||
version = parser.getAttributeValue(null, "version");
|
version = parser.getAttributeValue(null, "version");
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
@ -9227,6 +9056,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
if (packageSetting != null) {
|
if (packageSetting != null) {
|
||||||
packageSetting.uidError = "true".equals(uidError);
|
packageSetting.uidError = "true".equals(uidError);
|
||||||
packageSetting.installerPackageName = installerPackageName;
|
packageSetting.installerPackageName = installerPackageName;
|
||||||
|
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
|
||||||
packageSetting.obbPathString = obbPathStr;
|
packageSetting.obbPathString = obbPathStr;
|
||||||
final String enabledStr = parser.getAttributeValue(null, "enabled");
|
final String enabledStr = parser.getAttributeValue(null, "enabled");
|
||||||
if (enabledStr != null) {
|
if (enabledStr != null) {
|
||||||
@ -9893,12 +9723,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
|
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
|
||||||
} else {
|
} else {
|
||||||
// Disable moving fwd locked apps and system packages
|
// Disable moving fwd locked apps and system packages
|
||||||
if (pkg.applicationInfo != null &&
|
if (pkg.applicationInfo != null && isSystemApp(pkg)) {
|
||||||
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
|
|
||||||
Slog.w(TAG, "Cannot move system application");
|
Slog.w(TAG, "Cannot move system application");
|
||||||
returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
|
returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
|
||||||
} else if (pkg.applicationInfo != null &&
|
} else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
|
||||||
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) {
|
|
||||||
Slog.w(TAG, "Cannot move forward locked app.");
|
Slog.w(TAG, "Cannot move forward locked app.");
|
||||||
returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
|
returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
|
||||||
} else if (pkg.mOperationPending) {
|
} else if (pkg.mOperationPending) {
|
||||||
@ -9913,8 +9741,8 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
} else {
|
} else {
|
||||||
newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
|
newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
|
||||||
PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
|
PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
|
||||||
currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
|
currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL
|
||||||
PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL;
|
: PackageManager.INSTALL_INTERNAL;
|
||||||
if (newFlags == currFlags) {
|
if (newFlags == currFlags) {
|
||||||
Slog.w(TAG, "No move required. Trying to move to same location");
|
Slog.w(TAG, "No move required. Trying to move to same location");
|
||||||
returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
|
returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION;
|
||||||
@ -9926,13 +9754,13 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
|
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
|
||||||
processPendingMove(new MoveParams(null, observer, 0, packageName), returnCode);
|
processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
|
||||||
} else {
|
} else {
|
||||||
Message msg = mHandler.obtainMessage(INIT_COPY);
|
Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||||
InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
|
InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
|
||||||
pkg.applicationInfo.publicSourceDir);
|
pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
|
||||||
MoveParams mp = new MoveParams(srcArgs, observer, newFlags,
|
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
|
||||||
packageName);
|
pkg.applicationInfo.dataDir);
|
||||||
msg.obj = mp;
|
msg.obj = mp;
|
||||||
mHandler.sendMessage(msg);
|
mHandler.sendMessage(msg);
|
||||||
}
|
}
|
||||||
@ -9950,7 +9778,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
ArrayList<String> pkgList = null;
|
ArrayList<String> pkgList = null;
|
||||||
synchronized (mPackages) {
|
synchronized (mPackages) {
|
||||||
PackageParser.Package pkg = mPackages.get(mp.packageName);
|
PackageParser.Package pkg = mPackages.get(mp.packageName);
|
||||||
if (pkg == null ) {
|
if (pkg == null) {
|
||||||
Slog.w(TAG, " Package " + mp.packageName +
|
Slog.w(TAG, " Package " + mp.packageName +
|
||||||
" doesn't exist. Aborting move");
|
" doesn't exist. Aborting move");
|
||||||
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
|
returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST;
|
||||||
@ -9983,9 +9811,10 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
" Aborting move and returning error");
|
" Aborting move and returning error");
|
||||||
returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
|
returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
String oldCodePath = pkg.mPath;
|
final String oldCodePath = pkg.mPath;
|
||||||
String newCodePath = mp.targetArgs.getCodePath();
|
final String newCodePath = mp.targetArgs.getCodePath();
|
||||||
String newResPath = mp.targetArgs.getResourcePath();
|
final String newResPath = mp.targetArgs.getResourcePath();
|
||||||
|
final String newNativePath = mp.targetArgs.getNativeLibraryPath();
|
||||||
pkg.mPath = newCodePath;
|
pkg.mPath = newCodePath;
|
||||||
// Move dex files around
|
// Move dex files around
|
||||||
if (moveDexFilesLI(pkg)
|
if (moveDexFilesLI(pkg)
|
||||||
@ -9998,6 +9827,7 @@ class PackageManagerService extends IPackageManager.Stub {
|
|||||||
pkg.mScanPath = newCodePath;
|
pkg.mScanPath = newCodePath;
|
||||||
pkg.applicationInfo.sourceDir = newCodePath;
|
pkg.applicationInfo.sourceDir = newCodePath;
|
||||||
pkg.applicationInfo.publicSourceDir = newResPath;
|
pkg.applicationInfo.publicSourceDir = newResPath;
|
||||||
|
pkg.applicationInfo.nativeLibraryDir = newNativePath;
|
||||||
PackageSetting ps = (PackageSetting) pkg.mExtras;
|
PackageSetting ps = (PackageSetting) pkg.mExtras;
|
||||||
ps.codePath = new File(pkg.applicationInfo.sourceDir);
|
ps.codePath = new File(pkg.applicationInfo.sourceDir);
|
||||||
ps.codePathString = ps.codePath.getPath();
|
ps.codePathString = ps.codePath.getPath();
|
||||||
|
Reference in New Issue
Block a user