Multi-arch application installs.
Each application now has two ABIs, the primary and the secondary. The app is always launched with the primary, but the secondary might be used by other apps that load the given applications code. This implies we must: - dex2oat the app both ways. - extract shared libraries for both abis. The former is relatively straightforward but the latter requires us to change the layout for shared libs that we unpack from applications. The bulk of this change deals with the latter. This change continues to fill in nativeLibraryPath during scans for backwards compatibility. This will be removed in a future patch. Change-Id: Ia943dd11ef815c5cbfc60f17929eaa2a652a385a
This commit is contained in:
@ -491,13 +491,55 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
public String nativeLibraryDir;
|
||||
|
||||
/**
|
||||
* The ABI that this application requires, This is inferred from the ABIs
|
||||
* The path under the apps data directory we store unpacked libraries. For
|
||||
* new installs, we create subdirectories under legacyNativeLibraryDir that are
|
||||
* architecture specific. For legacy installs, the shared libraries are
|
||||
* placed directly under this path.
|
||||
*
|
||||
* For "legacy" installs {@code nativeLibraryDir} will be equal to this path.
|
||||
* For newer installs, it will be derived based on the codePath and the primary
|
||||
* cpu abi.
|
||||
*
|
||||
* @hide.
|
||||
*/
|
||||
public String legacyNativeLibraryDir;
|
||||
|
||||
/**
|
||||
* The primary ABI that this application requires, This is inferred from the ABIs
|
||||
* of the native JNI libraries the application bundles. Will be {@code null}
|
||||
* if this application does not require any particular ABI.
|
||||
*
|
||||
* If non-null, the application will always be launched with this ABI.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String cpuAbi;
|
||||
public String primaryCpuAbi;
|
||||
|
||||
/**
|
||||
* The secondary ABI for this application. Might be non-null for multi-arch
|
||||
* installs. The application itself never uses this ABI, but other applications that
|
||||
* use its code might.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String secondaryCpuAbi;
|
||||
|
||||
/**
|
||||
* The derived APK "root" for the given package. Will be non-null for bundled and
|
||||
* updated system apps. This will be a top level path under which apks and libraries
|
||||
* are installed, for eg. {@code /system}, {@code /oem} or {@code /vendor}. This is
|
||||
* used to calculate the location of native code for a given package, for e.g
|
||||
* {@code /vendor/lib} or {@code /vendor/lib64}.
|
||||
*
|
||||
* For app updates or fresh app installs, this will be {@code null} and we will use
|
||||
* {@code legacyNativeLibraryDir}
|
||||
*
|
||||
* NOTE: This can be removed if we have a unified layout for bundled and installed
|
||||
* apps.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String apkRoot;
|
||||
|
||||
/**
|
||||
* The kernel user-ID that has been assigned to this application;
|
||||
@ -641,7 +683,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
splitSourceDirs = orig.splitSourceDirs;
|
||||
splitPublicSourceDirs = orig.splitPublicSourceDirs;
|
||||
nativeLibraryDir = orig.nativeLibraryDir;
|
||||
cpuAbi = orig.cpuAbi;
|
||||
legacyNativeLibraryDir = orig.legacyNativeLibraryDir;
|
||||
primaryCpuAbi = orig.primaryCpuAbi;
|
||||
secondaryCpuAbi = orig.secondaryCpuAbi;
|
||||
apkRoot = orig.apkRoot;
|
||||
resourceDirs = orig.resourceDirs;
|
||||
seinfo = orig.seinfo;
|
||||
sharedLibraryFiles = orig.sharedLibraryFiles;
|
||||
@ -685,7 +730,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
dest.writeStringArray(splitSourceDirs);
|
||||
dest.writeStringArray(splitPublicSourceDirs);
|
||||
dest.writeString(nativeLibraryDir);
|
||||
dest.writeString(cpuAbi);
|
||||
dest.writeString(legacyNativeLibraryDir);
|
||||
dest.writeString(primaryCpuAbi);
|
||||
dest.writeString(secondaryCpuAbi);
|
||||
dest.writeString(apkRoot);
|
||||
dest.writeStringArray(resourceDirs);
|
||||
dest.writeString(seinfo);
|
||||
dest.writeStringArray(sharedLibraryFiles);
|
||||
@ -728,7 +776,10 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
splitSourceDirs = source.readStringArray();
|
||||
splitPublicSourceDirs = source.readStringArray();
|
||||
nativeLibraryDir = source.readString();
|
||||
cpuAbi = source.readString();
|
||||
legacyNativeLibraryDir = source.readString();
|
||||
primaryCpuAbi = source.readString();
|
||||
secondaryCpuAbi = source.readString();
|
||||
apkRoot = source.readString();
|
||||
resourceDirs = source.readStringArray();
|
||||
seinfo = source.readString();
|
||||
sharedLibraryFiles = source.readStringArray();
|
||||
|
@ -36,6 +36,13 @@ public class PackageInfoLite implements Parcelable {
|
||||
*/
|
||||
public int versionCode;
|
||||
|
||||
/**
|
||||
* The android:multiArch flag from the package manifest. If set,
|
||||
* we will extract all native libraries for the given app, not just those
|
||||
* from the preferred ABI.
|
||||
*/
|
||||
public boolean multiArch;
|
||||
|
||||
/**
|
||||
* Specifies the recommended install location. Can be one of
|
||||
* {@link #PackageHelper.RECOMMEND_INSTALL_INTERNAL} to install on internal storage
|
||||
|
@ -249,6 +249,8 @@ public class PackageParser {
|
||||
/** Paths of any split APKs, ordered by parsed splitName */
|
||||
public final String[] splitCodePaths;
|
||||
|
||||
public final boolean multiArch;
|
||||
|
||||
private PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
|
||||
String[] splitCodePaths) {
|
||||
this.packageName = baseApk.packageName;
|
||||
@ -259,6 +261,7 @@ public class PackageParser {
|
||||
this.codePath = codePath;
|
||||
this.baseCodePath = baseApk.codePath;
|
||||
this.splitCodePaths = splitCodePaths;
|
||||
this.multiArch = baseApk.multiArch;
|
||||
}
|
||||
|
||||
public List<String> getAllCodePaths() {
|
||||
@ -282,9 +285,11 @@ public class PackageParser {
|
||||
public final int installLocation;
|
||||
public final VerifierInfo[] verifiers;
|
||||
public final Signature[] signatures;
|
||||
public final boolean multiArch;
|
||||
|
||||
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
|
||||
int installLocation, List<VerifierInfo> verifiers, Signature[] signatures) {
|
||||
int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
|
||||
boolean multiArch) {
|
||||
this.codePath = codePath;
|
||||
this.packageName = packageName;
|
||||
this.splitName = splitName;
|
||||
@ -292,6 +297,7 @@ public class PackageParser {
|
||||
this.installLocation = installLocation;
|
||||
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
|
||||
this.signatures = signatures;
|
||||
this.multiArch = multiArch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1114,6 +1120,7 @@ public class PackageParser {
|
||||
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
|
||||
int versionCode = 0;
|
||||
int numFound = 0;
|
||||
boolean multiArch = false;
|
||||
for (int i = 0; i < attrs.getAttributeCount(); i++) {
|
||||
String attr = attrs.getAttributeName(i);
|
||||
if (attr.equals("installLocation")) {
|
||||
@ -1123,8 +1130,11 @@ public class PackageParser {
|
||||
} else if (attr.equals("versionCode")) {
|
||||
versionCode = attrs.getAttributeIntValue(i, 0);
|
||||
numFound++;
|
||||
} else if (attr.equals("multiArch")) {
|
||||
multiArch = attrs.getAttributeBooleanValue(i, false);
|
||||
numFound++;
|
||||
}
|
||||
if (numFound >= 2) {
|
||||
if (numFound >= 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1149,7 +1159,7 @@ public class PackageParser {
|
||||
}
|
||||
|
||||
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
|
||||
installLocation, verifiers, signatures);
|
||||
installLocation, verifiers, signatures, multiArch);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,10 +131,15 @@ public class NativeLibraryHelper {
|
||||
*
|
||||
* @return size of all native binary files in bytes
|
||||
*/
|
||||
public static long sumNativeBinariesLI(Handle handle, String abi) {
|
||||
public static long sumNativeBinariesLI(Handle handle, String[] abis) {
|
||||
long sum = 0;
|
||||
for (long apkHandle : handle.apkHandles) {
|
||||
sum += nativeSumNativeBinaries(apkHandle, abi);
|
||||
// NOTE: For a given APK handle, we parse the central directory precisely
|
||||
// once, but prefix matching of entries requires a CD traversal, which can
|
||||
// take a while (even if it needs no additional I/O).
|
||||
for (String abi : abis) {
|
||||
sum += nativeSumNativeBinaries(apkHandle, abi);
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
@ -196,45 +201,47 @@ public class NativeLibraryHelper {
|
||||
private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
|
||||
|
||||
// Convenience method to call removeNativeBinariesFromDirLI(File)
|
||||
public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
|
||||
if (nativeLibraryPath == null) return false;
|
||||
return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));
|
||||
public static void removeNativeBinariesLI(String nativeLibraryPath) {
|
||||
if (nativeLibraryPath == null) return;
|
||||
removeNativeBinariesFromDirLI(new File(nativeLibraryPath), false /* delete root dir */);
|
||||
}
|
||||
|
||||
// Remove the native binaries of a given package. This simply
|
||||
// gets rid of the files in the 'lib' sub-directory.
|
||||
public static boolean removeNativeBinariesFromDirLI(File nativeLibraryDir) {
|
||||
/**
|
||||
* Remove the native binaries of a given package. This deletes the files
|
||||
*/
|
||||
public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, boolean deleteRootDir) {
|
||||
if (DEBUG_NATIVE) {
|
||||
Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryDir.getPath());
|
||||
Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
|
||||
}
|
||||
|
||||
boolean deletedFiles = false;
|
||||
|
||||
/*
|
||||
* Just remove any file in the directory. Since the directory is owned
|
||||
* by the 'system' UID, the application is not supposed to have written
|
||||
* anything there.
|
||||
*/
|
||||
if (nativeLibraryDir.exists()) {
|
||||
final File[] binaries = nativeLibraryDir.listFiles();
|
||||
if (binaries != null) {
|
||||
for (int nn = 0; nn < binaries.length; nn++) {
|
||||
if (nativeLibraryRoot.exists()) {
|
||||
final File[] files = nativeLibraryRoot.listFiles();
|
||||
if (files != null) {
|
||||
for (int nn = 0; nn < files.length; nn++) {
|
||||
if (DEBUG_NATIVE) {
|
||||
Slog.d(TAG, " Deleting " + binaries[nn].getName());
|
||||
Slog.d(TAG, " Deleting " + files[nn].getName());
|
||||
}
|
||||
|
||||
if (!binaries[nn].delete()) {
|
||||
Slog.w(TAG, "Could not delete native binary: " + binaries[nn].getPath());
|
||||
} else {
|
||||
deletedFiles = true;
|
||||
if (files[nn].isDirectory()) {
|
||||
removeNativeBinariesFromDirLI(files[nn], true /* delete root dir */);
|
||||
} else if (!files[nn].delete()) {
|
||||
Slog.w(TAG, "Could not delete native binary: " + files[nn].getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do not delete 'lib' directory itself, or this will prevent
|
||||
// installation of future updates.
|
||||
// Do not delete 'lib' directory itself, unless we're specifically
|
||||
// asked to or this will prevent installation of future updates.
|
||||
if (deleteRootDir) {
|
||||
if (!nativeLibraryRoot.delete()) {
|
||||
Slog.w(TAG, "Could not delete native binary directory: " + nativeLibraryRoot.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deletedFiles;
|
||||
}
|
||||
|
||||
// We don't care about the other return values for now.
|
||||
|
@ -50,6 +50,7 @@ import com.android.internal.content.PackageHelper;
|
||||
import com.android.internal.os.IParcelFileDescriptorFactory;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
import libcore.io.IoUtils;
|
||||
import libcore.io.Streams;
|
||||
|
||||
@ -186,6 +187,7 @@ public class DefaultContainerService extends IntentService {
|
||||
ret.verifiers = pkg.verifiers;
|
||||
ret.recommendedInstallLocation = recommendAppInstallLocation(pkg, flags, threshold,
|
||||
abiOverride);
|
||||
ret.multiArch = pkg.multiArch;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -363,31 +365,26 @@ public class DefaultContainerService extends IntentService {
|
||||
final String resFileName = "pkg.apk";
|
||||
final String publicResFileName = "res.zip";
|
||||
|
||||
// The .apk file
|
||||
String codePath = pkg.baseCodePath;
|
||||
File codeFile = new File(codePath);
|
||||
|
||||
String[] abiList = Build.SUPPORTED_ABIS;
|
||||
if (abiOverride != null) {
|
||||
abiList = new String[] { abiOverride };
|
||||
} else {
|
||||
try {
|
||||
if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
|
||||
NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
|
||||
abiList = Build.SUPPORTED_32_BIT_ABIS;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Slog.w(TAG, "Problem determining ABI for: " + codeFile.getPath());
|
||||
return null;
|
||||
}
|
||||
if (pkg.multiArch) {
|
||||
// TODO: Support multiArch installs on ASEC.
|
||||
throw new IllegalArgumentException("multiArch not supported on ASEC installs.");
|
||||
}
|
||||
|
||||
final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList);
|
||||
// The .apk file
|
||||
final String codePath = pkg.baseCodePath;
|
||||
final File codeFile = new File(codePath);
|
||||
final String[] abis;
|
||||
try {
|
||||
abis = calculateAbiList(handle, abiOverride, pkg.multiArch);
|
||||
} catch (IOException ioe) {
|
||||
Slog.w(TAG, "Problem determining app ABIS: " + ioe);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Calculate size of container needed to hold base APK.
|
||||
final int sizeMb;
|
||||
try {
|
||||
sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abiIndex);
|
||||
sizeMb = calculateContainerSize(pkg, handle, isForwardLocked, abis);
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
|
||||
return null;
|
||||
@ -451,17 +448,18 @@ public class DefaultContainerService extends IntentService {
|
||||
final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
|
||||
if (sharedLibraryDir.mkdir()) {
|
||||
int ret = PackageManager.INSTALL_SUCCEEDED;
|
||||
if (abiIndex >= 0) {
|
||||
if (abis != null) {
|
||||
// TODO(multiArch): Support multi-arch installs on asecs. Note that we are NOT
|
||||
// using an ISA specific subdir here for now.
|
||||
final String abi = abis[0];
|
||||
ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
|
||||
sharedLibraryDir, abiList[abiIndex]);
|
||||
} else if (abiIndex != PackageManager.NO_NATIVE_LIBRARIES) {
|
||||
ret = abiIndex;
|
||||
}
|
||||
sharedLibraryDir, abi);
|
||||
|
||||
if (ret != PackageManager.INSTALL_SUCCEEDED) {
|
||||
Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
|
||||
PackageHelper.destroySdDir(newCid);
|
||||
return null;
|
||||
if (ret != PackageManager.INSTALL_SUCCEEDED) {
|
||||
Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
|
||||
PackageHelper.destroySdDir(newCid);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Slog.e(TAG, "Could not create native lib directory: " + sharedLibraryDir.getPath());
|
||||
@ -687,14 +685,53 @@ public class DefaultContainerService extends IntentService {
|
||||
NativeLibraryHelper.Handle handle = null;
|
||||
try {
|
||||
handle = NativeLibraryHelper.Handle.create(pkg);
|
||||
final int abi = NativeLibraryHelper.findSupportedAbi(handle,
|
||||
(abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
|
||||
return calculateContainerSize(pkg, handle, isForwardLocked, abi);
|
||||
return calculateContainerSize(pkg, handle, isForwardLocked,
|
||||
calculateAbiList(handle, abiOverride, pkg.multiArch));
|
||||
} finally {
|
||||
IoUtils.closeQuietly(handle);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] calculateAbiList(NativeLibraryHelper.Handle handle, String abiOverride,
|
||||
boolean isMultiArch) throws IOException {
|
||||
if (isMultiArch) {
|
||||
final int abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
|
||||
final int abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
|
||||
|
||||
if (abi32 >= 0 && abi64 >= 0) {
|
||||
return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64], Build.SUPPORTED_32_BIT_ABIS[abi32] };
|
||||
} else if (abi64 >= 0) {
|
||||
return new String[] { Build.SUPPORTED_64_BIT_ABIS[abi64] };
|
||||
} else if (abi32 >= 0) {
|
||||
return new String[] { Build.SUPPORTED_32_BIT_ABIS[abi32] };
|
||||
}
|
||||
|
||||
if (abi64 != PackageManager.NO_NATIVE_LIBRARIES || abi32 != PackageManager.NO_NATIVE_LIBRARIES) {
|
||||
throw new IOException("Error determining ABI list: errorCode=[" + abi32 + "," + abi64 + "]");
|
||||
}
|
||||
|
||||
} else {
|
||||
String[] abiList = Build.SUPPORTED_ABIS;
|
||||
if (abiOverride != null) {
|
||||
abiList = new String[] { abiOverride };
|
||||
} else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
|
||||
NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
|
||||
abiList = Build.SUPPORTED_32_BIT_ABIS;
|
||||
}
|
||||
|
||||
final int abi = NativeLibraryHelper.findSupportedAbi(handle,abiList);
|
||||
if (abi >= 0) {
|
||||
return new String[]{Build.SUPPORTED_ABIS[abi]};
|
||||
}
|
||||
|
||||
if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
|
||||
throw new IOException("Error determining ABI list: errorCode=" + abi);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the container size for a package.
|
||||
*
|
||||
@ -702,7 +739,7 @@ public class DefaultContainerService extends IntentService {
|
||||
* @throws IOException when there is a problem reading the file
|
||||
*/
|
||||
private int calculateContainerSize(PackageLite pkg, NativeLibraryHelper.Handle handle,
|
||||
boolean isForwardLocked, int abiIndex) throws IOException {
|
||||
boolean isForwardLocked, String[] abis) throws IOException {
|
||||
// Calculate size of container needed to hold APKs.
|
||||
long sizeBytes = 0;
|
||||
for (String codePath : pkg.getAllCodePaths()) {
|
||||
@ -715,9 +752,8 @@ public class DefaultContainerService extends IntentService {
|
||||
|
||||
// Check all the native files that need to be copied and add that to the
|
||||
// container size.
|
||||
if (abiIndex >= 0) {
|
||||
sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle,
|
||||
Build.SUPPORTED_ABIS[abiIndex]);
|
||||
if (abis != null) {
|
||||
sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(handle, abis);
|
||||
}
|
||||
|
||||
int sizeMb = (int) (sizeBytes >> 20);
|
||||
|
@ -2985,7 +2985,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
|
||||
}
|
||||
|
||||
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.cpuAbi;
|
||||
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
|
||||
if (requiredAbi == null) {
|
||||
requiredAbi = Build.SUPPORTED_ABIS[0];
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ public final class Installer extends SystemService {
|
||||
}
|
||||
|
||||
public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
|
||||
String fwdLockApkPath, String asecPath, String instructionSet, PackageStats pStats) {
|
||||
String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) {
|
||||
StringBuilder builder = new StringBuilder("getsize");
|
||||
builder.append(' ');
|
||||
builder.append(pkgName);
|
||||
@ -374,13 +374,17 @@ public final class Installer extends SystemService {
|
||||
builder.append(' ');
|
||||
builder.append(apkPath);
|
||||
builder.append(' ');
|
||||
// TODO: Extend getSizeInfo to look at the full subdirectory tree,
|
||||
// not just the first level.
|
||||
builder.append(libDirPath != null ? libDirPath : "!");
|
||||
builder.append(' ');
|
||||
builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
|
||||
builder.append(' ');
|
||||
builder.append(asecPath != null ? asecPath : "!");
|
||||
builder.append(' ');
|
||||
builder.append(instructionSet);
|
||||
// TODO: Extend getSizeInfo to look at *all* instrution sets, not
|
||||
// just the primary.
|
||||
builder.append(instructionSets[0]);
|
||||
|
||||
String s = transaction(builder.toString());
|
||||
String res[] = s.split(" ");
|
||||
@ -404,18 +408,17 @@ public final class Installer extends SystemService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Links the native library directory in an application's directory to its
|
||||
* real location.
|
||||
* Links the 32 bit native library directory in an application's data directory to the
|
||||
* real location for backward compatibility. Note that no such symlink is created for
|
||||
* 64 bit shared libraries.
|
||||
*
|
||||
* @param dataPath data directory where the application is
|
||||
* @param nativeLibPath target native library path
|
||||
* @return -1 on error
|
||||
*/
|
||||
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath, int userId) {
|
||||
public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) {
|
||||
if (dataPath == null) {
|
||||
Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
|
||||
return -1;
|
||||
} else if (nativeLibPath == null) {
|
||||
} else if (nativeLibPath32 == null) {
|
||||
Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
|
||||
return -1;
|
||||
}
|
||||
@ -423,7 +426,7 @@ public final class Installer extends SystemService {
|
||||
StringBuilder builder = new StringBuilder("linklib ");
|
||||
builder.append(dataPath);
|
||||
builder.append(' ');
|
||||
builder.append(nativeLibPath);
|
||||
builder.append(nativeLibPath32);
|
||||
builder.append(' ');
|
||||
builder.append(userId);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,10 @@ final class PackageSetting extends PackageSettingBase {
|
||||
SharedUserSetting sharedUser;
|
||||
|
||||
PackageSetting(String name, String realName, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String cpuAbiString, int pVersionCode, int pkgFlags) {
|
||||
super(name, realName, codePath, resourcePath, nativeLibraryPathString, cpuAbiString, pVersionCode,
|
||||
pkgFlags);
|
||||
String legacyNativeLibraryPathString, String primaryCpuAbiString,
|
||||
String secondaryCpuAbiString, int pVersionCode, int pkgFlags) {
|
||||
super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
|
||||
primaryCpuAbiString, secondaryCpuAbiString, pVersionCode, pkgFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,8 +55,16 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
String codePathString;
|
||||
File resourcePath;
|
||||
String resourcePathString;
|
||||
String nativeLibraryPathString;
|
||||
String cpuAbiString;
|
||||
|
||||
/**
|
||||
* The path under which native libraries for legacy apps are unpacked.
|
||||
* Will be set to {@code null} for newer installs, where the path can be
|
||||
* derived from {@link #codePath} unambiguously.
|
||||
*/
|
||||
String legacyNativeLibraryPathString;
|
||||
|
||||
String primaryCpuAbiString;
|
||||
String secondaryCpuAbiString;
|
||||
long timeStamp;
|
||||
long firstInstallTime;
|
||||
long lastUpdateTime;
|
||||
@ -84,11 +92,13 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
/* package name of the app that installed this package */
|
||||
String installerPackageName;
|
||||
PackageSettingBase(String name, String realName, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String cpuAbiString, int pVersionCode, int pkgFlags) {
|
||||
String legacyNativeLibraryPathString, String primaryCpuAbiString,
|
||||
String secondaryCpuAbiString, int pVersionCode, int pkgFlags) {
|
||||
super(pkgFlags);
|
||||
this.name = name;
|
||||
this.realName = realName;
|
||||
init(codePath, resourcePath, nativeLibraryPathString, cpuAbiString, pVersionCode);
|
||||
init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
|
||||
secondaryCpuAbiString, pVersionCode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,8 +114,9 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
codePathString = base.codePathString;
|
||||
resourcePath = base.resourcePath;
|
||||
resourcePathString = base.resourcePathString;
|
||||
nativeLibraryPathString = base.nativeLibraryPathString;
|
||||
cpuAbiString = base.cpuAbiString;
|
||||
legacyNativeLibraryPathString = base.legacyNativeLibraryPathString;
|
||||
primaryCpuAbiString = base.primaryCpuAbiString;
|
||||
secondaryCpuAbiString = base.secondaryCpuAbiString;
|
||||
timeStamp = base.timeStamp;
|
||||
firstInstallTime = base.firstInstallTime;
|
||||
lastUpdateTime = base.lastUpdateTime;
|
||||
@ -132,14 +143,15 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
|
||||
}
|
||||
|
||||
void init(File codePath, File resourcePath, String nativeLibraryPathString,
|
||||
String requiredCpuAbiString, int pVersionCode) {
|
||||
void init(File codePath, File resourcePath, String legacyNativeLibraryPathString,
|
||||
String primaryCpuAbiString, String secondaryCpuAbiString, int pVersionCode) {
|
||||
this.codePath = codePath;
|
||||
this.codePathString = codePath.toString();
|
||||
this.resourcePath = resourcePath;
|
||||
this.resourcePathString = resourcePath.toString();
|
||||
this.nativeLibraryPathString = nativeLibraryPathString;
|
||||
this.cpuAbiString = requiredCpuAbiString;
|
||||
this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
|
||||
this.primaryCpuAbiString = primaryCpuAbiString;
|
||||
this.secondaryCpuAbiString = secondaryCpuAbiString;
|
||||
this.versionCode = pVersionCode;
|
||||
}
|
||||
|
||||
@ -170,7 +182,8 @@ class PackageSettingBase extends GrantedPermissions {
|
||||
grantedPermissions = base.grantedPermissions;
|
||||
gids = base.gids;
|
||||
|
||||
cpuAbiString = base.cpuAbiString;
|
||||
primaryCpuAbiString = base.primaryCpuAbiString;
|
||||
secondaryCpuAbiString = base.secondaryCpuAbiString;
|
||||
timeStamp = base.timeStamp;
|
||||
firstInstallTime = base.firstInstallTime;
|
||||
lastUpdateTime = base.lastUpdateTime;
|
||||
|
@ -22,9 +22,10 @@ final class PendingPackage extends PackageSettingBase {
|
||||
final int sharedId;
|
||||
|
||||
PendingPackage(String name, String realName, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) {
|
||||
super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode,
|
||||
pkgFlags);
|
||||
String nativeLibrary32PathString, String nativeLibrary64PathString,
|
||||
String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) {
|
||||
super(name, realName, codePath, resourcePath, nativeLibrary32PathString, nativeLibrary64PathString,
|
||||
requiredCpuAbiString, pVersionCode, pkgFlags);
|
||||
this.sharedId = sharedId;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,13 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.FileUtils;
|
||||
import android.os.PatternMatcher;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.LogPrinter;
|
||||
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
@ -56,12 +62,6 @@ import android.content.pm.Signature;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.PackageUserState;
|
||||
import android.content.pm.VerifierDeviceIdentity;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@ -317,11 +317,12 @@ final class Settings {
|
||||
|
||||
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
|
||||
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String cpuAbiString, int pkgFlags, UserHandle user, boolean add) {
|
||||
String nativeLibraryRoot, String primaryCpuAbi, String secondaryCpuAbi, int pkgFlags,
|
||||
UserHandle user, boolean add) {
|
||||
final String name = pkg.packageName;
|
||||
PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
|
||||
resourcePath, nativeLibraryPathString, cpuAbiString, pkg.mVersionCode, pkgFlags,
|
||||
user, add, true /* allowInstall */);
|
||||
resourcePath, nativeLibraryRoot, primaryCpuAbi, secondaryCpuAbi,
|
||||
pkg.mVersionCode, pkgFlags, user, add, true /* allowInstall */);
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -407,7 +408,8 @@ final class Settings {
|
||||
p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||
}
|
||||
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
|
||||
p.nativeLibraryPathString, p.cpuAbiString, p.appId, p.versionCode, p.pkgFlags);
|
||||
p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
|
||||
p.secondaryCpuAbiString, p.appId, p.versionCode, p.pkgFlags);
|
||||
mDisabledSysPackages.remove(name);
|
||||
return ret;
|
||||
}
|
||||
@ -421,7 +423,8 @@ final class Settings {
|
||||
}
|
||||
|
||||
PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String cpuAbiString, int uid, int vc, int pkgFlags) {
|
||||
String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
|
||||
int uid, int vc, int pkgFlags) {
|
||||
PackageSetting p = mPackages.get(name);
|
||||
if (p != null) {
|
||||
if (p.appId == uid) {
|
||||
@ -431,8 +434,8 @@ final class Settings {
|
||||
"Adding duplicate package, keeping first: " + name);
|
||||
return null;
|
||||
}
|
||||
p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, cpuAbiString,
|
||||
vc, pkgFlags);
|
||||
p = new PackageSetting(name, realName, codePath, resourcePath,
|
||||
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
|
||||
p.appId = uid;
|
||||
if (addUserIdLPw(uid, p, name)) {
|
||||
mPackages.put(name, p);
|
||||
@ -500,11 +503,12 @@ final class Settings {
|
||||
|
||||
private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
|
||||
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
|
||||
String nativeLibraryPathString, String cpuAbiString, int vc, int pkgFlags,
|
||||
UserHandle installUser, boolean add, boolean allowInstall) {
|
||||
String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
|
||||
int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) {
|
||||
PackageSetting p = mPackages.get(name);
|
||||
if (p != null) {
|
||||
p.cpuAbiString = cpuAbiString;
|
||||
p.primaryCpuAbiString = primaryCpuAbiString;
|
||||
p.secondaryCpuAbiString = secondaryCpuAbiString;
|
||||
if (!p.codePath.equals(codePath)) {
|
||||
// Check to see if its a disabled system app
|
||||
if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
@ -524,7 +528,7 @@ final class Settings {
|
||||
* package settings since we might have moved from
|
||||
* internal to external storage or vice versa.
|
||||
*/
|
||||
p.nativeLibraryPathString = nativeLibraryPathString;
|
||||
p.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
|
||||
}
|
||||
}
|
||||
if (p.sharedUser != sharedUser) {
|
||||
@ -548,7 +552,7 @@ final class Settings {
|
||||
if (origPackage != null) {
|
||||
// We are consuming the data from an existing package.
|
||||
p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
|
||||
nativeLibraryPathString, cpuAbiString, vc, pkgFlags);
|
||||
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
|
||||
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
|
||||
+ name + " is adopting original package " + origPackage.name);
|
||||
// Note that we will retain the new package's signature so
|
||||
@ -565,7 +569,7 @@ final class Settings {
|
||||
p.setTimeStamp(codePath.lastModified());
|
||||
} else {
|
||||
p = new PackageSetting(name, realName, codePath, resourcePath,
|
||||
nativeLibraryPathString, cpuAbiString, vc, pkgFlags);
|
||||
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc, pkgFlags);
|
||||
p.setTimeStamp(codePath.lastModified());
|
||||
p.sharedUser = sharedUser;
|
||||
// If this is not a system app, it starts out stopped.
|
||||
@ -699,14 +703,15 @@ final class Settings {
|
||||
p.resourcePath = new File(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 the native library paths if needed
|
||||
final String nativeLibraryRoot = pkg.applicationInfo.legacyNativeLibraryDir;
|
||||
if (nativeLibraryRoot != null && !nativeLibraryRoot.equalsIgnoreCase(p.legacyNativeLibraryPathString)) {
|
||||
p.legacyNativeLibraryPathString = nativeLibraryRoot;
|
||||
}
|
||||
|
||||
// Update the required Cpu Abi
|
||||
p.cpuAbiString = pkg.applicationInfo.cpuAbi;
|
||||
p.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
|
||||
p.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
|
||||
// Update version code if needed
|
||||
if (pkg.mVersionCode != p.versionCode) {
|
||||
p.versionCode = pkg.mVersionCode;
|
||||
@ -1861,12 +1866,16 @@ final class Settings {
|
||||
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
||||
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
||||
}
|
||||
if (pkg.nativeLibraryPathString != null) {
|
||||
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
|
||||
if (pkg.legacyNativeLibraryPathString != null) {
|
||||
serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
|
||||
}
|
||||
if (pkg.cpuAbiString != null) {
|
||||
serializer.attribute(null, "requiredCpuAbi", pkg.cpuAbiString);
|
||||
if (pkg.primaryCpuAbiString != null) {
|
||||
serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);
|
||||
}
|
||||
if (pkg.secondaryCpuAbiString != null) {
|
||||
serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
|
||||
}
|
||||
|
||||
if (pkg.sharedUser == null) {
|
||||
serializer.attribute(null, "userId", Integer.toString(pkg.appId));
|
||||
} else {
|
||||
@ -1906,12 +1915,17 @@ final class Settings {
|
||||
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
|
||||
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
|
||||
}
|
||||
if (pkg.nativeLibraryPathString != null) {
|
||||
serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
|
||||
|
||||
if (pkg.legacyNativeLibraryPathString != null) {
|
||||
serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
|
||||
}
|
||||
if (pkg.cpuAbiString != null) {
|
||||
serializer.attribute(null, "requiredCpuAbi", pkg.cpuAbiString);
|
||||
if (pkg.primaryCpuAbiString != null) {
|
||||
serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);
|
||||
}
|
||||
if (pkg.secondaryCpuAbiString != null) {
|
||||
serializer.attribute(null, "secondaryCpuAbi", pkg.secondaryCpuAbiString);
|
||||
}
|
||||
|
||||
serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
|
||||
serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
|
||||
serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
|
||||
@ -2219,7 +2233,8 @@ final class Settings {
|
||||
if (idObj != null && idObj instanceof SharedUserSetting) {
|
||||
PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
|
||||
(SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
|
||||
pp.nativeLibraryPathString, pp.cpuAbiString, pp.versionCode, pp.pkgFlags,
|
||||
pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
|
||||
pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags,
|
||||
null, true /* add */, false /* allowInstall */);
|
||||
if (p == null) {
|
||||
PackageManagerService.reportSettingsProblem(Log.WARN,
|
||||
@ -2638,8 +2653,16 @@ final class Settings {
|
||||
String realName = parser.getAttributeValue(null, "realName");
|
||||
String codePathStr = parser.getAttributeValue(null, "codePath");
|
||||
String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
|
||||
String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
|
||||
String cpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
|
||||
|
||||
String legacyCpuAbiStr = parser.getAttributeValue(null, "requiredCpuAbi");
|
||||
String legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
|
||||
|
||||
String primaryCpuAbiStr = parser.getAttributeValue(null, "primaryCpuAbi");
|
||||
String secondaryCpuAbiStr = parser.getAttributeValue(null, "secondaryCpuAbi");
|
||||
|
||||
if (primaryCpuAbiStr == null && legacyCpuAbiStr != null) {
|
||||
primaryCpuAbiStr = legacyCpuAbiStr;
|
||||
}
|
||||
|
||||
if (resourcePathStr == null) {
|
||||
resourcePathStr = codePathStr;
|
||||
@ -2660,7 +2683,8 @@ final class Settings {
|
||||
pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
|
||||
}
|
||||
PackageSetting ps = new PackageSetting(name, realName, codePathFile,
|
||||
new File(resourcePathStr), nativeLibraryPathStr, cpuAbiString, versionCode, pkgFlags);
|
||||
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
|
||||
secondaryCpuAbiStr, versionCode, pkgFlags);
|
||||
String timeStampStr = parser.getAttributeValue(null, "ft");
|
||||
if (timeStampStr != null) {
|
||||
try {
|
||||
@ -2726,8 +2750,10 @@ final class Settings {
|
||||
String sharedIdStr = null;
|
||||
String codePathStr = null;
|
||||
String resourcePathStr = null;
|
||||
String nativeLibraryPathStr = null;
|
||||
String cpuAbiString = null;
|
||||
String legacyCpuAbiString = null;
|
||||
String legacyNativeLibraryPathStr = null;
|
||||
String primaryCpuAbiString = null;
|
||||
String secondaryCpuAbiString = null;
|
||||
String systemStr = null;
|
||||
String installerPackageName = null;
|
||||
String uidError = null;
|
||||
@ -2746,9 +2772,17 @@ final class Settings {
|
||||
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
|
||||
codePathStr = parser.getAttributeValue(null, "codePath");
|
||||
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
|
||||
nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
|
||||
cpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
|
||||
|
||||
legacyCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
|
||||
|
||||
legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
|
||||
primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi");
|
||||
secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi");
|
||||
|
||||
if (primaryCpuAbiString == null && legacyCpuAbiString != null) {
|
||||
primaryCpuAbiString = legacyCpuAbiString;
|
||||
}
|
||||
;
|
||||
version = parser.getAttributeValue(null, "version");
|
||||
if (version != null) {
|
||||
try {
|
||||
@ -2825,8 +2859,8 @@ final class Settings {
|
||||
+ parser.getPositionDescription());
|
||||
} else if (userId > 0) {
|
||||
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
|
||||
new File(resourcePathStr), nativeLibraryPathStr, cpuAbiString, userId, versionCode,
|
||||
pkgFlags);
|
||||
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
|
||||
secondaryCpuAbiString, userId, versionCode, pkgFlags);
|
||||
if (PackageManagerService.DEBUG_SETTINGS)
|
||||
Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
|
||||
+ userId + " pkg=" + packageSetting);
|
||||
@ -2843,8 +2877,8 @@ final class Settings {
|
||||
userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
|
||||
if (userId > 0) {
|
||||
packageSetting = new PendingPackage(name.intern(), realName, new File(
|
||||
codePathStr), new File(resourcePathStr), nativeLibraryPathStr, cpuAbiString, userId,
|
||||
versionCode, pkgFlags);
|
||||
codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
|
||||
primaryCpuAbiString, legacyCpuAbiString, userId, versionCode, pkgFlags);
|
||||
packageSetting.setTimeStamp(timeStamp);
|
||||
packageSetting.firstInstallTime = firstInstallTime;
|
||||
packageSetting.lastUpdateTime = lastUpdateTime;
|
||||
@ -2871,8 +2905,9 @@ final class Settings {
|
||||
if (packageSetting != null) {
|
||||
packageSetting.uidError = "true".equals(uidError);
|
||||
packageSetting.installerPackageName = installerPackageName;
|
||||
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
|
||||
packageSetting.cpuAbiString = cpuAbiString;
|
||||
packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
|
||||
packageSetting.primaryCpuAbiString = primaryCpuAbiString;
|
||||
packageSetting.secondaryCpuAbiString = secondaryCpuAbiString;
|
||||
// Handle legacy string here for single-user mode
|
||||
final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
|
||||
if (enabledStr != null) {
|
||||
@ -3417,8 +3452,9 @@ final class Settings {
|
||||
pw.print(prefix); pw.print(" pkg="); pw.println(ps.pkg);
|
||||
pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString);
|
||||
pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString);
|
||||
pw.print(prefix); pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
|
||||
pw.print(prefix); pw.print(" requiredCpuAbi="); pw.println(ps.cpuAbiString);
|
||||
pw.print(prefix); pw.print(" legacyNativeLibraryDir="); pw.println(ps.legacyNativeLibraryPathString);
|
||||
pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
|
||||
pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
|
||||
pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode);
|
||||
if (ps.pkg != null) {
|
||||
pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
|
||||
|
Reference in New Issue
Block a user