summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java/com/android/server')
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/Installer.java21
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java1023
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java35
-rw-r--r--services/core/java/com/android/server/pm/PendingPackage.java7
-rw-r--r--services/core/java/com/android/server/pm/Settings.java134
7 files changed, 732 insertions, 497 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 053fb5a..c7eabe8 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -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];
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 6ad2e60..1193968 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -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);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fe9ce8f..5c05f45 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -18,7 +18,6 @@ package com.android.server.pm;
import static android.Manifest.permission.GRANT_REVOKE_PERMISSIONS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
-import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
@@ -34,7 +33,6 @@ import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.EEXIST;
import static android.system.OsConstants.O_EXCL;
import static android.system.OsConstants.O_RDWR;
-import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.S_IRGRP;
import static android.system.OsConstants.S_IROTH;
import static android.system.OsConstants.S_IRWXU;
@@ -57,7 +55,6 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
@@ -67,14 +64,11 @@ import com.android.server.Watchdog;
import com.android.server.pm.Settings.DatabaseVersion;
import com.android.server.storage.DeviceStorageMonitorInternal;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
-import android.app.PackageInstallObserver;
import android.app.admin.IDevicePolicyManager;
import android.app.backup.IBackupManager;
import android.content.BroadcastReceiver;
@@ -149,7 +143,6 @@ import android.security.KeyStore;
import android.security.SystemKeyStore;
import android.system.ErrnoException;
import android.system.Os;
-import android.system.OsConstants;
import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -162,7 +155,6 @@ import android.util.PrintStreamPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.util.Xml;
import android.view.Display;
import java.io.BufferedInputStream;
@@ -172,7 +164,6 @@ import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
@@ -204,7 +195,6 @@ import dalvik.system.StaleDexCacheError;
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
/**
* Keep track of all those .apks everywhere.
@@ -233,6 +223,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_APP_DIR_OBSERVER = false;
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_DEXOPT = false;
+ private static final boolean DEBUG_ABI_SELECTION = false;
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
@@ -368,10 +359,10 @@ public class PackageManagerService extends IPackageManager.Stub {
final File mAppInstallDir;
/**
- * Directory to which applications installed internally have native
- * libraries copied.
+ * Directory to which applications installed internally have their
+ * 32 bit native libraries copied.
*/
- private File mAppLibInstallDir;
+ private File mAppLib32InstallDir;
// Directory containing the private parts (e.g. code and non-resource assets) of forward-locked
// apps.
@@ -1354,7 +1345,7 @@ public class PackageManagerService extends IPackageManager.Stub {
File dataDir = Environment.getDataDirectory();
mAppDataDir = new File(dataDir, "data");
mAppInstallDir = new File(dataDir, "app");
- mAppLibInstallDir = new File(dataDir, "app-lib");
+ mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
@@ -2089,7 +2080,8 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags = ps.pkgFlags | ApplicationInfo.FLAG_IS_DATA_ONLY;
pkg.applicationInfo.dataDir =
getDataPathForPackage(packageName, 0).getPath();
- pkg.applicationInfo.cpuAbi = ps.cpuAbiString;
+ pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString;
+ pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString;
}
return generatePackageInfo(pkg, flags, userId);
}
@@ -4269,8 +4261,8 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
- ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
- getAppInstructionSetFromSettings(ps));
+ ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
+ getAppDexInstructionSets(ps), isMultiArch(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4334,8 +4326,8 @@ public class PackageManagerService extends IPackageManager.Stub {
+ ps.codePathString + ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
- ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
- getAppInstructionSetFromSettings(ps));
+ ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
+ getAppDexInstructionSets(ps), isMultiArch(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4585,7 +4577,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mPackageUsage.write(true);
}
- private void performDexOptLibsLI(ArrayList<String> libs, String instructionSet,
+ private void performDexOptLibsLI(ArrayList<String> libs, String[] instructionSets,
boolean forceDex, boolean defer, HashSet<String> done) {
for (int i=0; i<libs.size(); i++) {
PackageParser.Package libPkg;
@@ -4600,7 +4592,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
if (libPkg != null && !done.contains(libName)) {
- performDexOptLI(libPkg, instructionSet, forceDex, defer, done);
+ performDexOptLI(libPkg, instructionSets, forceDex, defer, done);
}
}
}
@@ -4610,89 +4602,98 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int DEX_OPT_DEFERRED = 2;
static final int DEX_OPT_FAILED = -1;
- private int performDexOptLI(PackageParser.Package pkg, String instructionSetOverride,
+ private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
boolean forceDex, boolean defer, HashSet<String> done) {
- final String instructionSet = instructionSetOverride != null ?
- instructionSetOverride : getAppInstructionSet(pkg.applicationInfo);
+ final String[] instructionSets = targetInstructionSets != null ?
+ targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
if (done != null) {
done.add(pkg.packageName);
if (pkg.usesLibraries != null) {
- performDexOptLibsLI(pkg.usesLibraries, instructionSet, forceDex, defer, done);
+ performDexOptLibsLI(pkg.usesLibraries, instructionSets, forceDex, defer, done);
}
if (pkg.usesOptionalLibraries != null) {
- performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSet, forceDex, defer, done);
+ performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSets, forceDex, defer, done);
}
}
if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
final Collection<String> paths = pkg.getAllCodePaths();
for (String path : paths) {
- try {
- boolean isDexOptNeededInternal = DexFile.isDexOptNeededInternal(path,
- pkg.packageName, instructionSet, defer);
- // There are three basic cases here:
- // 1.) we need to dexopt, either because we are forced or it is needed
- // 2.) we are defering a needed dexopt
- // 3.) we are skipping an unneeded dexopt
- if (forceDex || (!defer && isDexOptNeededInternal)) {
- Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
- final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
- int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
- pkg.packageName, instructionSet);
- // Note that we ran dexopt, since rerunning will
- // probably just result in an error again.
- pkg.mDexOptNeeded = false;
- if (ret < 0) {
- return DEX_OPT_FAILED;
+ for (String instructionSet : instructionSets) {
+ try {
+ boolean isDexOptNeededInternal = DexFile.isDexOptNeededInternal(path,
+ pkg.packageName, instructionSet, defer);
+ // There are three basic cases here:
+ // 1.) we need to dexopt, either because we are forced or it is needed
+ // 2.) we are defering a needed dexopt
+ // 3.) we are skipping an unneeded dexopt
+ if (forceDex || (!defer && isDexOptNeededInternal)) {
+ Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
+ pkg.packageName, instructionSet);
+ // Note that we ran dexopt, since rerunning will
+ // probably just result in an error again.
+ pkg.mDexOptNeeded = false;
+ if (ret < 0) {
+ return DEX_OPT_FAILED;
+ }
+ return DEX_OPT_PERFORMED;
}
- return DEX_OPT_PERFORMED;
- }
- if (defer && isDexOptNeededInternal) {
- if (mDeferredDexOpt == null) {
- mDeferredDexOpt = new HashSet<PackageParser.Package>();
+ if (defer && isDexOptNeededInternal) {
+ if (mDeferredDexOpt == null) {
+ mDeferredDexOpt = new HashSet<PackageParser.Package>();
+ }
+ mDeferredDexOpt.add(pkg);
+ return DEX_OPT_DEFERRED;
}
- mDeferredDexOpt.add(pkg);
- return DEX_OPT_DEFERRED;
+ pkg.mDexOptNeeded = false;
+ return DEX_OPT_SKIPPED;
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Apk not found for dexopt: " + path);
+ return DEX_OPT_FAILED;
+ } catch (IOException e) {
+ Slog.w(TAG, "IOException reading apk: " + path, e);
+ return DEX_OPT_FAILED;
+ } catch (StaleDexCacheError e) {
+ Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
+ return DEX_OPT_FAILED;
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception when doing dexopt : ", e);
+ return DEX_OPT_FAILED;
}
- pkg.mDexOptNeeded = false;
- return DEX_OPT_SKIPPED;
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Apk not found for dexopt: " + path);
- return DEX_OPT_FAILED;
- } catch (IOException e) {
- Slog.w(TAG, "IOException reading apk: " + path, e);
- return DEX_OPT_FAILED;
- } catch (StaleDexCacheError e) {
- Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e);
- return DEX_OPT_FAILED;
- } catch (Exception e) {
- Slog.w(TAG, "Exception when doing dexopt : ", e);
- return DEX_OPT_FAILED;
}
}
}
return DEX_OPT_SKIPPED;
}
- private String getAppInstructionSet(ApplicationInfo info) {
- String instructionSet = getPreferredInstructionSet();
-
- if (info.cpuAbi != null) {
- instructionSet = VMRuntime.getInstructionSet(info.cpuAbi);
+ private static String[] getAppDexInstructionSets(ApplicationInfo info) {
+ if (info.primaryCpuAbi != null) {
+ if (info.secondaryCpuAbi != null) {
+ return new String[] {
+ VMRuntime.getInstructionSet(info.primaryCpuAbi),
+ VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
+ } else {
+ return new String[] {
+ VMRuntime.getInstructionSet(info.primaryCpuAbi) };
+ }
}
- return instructionSet;
+ return new String[] { getPreferredInstructionSet() };
}
- private String getAppInstructionSetFromSettings(PackageSetting ps) {
- String instructionSet = getPreferredInstructionSet();
-
- if (ps.cpuAbiString != null) {
- instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString);
+ private static String[] getAppDexInstructionSets(PackageSetting ps) {
+ if (ps.primaryCpuAbiString != null) {
+ if (ps.secondaryCpuAbiString != null) {
+ return new String[] { ps.primaryCpuAbiString, ps.secondaryCpuAbiString };
+ } else {
+ return new String[] { ps.primaryCpuAbiString };
+ }
}
- return instructionSet;
+ return new String[] { getPreferredInstructionSet() };
}
private static String getPreferredInstructionSet() {
@@ -4726,7 +4727,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
done = null;
}
- return performDexOptLI(pkg, null /* instruction set override */, forceDex, defer, done);
+ return performDexOptLI(pkg, null /* target instruction sets */, forceDex, defer, done);
}
private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
@@ -4790,12 +4791,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- final File nativeLibraryFile = new File(mAppLibInstallDir, packageName);
- NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
- if (!nativeLibraryFile.delete()) {
- Slog.w(TAG, "Couldn't delete native library directory " + nativeLibraryFile.getPath());
- }
-
return res;
}
@@ -4827,7 +4822,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Fix that up here.
if (isSystemApp(pkg)) {
PackageSetting ps = mSettings.mPackages.get(pkg.applicationInfo.packageName);
- setInternalAppNativeLibraryPath(pkg, ps);
+ setBundledAppAbisAndRoots(pkg, ps);
}
if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
@@ -5064,8 +5059,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// Just create the setting, don't add it yet. For already existing packages
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
- destResourceFile, pkg.applicationInfo.nativeLibraryDir,
- pkg.applicationInfo.cpuAbi,
+ destResourceFile, pkg.applicationInfo.legacyNativeLibraryDir,
+ pkg.applicationInfo.primaryCpuAbi,
+ pkg.applicationInfo.secondaryCpuAbi,
pkg.applicationInfo.flags, user, false);
if (pkgSetting == null) {
Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
@@ -5289,6 +5285,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ pkg.applicationInfo.uid + "/fs_"
+ currentUid;
pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
+ pkg.applicationInfo.legacyNativeLibraryDir = pkg.applicationInfo.dataDir;
String msg = "Package " + pkg.packageName
+ " has mismatched uid: "
+ currentUid + " on disk, "
@@ -5320,6 +5317,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
+ Slog.w(TAG, "Unable to create data dirs [errorCode=" + ret + "]");
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
@@ -5332,158 +5330,185 @@ public 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).
- *
- * This happens during an upgrade from a package settings file that
- * doesn't have a native library path attribute at all.
- */
- if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) {
- if (pkgSetting.nativeLibraryPathString == null) {
- setInternalAppNativeLibraryPath(pkg, pkgSetting);
- } else {
- pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
- }
- }
pkgSetting.uidError = uidError;
}
final String path = scanFile.getPath();
- /* Note: We don't want to unpack the native binaries for
- * system applications, unless they have been updated
- * (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
- * container already.
- *
- * In other words, we're going to unpack the binaries
- * only for non-system apps and system app upgrades.
- */
- if (pkg.applicationInfo.nativeLibraryDir != null) {
+ final String codePath = pkg.applicationInfo.getCodePath();
+ if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
+ // For the case where we had previously uninstalled an update, get rid
+ // of any native binaries we might have unpackaged. Note that this assumes
+ // that system app updates were not installed via ASEC.
+ //
+ // TODO(multiArch): Is this cleanup really necessary ?
+ NativeLibraryHelper.removeNativeBinariesFromDirLI(
+ new File(codePath, LIB_DIR_NAME), false /* delete dirs */);
+ setBundledAppAbisAndRoots(pkg, pkgSetting);
+ } else {
+ // TODO: We can probably be smarter about this stuff. For installed apps,
+ // we can calculate this information at install time once and for all. For
+ // system apps, we can probably assume that this information doesn't change
+ // after the first boot scan. As things stand, we do lots of unnecessary work.
+
+ final boolean isAsec = isForwardLocked(pkg) || isExternal(pkg);
+ final String nativeLibraryRootStr;
+ final boolean useIsaSpecificSubdirs;
+ if (pkg.applicationInfo.legacyNativeLibraryDir != null) {
+ nativeLibraryRootStr = pkg.applicationInfo.legacyNativeLibraryDir;
+ useIsaSpecificSubdirs = false;
+ } else {
+ nativeLibraryRootStr = new File(pkg.codePath, LIB_DIR_NAME).getAbsolutePath();
+ useIsaSpecificSubdirs = true;
+ }
+
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(scanFile);
- // Enable gross and lame hacks for apps that are built with old
- // SDK tools. We must scan their APKs for renderscript bitcode and
- // not launch them if it's present. Don't bother checking on devices
- // that don't have 64 bit support.
- String[] abiList = Build.SUPPORTED_ABIS;
- boolean hasLegacyRenderscriptBitcode = false;
- 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;
- hasLegacyRenderscriptBitcode = true;
- }
-
- File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
- final String dataPathString = dataPath.getCanonicalPath();
-
- if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
- /*
- * Upgrading from a previous version of the OS sometimes
- * leaves native libraries in the /data/data/<app>/lib
- * directory for system apps even when they shouldn't be.
- * Recent changes in the JNI library search path
- * necessitates we remove those to match previous behavior.
- */
- if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
- Log.i(TAG, "removed obsolete native libraries for system package "
- + path);
+ // TODO(multiArch): This can be null for apps that didn't go through the
+ // usual installation process. We can calculate it again, like we
+ // do during install time.
+ //
+ // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
+ // unnecessary.
+ final File nativeLibraryRoot = new File(nativeLibraryRootStr);
+
+ // Null out the abis so that they can be recalculated.
+ pkg.applicationInfo.primaryCpuAbi = null;
+ pkg.applicationInfo.secondaryCpuAbi = null;
+ if (isMultiArch(pkg.applicationInfo)) {
+ // Warn if we've set an abiOverride for multi-lib packages..
+ // By definition, we need to copy both 32 and 64 bit libraries for
+ // such packages.
+ if (abiOverride != null) {
+ Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+ }
+
+ int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
+ int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
+ if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+ if (isAsec) {
+ abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
+ } else {
+ abi32 = copyNativeLibrariesForInternalApp(handle,
+ nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS, useIsaSpecificSubdirs);
+ }
}
- if (abiOverride != null || hasLegacyRenderscriptBitcode) {
- pkg.applicationInfo.cpuAbi = abiList[0];
- pkgSetting.cpuAbiString = abiList[0];
- } else {
- setInternalAppAbi(pkg, pkgSetting);
+
+ if (abi32 < 0 && abi32 != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Error unpackaging 32 bit native libs for multiarch app, errorCode=" + abi32);
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
}
- } else {
- if (!isForwardLocked(pkg) && !isExternal(pkg)) {
- /*
- * Update native library dir if it starts with
- * /data/data
- */
- if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
- setInternalAppNativeLibraryPath(pkg, pkgSetting);
- nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
+
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ if (isAsec) {
+ abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
+ } else {
+ abi64 = copyNativeLibrariesForInternalApp(handle,
+ nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS, useIsaSpecificSubdirs);
}
+ }
- try {
- int copyRet = copyNativeLibrariesForInternalApp(handle,
- nativeLibraryDir, abiList);
- if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- Slog.e(TAG, "Unable to copy native libraries");
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
- }
+ if (abi64 < 0 && abi64 != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Error unpackaging 64 bit native libs for multiarch app, errorCode=" + abi32);
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
- // We've successfully copied native libraries across, so we make a
- // note of what ABI we're using
- if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- pkg.applicationInfo.cpuAbi = abiList[copyRet];
- } else if (abiOverride != null || hasLegacyRenderscriptBitcode) {
- pkg.applicationInfo.cpuAbi = abiList[0];
- } else {
- pkg.applicationInfo.cpuAbi = null;
- }
- } catch (IOException e) {
- Slog.e(TAG, "Unable to copy native libraries", e);
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
- }
- } else {
- // We don't have to copy the shared libraries if we're in the ASEC container
- // but we still need to scan the file to figure out what ABI the app needs.
- //
- // TODO: This duplicates work done in the default container service. It's possible
- // to clean this up but we'll need to change the interface between this service
- // and IMediaContainerService (but doing so will spread this logic out, rather
- // than centralizing it).
- final int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
- if (abi >= 0) {
- pkg.applicationInfo.cpuAbi = abiList[abi];
- } else if (abi == PackageManager.NO_NATIVE_LIBRARIES) {
- // Note that (non upgraded) system apps will not have any native
- // libraries bundled in their APK, but we're guaranteed not to be
- // such an app at this point.
- if (abiOverride != null || hasLegacyRenderscriptBitcode) {
- pkg.applicationInfo.cpuAbi = abiList[0];
- } else {
- pkg.applicationInfo.cpuAbi = null;
- }
+
+ if (abi64 >= 0) {
+ pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
+ }
+
+ if (abi32 >= 0) {
+ final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
+ if (abi64 >= 0) {
+ pkg.applicationInfo.secondaryCpuAbi = abi;
} else {
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
+ pkg.applicationInfo.primaryCpuAbi = abi;
}
}
+ } else {
+ String[] abiList = (abiOverride != null) ?
+ new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+
+ // Enable gross and lame hacks for apps that are built with old
+ // SDK tools. We must scan their APKs for renderscript bitcode and
+ // not launch them if it's present. Don't bother checking on devices
+ // that don't have 64 bit support.
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null &&
+ NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
- if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
- final int[] userIds = sUserManager.getUserIds();
- synchronized (mInstallLock) {
- for (int userId : userIds) {
- if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
- pkg.applicationInfo.nativeLibraryDir, userId) < 0) {
- Slog.w(TAG, "Failed linking native library dir (user=" + userId
- + ")");
- mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
- return null;
- }
- }
+ final int copyRet;
+ if (isAsec) {
+ copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
+ } else {
+ copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryRoot, abiList,
+ useIsaSpecificSubdirs);
+ }
+
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Error unpackaging native libs for app, errorCode=" + copyRet);
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
}
- }
- pkgSetting.cpuAbiString = pkg.applicationInfo.cpuAbi;
+ if (copyRet >= 0) {
+ pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
+ }
+ }
} catch (IOException ioe) {
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
} finally {
IoUtils.closeQuietly(handle);
}
+
+ if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
+ final int[] userIds = sUserManager.getUserIds();
+ synchronized (mInstallLock) {
+ // Create a native library symlink only if we have native libraries
+ // and if the native libraries are 32 bit libraries. We do not provide
+ // this symlink for 64 bit libraries.
+ if (pkg.applicationInfo.primaryCpuAbi != null &&
+ !VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
+ final String nativeLibPath;
+ if (pkg.applicationInfo.legacyNativeLibraryDir != null) {
+ nativeLibPath = pkg.applicationInfo.legacyNativeLibraryDir;
+ } else {
+ nativeLibPath = new File(nativeLibraryRootStr,
+ VMRuntime.getInstructionSet(pkg.applicationInfo.primaryCpuAbi)).getAbsolutePath();
+ }
+
+ for (int userId : userIds) {
+ if (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < 0) {
+ Slog.w(TAG, "Failed linking native library dir (user=" + userId
+ + ")");
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ }
+ }
+ }
+
+ pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
+ pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
+ }
+
+ if (DEBUG_ABI_SELECTION) {
+ Log.d(TAG, "Abis for package[" + pkg.packageName + "] are" +
+ " primary=" + pkg.applicationInfo.primaryCpuAbi +
+ " secondary=" + pkg.applicationInfo.secondaryCpuAbi);
}
+ // Check if we have a legacy native library path, use it if we do.
+ pkg.applicationInfo.legacyNativeLibraryDir = pkgSetting.legacyNativeLibraryPathString;
+
+ // Now that we've calculated the ABIs and determined if it's an internal app,
+ // we will go ahead and populate the nativeLibraryPath.
+ populateDefaultNativeLibraryPath(pkg, pkg.applicationInfo);
+
if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
// We don't do this here during boot because we can do it all
// at once after scanning all existing packages.
@@ -5929,6 +5954,9 @@ public class PackageManagerService extends IPackageManager.Stub {
a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs;
a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs;
a.info.dataDir = pkg.applicationInfo.dataDir;
+
+ // TODO: Update instrumentation.nativeLibraryDir as well ? Does it
+ // need other information about the application, like the ABI and what not ?
a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
mInstrumentation.put(a.getComponentName(), a);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
@@ -5989,13 +6017,16 @@ public class PackageManagerService extends IPackageManager.Stub {
* match {@code scannedPackage} or will update the ABI of {@code scannedPackage} to match
* the ABI selected for {@code packagesForUser}. This variant is used when installing or
* updating a package that belongs to a shared user.
+ *
+ * NOTE: We currently only match for the primary CPU abi string. Matching the secondary
+ * adds unnecessary complexity.
*/
private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
String requiredInstructionSet = null;
- if (scannedPackage != null && scannedPackage.applicationInfo.cpuAbi != null) {
+ if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
requiredInstructionSet = VMRuntime.getInstructionSet(
- scannedPackage.applicationInfo.cpuAbi);
+ scannedPackage.applicationInfo.primaryCpuAbi);
}
PackageSetting requirer = null;
@@ -6005,11 +6036,11 @@ public class PackageManagerService extends IPackageManager.Stub {
// we will never be able to change the ABI of any package belonging to a shared
// user, even if it's compatible with other packages.
if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
- if (ps.cpuAbiString == null) {
+ if (ps.primaryCpuAbiString == null) {
continue;
}
- final String instructionSet = VMRuntime.getInstructionSet(ps.cpuAbiString);
+ final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
if (requiredInstructionSet != null) {
if (!instructionSet.equals(requiredInstructionSet)) {
// We have a mismatch between instruction sets (say arm vs arm64).
@@ -6037,30 +6068,30 @@ public class PackageManagerService extends IPackageManager.Stub {
// requirer != null implies that either scannedPackage was null or that scannedPackage
// did not require an ABI, in which case we have to adjust scannedPackage to match
// the ABI of the set (which is the same as requirer's ABI)
- adjustedAbi = requirer.cpuAbiString;
+ adjustedAbi = requirer.primaryCpuAbiString;
if (scannedPackage != null) {
- scannedPackage.applicationInfo.cpuAbi = adjustedAbi;
+ scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi;
}
} else {
// requirer == null implies that we're updating all ABIs in the set to
// match scannedPackage.
- adjustedAbi = scannedPackage.applicationInfo.cpuAbi;
+ adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi;
}
for (PackageSetting ps : packagesForUser) {
if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
- if (ps.cpuAbiString != null) {
+ if (ps.primaryCpuAbiString != null) {
continue;
}
- ps.cpuAbiString = adjustedAbi;
+ ps.primaryCpuAbiString = adjustedAbi;
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
- ps.pkg.applicationInfo.cpuAbi = adjustedAbi;
+ ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
- ps.cpuAbiString = null;
- ps.pkg.applicationInfo.cpuAbi = null;
+ ps.primaryCpuAbiString = null;
+ ps.pkg.applicationInfo.primaryCpuAbi = null;
return false;
} else {
mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
@@ -6097,7 +6128,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private String calculateApkRoot(final String codePathString) {
+ private static String calculateApkRoot(final String codePathString) {
final File codePath = new File(codePathString);
final File codeRoot;
if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
@@ -6121,7 +6152,7 @@ public class PackageManagerService extends IPackageManager.Stub {
Slog.w(TAG, "Unrecognized code path "
+ codePath + " - using " + codeRoot);
} catch (IOException e) {
- // Can't canonicalize the lib path -- shenanigans?
+ // Can't canonicalize the code path -- shenanigans?
Slog.w(TAG, "Can't canonicalize code path " + codePath);
return Environment.getRootDirectory().getPath();
}
@@ -6129,104 +6160,154 @@ public class PackageManagerService extends IPackageManager.Stub {
return codeRoot.getPath();
}
- // This is the initial scan-time determination of how to handle a given
- // package for purposes of native library location.
- private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
- PackageSetting pkgSetting) {
- // "bundled" here means system-installed with no overriding update
- final boolean bundledApk = isSystemApp(pkg) && !isUpdatedSystemApp(pkg);
- final File codeFile = new File(pkg.applicationInfo.getCodePath());
- final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
-
- String nativeLibraryPath = null;
- if (bundledApk) {
- // If "/system/lib64/apkname" exists, assume that is the per-package
- // native library directory to use; otherwise use "/system/lib/apkname".
- String apkRoot = calculateApkRoot(pkg.applicationInfo.getCodePath());
- File lib64 = new File(apkRoot, LIB64_DIR_NAME);
- File packLib64 = new File(lib64, apkName);
- File libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
- nativeLibraryPath = (new File(libDir, apkName)).getAbsolutePath();
- } else if (isApkFile(codeFile)) {
- // Monolithic install
- nativeLibraryPath = (new File(mAppLibInstallDir, apkName)).getAbsolutePath();
- } else {
- // Cluster install
- // TODO: pipe through abiOverride
- String[] abiList = Build.SUPPORTED_ABIS;
- NativeLibraryHelper.Handle handle = null;
- try {
- handle = NativeLibraryHelper.Handle.create(codeFile);
- if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
- NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
- abiList = Build.SUPPORTED_32_BIT_ABIS;
+ private void populateDefaultNativeLibraryPath(PackageParser.Package pkg,
+ ApplicationInfo info) {
+ if (info.legacyNativeLibraryDir != null) {
+ // Not a cluster install.
+ if (DEBUG_ABI_SELECTION) {
+ Log.i(TAG, "Set nativeLibraryDir [non_cluster] for: " + pkg.packageName +
+ " to " + info.legacyNativeLibraryDir);
+ }
+ info.nativeLibraryDir = info.legacyNativeLibraryDir;
+ } else if (info.primaryCpuAbi != null) {
+ final boolean is64Bit = VMRuntime.is64BitAbi(info.primaryCpuAbi);
+ if (info.apkRoot != null) {
+ // This is a bundled system app so choose the path based on the ABI.
+ // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this
+ // is just the default path.
+ final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
+ final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
+ info.nativeLibraryDir = (new File(info.apkRoot, new File(libDir, apkName).getAbsolutePath()))
+ .getAbsolutePath();
+
+ if (DEBUG_ABI_SELECTION) {
+ Log.i(TAG, "Set nativeLibraryDir [system] for: " + pkg.packageName +
+ " to " + info.nativeLibraryDir);
}
+ } else {
+ // Cluster install. legacyNativeLibraryDir == null && primaryCpuAbi = null
+ // implies this must be a cluster package.
+ final String codePath = pkg.codePath;
+ final File libPath = new File(new File(codePath, LIB_DIR_NAME),
+ VMRuntime.getInstructionSet(info.primaryCpuAbi));
+ info.nativeLibraryDir = libPath.getAbsolutePath();
- final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList);
- if (abiIndex >= 0) {
- final File baseLibFile = new File(codeFile, LIB_DIR_NAME);
- final String abi = Build.SUPPORTED_ABIS[abiIndex];
- final String instructionSet = VMRuntime.getInstructionSet(abi);
- nativeLibraryPath = new File(baseLibFile, instructionSet).getAbsolutePath();
+ if (DEBUG_ABI_SELECTION) {
+ Log.i(TAG, "Set nativeLibraryDir [cluster] for: " + pkg.packageName +
+ " to " + info.nativeLibraryDir);
}
- } catch (IOException e) {
- Slog.e(TAG, "Failed to detect native libraries", e);
- } finally {
- IoUtils.closeQuietly(handle);
}
+ } else {
+ if (DEBUG_ABI_SELECTION) {
+ Log.i(TAG, "Setting nativeLibraryDir to null for: " + pkg.packageName);
+ }
+
+ info.nativeLibraryDir = null;
}
- pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
+ }
+
+ /**
+ * Calculate the abis and roots for a bundled app. These can uniquely
+ * be determined from the contents of the system partition, i.e whether
+ * it contains 64 or 32 bit shared libraries etc. We do not validate any
+ * of this information, and instead assume that the system was built
+ * sensibly.
+ */
+ private void setBundledAppAbisAndRoots(PackageParser.Package pkg,
+ PackageSetting pkgSetting) {
+ final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
+
+ // If "/system/lib64/apkname" exists, assume that is the per-package
+ // native library directory to use; otherwise use "/system/lib/apkname".
+ final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+ pkg.applicationInfo.apkRoot = apkRoot;
+ setBundledAppAbi(pkg, apkRoot, apkName);
// pkgSetting might be null during rescan following uninstall of updates
// to a bundled app, so accommodate that possibility. The settings in
// that case will be established later from the parsed package.
+ //
+ // If the settings aren't null, sync them up with what we've just derived.
+ // note that apkRoot isn't stored in the package settings.
if (pkgSetting != null) {
- pkgSetting.nativeLibraryPathString = nativeLibraryPath;
+ pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
+ pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
}
}
- // Deduces the required ABI of an upgraded system app.
- private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) {
- final String apkRoot = calculateApkRoot(pkg.applicationInfo.getCodePath());
- final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
-
+ /**
+ * Deduces the ABI of a bundled app and sets the relevant fields on the
+ * parsed pkg object.
+ *
+ * @param apkRoot the root of the installed apk, something like {@code /system} or {@code /oem}
+ * under which system libraries are installed.
+ * @param apkName the name of the installed package.
+ */
+ private static void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) {
// This is of the form "/system/lib64/<packagename>", "/vendor/lib64/<packagename>"
// or similar.
- final File lib64 = new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath());
- final File lib = new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath());
-
- // Assume that the bundled native libraries always correspond to the
- // most preferred 32 or 64 bit ABI.
- if (lib64.exists()) {
- pkg.applicationInfo.cpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
- pkgSetting.cpuAbiString = Build.SUPPORTED_64_BIT_ABIS[0];
- } else if (lib.exists()) {
- pkg.applicationInfo.cpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
- pkgSetting.cpuAbiString = Build.SUPPORTED_32_BIT_ABIS[0];
+ final boolean has64BitLibs = (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists();
+ final boolean has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists();
+
+ if (has64BitLibs && !has32BitLibs) {
+ // The package has 64 bit libs, but not 32 bit libs. Its primary
+ // ABI should be 64 bit. We can safely assume here that the bundled
+ // native libraries correspond to the most preferred ABI in the list.
+
+ pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
+ pkg.applicationInfo.secondaryCpuAbi = null;
+ } else if (has32BitLibs && !has64BitLibs) {
+ // The package has 32 bit libs but not 64 bit libs. Its primary
+ // ABI should be 32 bit.
+
+ pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
+ pkg.applicationInfo.secondaryCpuAbi = null;
+ } else if (has32BitLibs && has64BitLibs) {
+ // The application has both 64 and 32 bit bundled libraries. We check
+ // here that the app declares multiArch support, and warn if it doesn't.
+ //
+ // We will be lenient here and record both ABIs. The primary will be the
+ // ABI that's higher on the list, i.e, a device that's configured to prefer
+ // 64 bit apps will see a 64 bit primary ABI,
+
+ if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) {
+ Slog.e(TAG, "Package: " + pkg + " has multiple bundled libs, but is not multiarch.");
+ }
+
+ if (VMRuntime.is64BitAbi(getPreferredInstructionSet())) {
+ pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
+ pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
+ } else {
+ pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
+ pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
+ }
} else {
- // This is the case where the app has no native code.
- pkg.applicationInfo.cpuAbi = null;
- pkgSetting.cpuAbiString = null;
+ pkg.applicationInfo.primaryCpuAbi = null;
+ pkg.applicationInfo.secondaryCpuAbi = null;
}
}
- private static int copyNativeLibrariesForInternalApp(NativeLibraryHelper.Handle handle,
- final File nativeLibraryDir, String[] abiList) throws IOException {
- if (!nativeLibraryDir.isDirectory()) {
- nativeLibraryDir.delete();
+ private static void createNativeLibrarySubdir(File path) throws IOException {
+ if (!path.isDirectory()) {
+ path.delete();
- if (!nativeLibraryDir.mkdir()) {
- throw new IOException("Cannot create " + nativeLibraryDir.getPath());
+ if (!path.mkdir()) {
+ throw new IOException("Cannot create " + path.getPath());
}
try {
- Os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ Os.chmod(path.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
} catch (ErrnoException e) {
throw new IOException("Cannot chmod native library directory "
- + nativeLibraryDir.getPath(), e);
+ + path.getPath(), e);
}
- } else if (!SELinux.restorecon(nativeLibraryDir)) {
- throw new IOException("Cannot set SELinux context for " + nativeLibraryDir.getPath());
+ } else if (!SELinux.restorecon(path)) {
+ throw new IOException("Cannot set SELinux context for " + path.getPath());
}
+ }
+
+ private static int copyNativeLibrariesForInternalApp(NativeLibraryHelper.Handle handle,
+ final File nativeLibraryRoot, String[] abiList, boolean useIsaSubdir) throws IOException {
+ createNativeLibrarySubdir(nativeLibraryRoot);
/*
* If this is an internal application or our nativeLibraryPath points to
@@ -6234,8 +6315,22 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
if (abi >= 0) {
+ /*
+ * If we have a matching instruction set, construct a subdir under the native
+ * library root that corresponds to this instruction set.
+ */
+ final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
+ final File subDir;
+ if (useIsaSubdir) {
+ final File isaSubdir = new File(nativeLibraryRoot, instructionSet);
+ createNativeLibrarySubdir(isaSubdir);
+ subDir = isaSubdir;
+ } else {
+ subDir = nativeLibraryRoot;
+ }
+
int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
+ subDir, Build.SUPPORTED_ABIS[abi]);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
@@ -8374,7 +8469,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private InstallArgs mArgs;
private int mRet;
final String packageAbiOverride;
- final String packageInstructionSetOverride;
+ boolean multiArch;
InstallParams(File originFile, boolean originStaged, IPackageInstallObserver2 observer,
int flags, String installerPackageName, VerificationParams verificationParams,
@@ -8387,8 +8482,6 @@ public class PackageManagerService extends IPackageManager.Stub {
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.packageAbiOverride = packageAbiOverride;
- this.packageInstructionSetOverride = (packageAbiOverride == null) ?
- packageAbiOverride : VMRuntime.getInstructionSet(packageAbiOverride);
}
@Override
@@ -8499,6 +8592,11 @@ public class PackageManagerService extends IPackageManager.Stub {
final String originPath = originFile.getAbsolutePath();
pkgLite = mContainerService.getMinimalPackageInfo(originPath, flags, lowThreshold,
packageAbiOverride);
+ // Keep track of whether this package is a multiArch package until
+ // we perform a full scan of it. We need to do this because we might
+ // end up extracting the package shared libraries before we perform
+ // a full scan.
+ multiArch = pkgLite.multiArch;
/*
* If we have too little free space, try to free cache
@@ -8744,7 +8842,8 @@ public class PackageManagerService extends IPackageManager.Stub {
int mRet;
MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
- String packageName, String instructionSet, int uid, UserHandle user) {
+ String packageName, String[] instructionSets, int uid, UserHandle user,
+ boolean isMultiArch) {
super(user);
this.srcArgs = srcArgs;
this.observer = observer;
@@ -8754,7 +8853,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (srcArgs != null) {
final String codePath = srcArgs.getCodePath();
targetArgs = createInstallArgsForMoveTarget(codePath, flags, packageName,
- instructionSet);
+ instructionSets, isMultiArch);
} else {
targetArgs = null;
}
@@ -8869,7 +8968,8 @@ public class PackageManagerService extends IPackageManager.Stub {
* when cleaning up old installs, or used as a move source.
*/
private InstallArgs createInstallArgsForExisting(int flags, String codePath,
- String resourcePath, String nativeLibraryPath, String instructionSet) {
+ String resourcePath, String nativeLibraryRoot, String[] instructionSets,
+ boolean isMultiArch) {
final boolean isInAsec;
if (installOnSd(flags)) {
/* Apps on SD card are always in ASEC containers. */
@@ -8886,23 +8986,24 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (isInAsec) {
- return new AsecInstallArgs(codePath, resourcePath, nativeLibraryPath,
- instructionSet, installOnSd(flags), installForwardLocked(flags));
+ return new AsecInstallArgs(codePath, instructionSets,
+ installOnSd(flags), installForwardLocked(flags), isMultiArch);
} else {
- return new FileInstallArgs(codePath, resourcePath, nativeLibraryPath, instructionSet);
+ return new FileInstallArgs(codePath, resourcePath, nativeLibraryRoot,
+ instructionSets, isMultiArch);
}
}
private InstallArgs createInstallArgsForMoveTarget(String codePath, int flags, String pkgName,
- String instructionSet) {
+ String[] instructionSets, boolean isMultiArch) {
final File codeFile = new File(codePath);
if (installOnSd(flags) || installForwardLocked(flags)) {
String cid = getNextCodePath(codePath, pkgName, "/"
+ AsecInstallArgs.RES_FILE_NAME);
- return new AsecInstallArgs(codeFile, cid, instructionSet, installOnSd(flags),
- installForwardLocked(flags));
+ return new AsecInstallArgs(codeFile, cid, instructionSets, installOnSd(flags),
+ installForwardLocked(flags), isMultiArch);
} else {
- return new FileInstallArgs(codeFile, instructionSet);
+ return new FileInstallArgs(codeFile, instructionSets, isMultiArch);
}
}
@@ -8920,12 +9021,18 @@ public class PackageManagerService extends IPackageManager.Stub {
final String installerPackageName;
final ManifestDigest manifestDigest;
final UserHandle user;
- final String instructionSet;
final String abiOverride;
+ final boolean multiArch;
+
+ // The list of instruction sets supported by this app. This is currently
+ // only used during the rmdex() phase to clean up resources. We can get rid of this
+ // if we move dex files under the common app path.
+ /* nullable */ String[] instructionSets;
InstallArgs(File originFile, boolean originStaged, IPackageInstallObserver2 observer,
- int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user, String instructionSet, String abiOverride) {
+ int flags, String installerPackageName, ManifestDigest manifestDigest,
+ UserHandle user, String[] instructionSets,
+ String abiOverride, boolean multiArch) {
this.originFile = originFile;
this.originStaged = originStaged;
this.flags = flags;
@@ -8933,8 +9040,9 @@ public class PackageManagerService extends IPackageManager.Stub {
this.installerPackageName = installerPackageName;
this.manifestDigest = manifestDigest;
this.user = user;
- this.instructionSet = instructionSet;
+ this.instructionSets = instructionSets;
this.abiOverride = abiOverride;
+ this.multiArch = multiArch;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -8951,8 +9059,7 @@ public class PackageManagerService extends IPackageManager.Stub {
abstract String getCodePath();
/** @see PackageSettingBase#resourcePathString */
abstract String getResourcePath();
- /** @see PackageSettingBase#nativeLibraryPathString */
- abstract String getNativeLibraryPath();
+ abstract String getLegacyNativeLibraryPath();
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
@@ -8995,7 +9102,7 @@ public class PackageManagerService extends IPackageManager.Stub {
class FileInstallArgs extends InstallArgs {
private File codeFile;
private File resourceFile;
- private File nativeLibraryFile;
+ private File legacyNativeLibraryPath;
// Example topology:
// /data/app/com.example/base.apk
@@ -9008,24 +9115,27 @@ public class PackageManagerService extends IPackageManager.Stub {
FileInstallArgs(InstallParams params) {
super(params.originFile, params.originStaged, params.observer, params.flags,
params.installerPackageName, params.getManifestDigest(), params.getUser(),
- params.packageInstructionSetOverride, params.packageAbiOverride);
+ null /* instruction sets */, params.packageAbiOverride,
+ params.multiArch);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
}
/** Existing install */
- FileInstallArgs(String codePath, String resourcePath, String nativeLibraryPath,
- String instructionSet) {
- super(null, false, null, 0, null, null, null, instructionSet, null);
+ FileInstallArgs(String codePath, String resourcePath, String legacyNativeLibraryRoot,
+ String[] instructionSets, boolean isMultiArch) {
+ super(null, false, null, 0, null, null, null, instructionSets, null, isMultiArch);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
- this.nativeLibraryFile = (nativeLibraryPath != null) ? new File(nativeLibraryPath) : null;
+ this.legacyNativeLibraryPath = (legacyNativeLibraryRoot != null) ?
+ new File(legacyNativeLibraryRoot) : null;
}
/** New install from existing */
- FileInstallArgs(File originFile, String instructionSet) {
- super(originFile, false, null, 0, null, null, null, instructionSet, null);
+ FileInstallArgs(File originFile, String[] instructionSets, boolean isMultiArch) {
+ super(originFile, false, null, 0, null, null, null, instructionSets, null,
+ isMultiArch);
}
boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
@@ -9091,35 +9201,67 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- String[] abiList = (abiOverride != null) ?
- new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+ final File libraryRoot = new File(codeFile, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(codeFile);
- if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
- abiOverride == null &&
- NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
- abiList = Build.SUPPORTED_32_BIT_ABIS;
- }
-
- // TODO: refactor to avoid double findSupportedAbi()
- final int abiIndex = NativeLibraryHelper.findSupportedAbi(handle, abiList);
- if (abiIndex < 0 && abiIndex != PackageManager.NO_NATIVE_LIBRARIES) {
- return abiIndex;
- } else if (abiIndex >= 0) {
- final File baseLibFile = new File(codeFile, LIB_DIR_NAME);
- baseLibFile.mkdir();
- Os.chmod(baseLibFile.getAbsolutePath(), 0755);
-
- final String abi = Build.SUPPORTED_ABIS[abiIndex];
- final String instructionSet = VMRuntime.getInstructionSet(abi);
- nativeLibraryFile = new File(baseLibFile, instructionSet);
- nativeLibraryFile.mkdir();
- Os.chmod(nativeLibraryFile.getAbsolutePath(), 0755);
-
- copyNativeLibrariesForInternalApp(handle, nativeLibraryFile, abiList);
- }
- } catch (IOException | ErrnoException e) {
+ if (multiArch) {
+ // Warn if we've set an abiOverride for multi-lib packages..
+ // By definition, we need to copy both 32 and 64 bit libraries for
+ // such packages.
+ if (abiOverride != null) {
+ Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
+ }
+
+ int copyRet = PackageManager.NO_NATIVE_LIBRARIES;
+ if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
+ copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
+ Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Failure copying 32 bit native libraries [errorCode=" + copyRet + "]");
+ return copyRet;
+ }
+ }
+
+ if (DEBUG_ABI_SELECTION && copyRet >= 0) {
+ Log.d(TAG, "Installed 32 bit libraries under: " + codeFile + " abi=" +
+ Build.SUPPORTED_32_BIT_ABIS[copyRet]);
+ }
+
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+ copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
+ Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Failure copying 64 bit native libraries [errorCode=" + copyRet + "]");
+ return copyRet;
+ }
+ }
+
+ if (DEBUG_ABI_SELECTION && copyRet >= 0) {
+ Log.d(TAG, "Installed 64 bit libraries under: " + codeFile + " abi=" +
+ Build.SUPPORTED_64_BIT_ABIS[copyRet]);
+ }
+ } else {
+ String[] abiList = (abiOverride != null) ?
+ new String[] { abiOverride } : Build.SUPPORTED_ABIS;
+
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && abiOverride == null &&
+ NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
+
+ int copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot, abiList,
+ true /* use isa specific subdirs */);
+ if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+ Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
+ return copyRet;
+ }
+
+ if (DEBUG_ABI_SELECTION && copyRet >= 0) {
+ Log.d(TAG, "Installed libraries under: " + codeFile + " abi=" + abiList[copyRet]);
+ }
+ }
+ } catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
@@ -9156,8 +9298,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// Reflect the rename internally
codeFile = afterCodeFile;
resourceFile = afterCodeFile;
- nativeLibraryFile = FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile,
- nativeLibraryFile);
// Reflect the rename in scanned details
pkg.codePath = afterCodeFile.getAbsolutePath();
@@ -9173,7 +9313,8 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.setResourcePath(pkg.codePath);
pkg.applicationInfo.setBaseResourcePath(pkg.baseCodePath);
pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
- pkg.applicationInfo.nativeLibraryDir = getNativeLibraryPath();
+ // Null out the legacy native dir so we stop using it.
+ pkg.applicationInfo.legacyNativeLibraryDir = null;
return true;
}
@@ -9197,8 +9338,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- String getNativeLibraryPath() {
- return (nativeLibraryFile != null) ? nativeLibraryFile.getAbsolutePath() : null;
+ String getLegacyNativeLibraryPath() {
+ return (legacyNativeLibraryPath != null) ? legacyNativeLibraryPath.getAbsolutePath() : null;
}
private boolean cleanUp() {
@@ -9215,9 +9356,11 @@ public class PackageManagerService extends IPackageManager.Stub {
resourceFile.delete();
}
- if (nativeLibraryFile != null && !FileUtils.contains(codeFile, nativeLibraryFile)) {
- FileUtils.deleteContents(nativeLibraryFile);
- nativeLibraryFile.delete();
+ if (legacyNativeLibraryPath != null && !FileUtils.contains(codeFile, legacyNativeLibraryPath)) {
+ if (!FileUtils.deleteContents(legacyNativeLibraryPath)) {
+ Slog.w(TAG, "Couldn't delete native library directory " + legacyNativeLibraryPath);
+ }
+ legacyNativeLibraryPath.delete();
}
return true;
@@ -9238,16 +9381,18 @@ public class PackageManagerService extends IPackageManager.Stub {
cleanUp();
if (!allCodePaths.isEmpty()) {
- if (instructionSet == null) {
+ if (instructionSets == null) {
throw new IllegalStateException("instructionSet == null");
}
for (String codePath : allCodePaths) {
- int retCode = mInstaller.rmdex(codePath, instructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package: "
- + " at location " + codePath + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
+ for (String instructionSet : instructionSets) {
+ int retCode = mInstaller.rmdex(codePath, instructionSet);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove dex file for package: "
+ + " at location " + codePath + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
+ }
}
}
}
@@ -9289,21 +9434,22 @@ public class PackageManagerService extends IPackageManager.Stub {
String cid;
String packagePath;
String resourcePath;
- String libraryPath;
+ String legacyNativeLibraryDir;
/** New install */
AsecInstallArgs(InstallParams params) {
super(params.originFile, params.originStaged, params.observer, params.flags,
- params.installerPackageName, params.getManifestDigest(), params.getUser(),
- params.packageInstructionSetOverride, params.packageAbiOverride);
+ params.installerPackageName, params.getManifestDigest(),
+ params.getUser(), null /* instruction sets */,
+ params.packageAbiOverride, params.multiArch);
}
/** Existing install */
- AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
- String instructionSet, boolean isExternal, boolean isForwardLocked) {
+ AsecInstallArgs(String fullCodePath, String[] instructionSets,
+ boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
super(null, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSet, null);
+ instructionSets, null, isMultiArch);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -9312,20 +9458,21 @@ public class PackageManagerService extends IPackageManager.Stub {
setCachePath(subStr1);
}
- AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) {
+ AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked,
+ boolean isMultiArch) {
super(null, false, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSet, null);
+ instructionSets, null, isMultiArch);
this.cid = cid;
setCachePath(PackageHelper.getSdDir(cid));
}
/** New install from existing */
- AsecInstallArgs(File originPackageFile, String cid, String instructionSet,
- boolean isExternal, boolean isForwardLocked) {
+ AsecInstallArgs(File originPackageFile, String cid, String[] instructionSets,
+ boolean isExternal, boolean isForwardLocked, boolean isMultiArch) {
super(originPackageFile, false, null, (isExternal ? INSTALL_EXTERNAL : 0)
| (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSet, null);
+ instructionSets, null, isMultiArch);
this.cid = cid;
}
@@ -9376,8 +9523,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
- String getNativeLibraryPath() {
- return libraryPath;
+ String getLegacyNativeLibraryPath() {
+ return legacyNativeLibraryDir;
}
int doPreInstall(int status) {
@@ -9452,14 +9599,16 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.setResourcePath(getResourcePath());
pkg.applicationInfo.setBaseResourcePath(getResourcePath());
pkg.applicationInfo.setSplitResourcePaths(null);
- pkg.applicationInfo.nativeLibraryDir = getNativeLibraryPath();
+ // ASEC installs are considered "legacy" because we don't support
+ // multiarch on them yet, and use the old style paths on them.
+ pkg.applicationInfo.legacyNativeLibraryDir = legacyNativeLibraryDir;
return true;
}
private void setCachePath(String newCachePath) {
File cachePath = new File(newCachePath);
- libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
+ legacyNativeLibraryDir = new File(cachePath, LIB_DIR_NAME).getPath();
packagePath = new File(cachePath, RES_FILE_NAME).getPath();
if (isFwdLocked()) {
@@ -9508,15 +9657,17 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanUpResourcesLI() {
String sourceFile = getCodePath();
// Remove dex file
- if (instructionSet == null) {
+ if (instructionSets == null) {
throw new IllegalStateException("instructionSet == null");
}
- int retCode = mInstaller.rmdex(sourceFile, instructionSet);
- if (retCode < 0) {
- Slog.w(TAG, "Couldn't remove dex file for package: "
- + " at location "
- + sourceFile.toString() + ", retcode=" + retCode);
- // we don't consider this to be a failure of the core package deletion
+ for (String instructionSet : instructionSets) {
+ int retCode = mInstaller.rmdex(sourceFile, instructionSet);
+ if (retCode < 0) {
+ Slog.w(TAG, "Couldn't remove dex file for package: "
+ + " at location "
+ + sourceFile.toString() + ", retcode=" + retCode);
+ // we don't consider this to be a failure of the core package deletion
+ }
}
cleanUp();
}
@@ -9922,8 +10073,9 @@ public class PackageManagerService extends IPackageManager.Stub {
res.removedInfo.args = createInstallArgsForExisting(0,
deletedPackage.applicationInfo.getCodePath(),
deletedPackage.applicationInfo.getResourcePath(),
- deletedPackage.applicationInfo.nativeLibraryDir,
- getAppInstructionSet(deletedPackage.applicationInfo));
+ deletedPackage.applicationInfo.legacyNativeLibraryDir,
+ getAppDexInstructionSets(deletedPackage.applicationInfo),
+ isMultiArch(deletedPackage.applicationInfo));
} else {
res.removedInfo.args = null;
}
@@ -9983,10 +10135,11 @@ public class PackageManagerService extends IPackageManager.Stub {
private int moveDexFilesLI(String oldCodePath, PackageParser.Package newPackage) {
// TODO: extend to move split APK dex files
if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
- final String instructionSet = getAppInstructionSet(newPackage.applicationInfo);
- int retCode = mInstaller.movedex(oldCodePath, newPackage.baseCodePath,
- instructionSet);
- if (retCode != 0) {
+ final String[] instructionSets = getAppDexInstructionSets(newPackage.applicationInfo);
+ for (String instructionSet : instructionSets) {
+ int retCode = mInstaller.movedex(oldCodePath, newPackage.baseCodePath,
+ instructionSet);
+ if (retCode != 0) {
/*
* Programs may be lazily run through dexopt, so the
* source may not exist. However, something seems to
@@ -9995,9 +10148,10 @@ public class PackageManagerService extends IPackageManager.Stub {
* remove the target to make sure there isn't a stale
* file from a previous version of the package.
*/
- newPackage.mDexOptNeeded = true;
- mInstaller.rmdex(oldCodePath, instructionSet);
- mInstaller.rmdex(newPackage.baseCodePath, instructionSet);
+ newPackage.mDexOptNeeded = true;
+ mInstaller.rmdex(oldCodePath, instructionSet);
+ mInstaller.rmdex(newPackage.baseCodePath, instructionSet);
+ }
}
}
return PackageManager.INSTALL_SUCCEEDED;
@@ -10234,6 +10388,14 @@ public class PackageManagerService extends IPackageManager.Stub {
return (ps.pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
}
+ private static boolean isMultiArch(PackageSetting ps) {
+ return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0;
+ }
+
+ private static boolean isMultiArch(ApplicationInfo info) {
+ return (info.flags & ApplicationInfo.FLAG_MULTIARCH) != 0;
+ }
+
private static boolean isExternal(PackageParser.Package pkg) {
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
}
@@ -10591,7 +10753,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Reinstate the old system package
mSettings.enableSystemPackageLPw(newPs.name);
// Remove any native libraries from the upgraded package.
- NativeLibraryHelper.removeNativeBinariesLI(newPs.nativeLibraryPathString);
+ NativeLibraryHelper.removeNativeBinariesLI(newPs.legacyNativeLibraryPathString);
}
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
@@ -10610,7 +10772,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// writer
synchronized (mPackages) {
PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
- setInternalAppNativeLibraryPath(newPkg, ps);
+ setBundledAppAbisAndRoots(newPkg, ps);
updatePermissionsLPw(newPkg.packageName, newPkg,
UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
if (applyUserRestrictions) {
@@ -10650,8 +10812,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Delete application code and resources
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
- ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
- getAppInstructionSetFromSettings(ps));
+ ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
+ getAppDexInstructionSets(ps), isMultiArch(ps));
}
return true;
}
@@ -11056,7 +11218,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
PackageParser.Package p;
boolean dataOnly = false;
- String libDirPath = null;
+ String libDirRoot = null;
String asecPath = null;
PackageSetting ps = null;
synchronized (mPackages) {
@@ -11071,7 +11233,7 @@ public class PackageManagerService extends IPackageManager.Stub {
p = ps.pkg;
}
if (ps != null) {
- libDirPath = ps.nativeLibraryPathString;
+ libDirRoot = ps.legacyNativeLibraryPathString;
}
if (p != null && (isExternal(p) || isForwardLocked(p))) {
String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath());
@@ -11092,8 +11254,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
// TODO: extend to measure size of split APKs
- int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirPath,
- publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps),
+ // TODO(multiArch): Extend getSizeInfo to look at the full subdirectory tree,
+ // not just the first level.
+ // TODO(multiArch): Extend getSizeInfo to look at *all* instruction sets, not
+ // just the primary.
+ int res = mInstaller.getSizeInfo(packageName, userHandle, p.baseCodePath, libDirRoot,
+ publicSrcDir, asecPath, getAppDexInstructionSets(ps),
pStats);
if (res < 0) {
return false;
@@ -12357,8 +12523,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final AsecInstallArgs args = new AsecInstallArgs(cid,
- getAppInstructionSetFromSettings(ps),
- isForwardLocked(ps));
+ getAppDexInstructionSets(ps), isForwardLocked(ps), isMultiArch(ps));
// The package status is changed only if the code path
// matches between settings and the container id.
if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
@@ -12676,16 +12841,17 @@ public class PackageManagerService extends IPackageManager.Stub {
* anyway.
*/
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user),
+ processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1, user, false),
returnCode);
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
- final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
+ final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ final boolean multiArch = isMultiArch(pkg.applicationInfo);
InstallArgs srcArgs = createInstallArgsForExisting(currFlags,
pkg.applicationInfo.getCodePath(), pkg.applicationInfo.getResourcePath(),
- pkg.applicationInfo.nativeLibraryDir, instructionSet);
+ pkg.applicationInfo.legacyNativeLibraryDir, instructionSets, multiArch);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
- instructionSet, pkg.applicationInfo.uid, user);
+ instructionSets, pkg.applicationInfo.uid, user, multiArch);
msg.obj = mp;
mHandler.sendMessage(msg);
}
@@ -12747,12 +12913,15 @@ public class PackageManagerService extends IPackageManager.Stub {
final String oldCodePath = pkg.codePath;
final String newCodePath = mp.targetArgs.getCodePath();
final String newResPath = mp.targetArgs.getResourcePath();
- final String newNativePath = mp.targetArgs
- .getNativeLibraryPath();
-
- final File newNativeDir = new File(newNativePath);
+ // TODO: This assumes the new style of installation.
+ // should we look at legacyNativeLibraryPath ?
+ final String newNativeRoot = new File(pkg.codePath, LIB_DIR_NAME).getAbsolutePath();
+ final File newNativeDir = new File(newNativeRoot);
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
+ // TODO(multiArch): Fix this so that it looks at the existing
+ // recorded CPU abis from the package. There's no need for a separate
+ // round of ABI scanning here.
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(
@@ -12771,11 +12940,17 @@ public class PackageManagerService extends IPackageManager.Stub {
IoUtils.closeQuietly(handle);
}
}
+
final int[] users = sUserManager.getUserIds();
if (returnCode == PackageManager.MOVE_SUCCEEDED) {
for (int user : users) {
+ // TODO(multiArch): Fix this so that it links to the
+ // correct directory. We're currently pointing to root. but we
+ // must point to the arch specific subdirectory (if applicable).
+ //
+ // TODO(multiArch): Bogus reference to nativeLibraryDir.
if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
- newNativePath, user) < 0) {
+ newNativeRoot, user) < 0) {
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
}
}
@@ -12801,15 +12976,21 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.setResourcePath(newResPath);
pkg.applicationInfo.setBaseResourcePath(newResPath);
pkg.applicationInfo.setSplitResourcePaths(null);
- pkg.applicationInfo.nativeLibraryDir = newNativePath;
+ // Null out the legacy nativeLibraryDir so that we stop using it and
+ // always derive the codepath.
+ pkg.applicationInfo.legacyNativeLibraryDir = null;
PackageSetting ps = (PackageSetting) pkg.mExtras;
ps.codePath = new File(pkg.applicationInfo.getCodePath());
ps.codePathString = ps.codePath.getPath();
- ps.resourcePath = new File(
- pkg.applicationInfo.getResourcePath());
+ ps.resourcePath = new File(pkg.applicationInfo.getResourcePath());
ps.resourcePathString = ps.resourcePath.getPath();
- ps.nativeLibraryPathString = newNativePath;
+
+ // Note that we don't have to recalculate the primary and secondary
+ // CPU ABIs because they must already have been calculated during the
+ // initial install of the app.
+ ps.legacyNativeLibraryPathString = null;
+
// Set the application info flag
// correctly.
if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 284da99..a6571cf 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -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);
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index f263e07..3390efe 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -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;
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
index 36c3a34..85be651 100644
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ b/services/core/java/com/android/server/pm/PendingPackage.java
@@ -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;
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 81ea72c..71b8974 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -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.primaryCpuAbiString != null) {
+ serializer.attribute(null, "primaryCpuAbi", pkg.primaryCpuAbiString);
}
- if (pkg.cpuAbiString != null) {
- serializer.attribute(null, "requiredCpuAbi", pkg.cpuAbiString);
+ 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);