Merge "Explictly release the surface in TV input framework"
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 82d13a6..391c197 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,6 +15,7 @@
#include <cutils/properties.h>
#include <cutils/trace.h>
#include <android_runtime/AndroidRuntime.h>
+#include <private/android_filesystem_config.h> // for AID_SYSTEM
#include <stdlib.h>
#include <stdio.h>
@@ -137,6 +138,44 @@
return (end - start);
}
+static void maybeCreateDalvikCache() {
+#if defined(__aarch64__)
+ static const char kInstructionSet[] = "arm64";
+#elif defined(__x86_64__)
+ static const char kInstructionSet[] = "x86_64";
+#elif defined(__arm__)
+ static const char kInstructionSet[] = "arm";
+#elif defined(__x86__)
+ static const char kInstructionSet[] = "x86";
+#elif defined (__mips__)
+ static const char kInstructionSet[] = "mips";
+#else
+#error "Unknown instruction set"
+#endif
+ const char* androidRoot = getenv("ANDROID_DATA");
+ LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset");
+
+ char dalvikCacheDir[PATH_MAX];
+ const int numChars = snprintf(dalvikCacheDir, PATH_MAX,
+ "%s/dalvik-cache/%s", androidRoot, kInstructionSet);
+ LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
+ "Error constructing dalvik cache : %s", strerror(errno));
+
+ int result = mkdir(dalvikCacheDir, 0771);
+ LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST),
+ "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno));
+
+ // We always perform these steps because the directory might
+ // already exist, with wider permissions and a different owner
+ // than we'd like.
+ result = chown(dalvikCacheDir, AID_SYSTEM, AID_SYSTEM);
+ LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));
+
+ result = chmod(dalvikCacheDir, 0771);
+ LOG_ALWAYS_FATAL_IF((result < 0),
+ "Error changing dalvik-cache permissions : %s", strerror(errno));
+}
+
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
static const char ZYGOTE_NICE_NAME[] = "zygote64";
@@ -223,6 +262,9 @@
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
+ // We're in zygote mode.
+ maybeCreateDalvikCache();
+
if (startSystemServer) {
args.add(String8("start-system-server"));
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0336dd6..1ca6b90 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -81,12 +81,38 @@
public static final String SERIAL = getString("ro.serialno");
/**
- * A list of ABIs (in priority) order supported by this device.
+ * An ordered list of ABIs supported by this device. The most preferred ABI is the first
+ * element in the list.
+ *
+ * See {@link #SUPPORTED_32_BIT_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
*
* @hide
*/
public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(",");
+ /**
+ * An ordered list of <b>32 bit</b> ABIs supported by this device. The most preferred ABI
+ * is the first element in the list.
+ *
+ * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
+ *
+ * @hide
+ */
+ public static final String[] SUPPORTED_32_BIT_ABIS = getString("ro.product.cpu.abilist32")
+ .split(",");
+
+ /**
+ * An ordered list of <b>64 bit</b> ABIs supported by this device. The most preferred ABI
+ * is the first element in the list.
+ *
+ * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_32_BIT_ABIS}.
+ *
+ * @hide
+ */
+ public static final String[] SUPPORTED_64_BIT_ABIS = getString("ro.product.cpu.abilist64")
+ .split(",");
+
+
/** Various version strings. */
public static class VERSION {
/**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b4ed68c..1b3aa0a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -707,16 +707,6 @@
return primaryZygoteState;
}
- // TODO: Get rid of this. This is a temporary workaround until all the
- // compilation related pieces for the dual zygote stack are ready.
- // b/3647418.
- if (System.getenv("ANDROID_SOCKET_" + SECONDARY_ZYGOTE_SOCKET) == null) {
- Log.e(LOG_TAG, "Forcing app to primary zygote, secondary unavailable (ABI= " + abi + ")");
- // Should be :
- // throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
- return primaryZygoteState;
- }
-
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET,
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ff816ea..82d3f53 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -211,7 +211,7 @@
return execute(builder.toString());
}
- public int dexopt(String apkPath, int uid, boolean isPublic) {
+ public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
StringBuilder builder = new StringBuilder("dexopt");
builder.append(' ');
builder.append(apkPath);
@@ -219,10 +219,13 @@
builder.append(uid);
builder.append(isPublic ? " 1" : " 0");
builder.append(" *"); // No pkgName arg present
+ builder.append(' ');
+ builder.append(instructionSet);
return execute(builder.toString());
}
- public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) {
+ public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
+ String instructionSet) {
StringBuilder builder = new StringBuilder("dexopt");
builder.append(' ');
builder.append(apkPath);
@@ -231,6 +234,8 @@
builder.append(isPublic ? " 1" : " 0");
builder.append(' ');
builder.append(pkgName);
+ builder.append(' ');
+ builder.append(instructionSet);
return execute(builder.toString());
}
@@ -245,19 +250,23 @@
return execute(builder.toString());
}
- public int movedex(String srcPath, String dstPath) {
+ public int movedex(String srcPath, String dstPath, String instructionSet) {
StringBuilder builder = new StringBuilder("movedex");
builder.append(' ');
builder.append(srcPath);
builder.append(' ');
builder.append(dstPath);
+ builder.append(' ');
+ builder.append(instructionSet);
return execute(builder.toString());
}
- public int rmdex(String codePath) {
+ public int rmdex(String codePath, String instructionSet) {
StringBuilder builder = new StringBuilder("rmdex");
builder.append(' ');
builder.append(codePath);
+ builder.append(' ');
+ builder.append(instructionSet);
return execute(builder.toString());
}
@@ -344,7 +353,7 @@
}
public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
- String fwdLockApkPath, String asecPath, PackageStats pStats) {
+ String fwdLockApkPath, String asecPath, String instructionSet, PackageStats pStats) {
StringBuilder builder = new StringBuilder("getsize");
builder.append(' ');
builder.append(pkgName);
@@ -358,6 +367,8 @@
builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
builder.append(' ');
builder.append(asecPath != null ? asecPath : "!");
+ builder.append(' ');
+ builder.append(instructionSet);
String s = transaction(builder.toString());
String res[] = s.split(" ");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d0412ef..038e2dd 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -31,6 +31,7 @@
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.internal.util.ArrayUtils.removeInt;
+import android.content.pm.PackageParser.*;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.NativeLibraryHelper;
@@ -80,7 +81,6 @@
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageStats;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
@@ -162,6 +162,7 @@
import java.util.Map;
import java.util.Set;
+import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
import com.android.internal.R;
@@ -270,6 +271,8 @@
static final String mTempContainerPrefix = "smdl2tmp";
+ private static String sPreferredInstructionSet;
+
final ServiceThread mHandlerThread;
private static final String IDMAP_PREFIX = "/data/resource-cache/";
@@ -1242,27 +1245,38 @@
boolean didDexOpt = false;
+ final List<String> instructionSets = getAllInstructionSets();
+
/**
* Ensure all external libraries have had dexopt run on them.
*/
if (mSharedLibraries.size() > 0) {
- Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator();
- while (libs.hasNext()) {
- String lib = libs.next().path;
- if (lib == null) {
- continue;
- }
- try {
- if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) {
- alreadyDexOpted.add(lib);
- mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
- didDexOpt = true;
+ // NOTE: For now, we're compiling these system "shared libraries"
+ // (and framework jars) into all available architectures. It's possible
+ // to compile them only when we come across an app that uses them (there's
+ // already logic for that in scanPackageLI) but that adds some complexity.
+ for (String instructionSet : instructionSets) {
+ for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
+ final String lib = libEntry.path;
+ if (lib == null) {
+ continue;
}
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Library not found: " + lib);
- } catch (IOException e) {
- Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
- + e.getMessage());
+
+ try {
+ if (dalvik.system.DexFile.isDexOptNeededInternal(
+ lib, null, instructionSet, false)) {
+ alreadyDexOpted.add(lib);
+
+ // The list of "shared libraries" we have at this point is
+ mInstaller.dexopt(lib, Process.SYSTEM_UID, true, instructionSet);
+ didDexOpt = true;
+ }
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Library not found: " + lib);
+ } catch (IOException e) {
+ Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+ + e.getMessage());
+ }
}
}
}
@@ -1285,49 +1299,37 @@
*/
String[] frameworkFiles = frameworkDir.list();
if (frameworkFiles != null) {
- for (int i=0; i<frameworkFiles.length; i++) {
- File libPath = new File(frameworkDir, frameworkFiles[i]);
- String path = libPath.getPath();
- // Skip the file if we alrady did it.
- if (alreadyDexOpted.contains(path)) {
- continue;
- }
- // Skip the file if it is not a type we want to dexopt.
- if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
- continue;
- }
- try {
- if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) {
- mInstaller.dexopt(path, Process.SYSTEM_UID, true);
- didDexOpt = true;
+ // TODO: We could compile these only for the most preferred ABI. We should
+ // first double check that the dex files for these commands are not referenced
+ // by other system apps.
+ for (String instructionSet : instructionSets) {
+ for (int i=0; i<frameworkFiles.length; i++) {
+ File libPath = new File(frameworkDir, frameworkFiles[i]);
+ String path = libPath.getPath();
+ // Skip the file if we already did it.
+ if (alreadyDexOpted.contains(path)) {
+ continue;
}
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "Jar not found: " + path);
- } catch (IOException e) {
- Slog.w(TAG, "Exception reading jar: " + path, e);
+ // Skip the file if it is not a type we want to dexopt.
+ if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
+ continue;
+ }
+ try {
+ if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, instructionSet, false)) {
+ mInstaller.dexopt(path, Process.SYSTEM_UID, true, instructionSet);
+ didDexOpt = true;
+ }
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Jar not found: " + path);
+ } catch (IOException e) {
+ Slog.w(TAG, "Exception reading jar: " + path, e);
+ }
}
}
}
if (didDexOpt) {
- File dalvikCacheDir = new File(dataDir, "dalvik-cache");
-
- // If we had to do a dexopt of one of the previous
- // things, then something on the system has changed.
- // Consider this significant, and wipe away all other
- // existing dexopt files to ensure we don't leave any
- // dangling around.
- String[] files = dalvikCacheDir.list();
- if (files != null) {
- for (int i=0; i<files.length; i++) {
- String fn = files[i];
- if (fn.startsWith("data@app@")
- || fn.startsWith("data@app-private@")) {
- Slog.i(TAG, "Pruning dalvik file: " + fn);
- (new File(dalvikCacheDir, fn)).delete();
- }
- }
- }
+ pruneDexFiles(new File(dataDir, "dalvik-cache"));
}
// Collect vendor overlay packages.
@@ -1505,6 +1507,12 @@
// the correct library paths.
updateAllSharedLibrariesLPw();
+
+ for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
+ adjustCpuAbisForSharedUserLPw(setting.packages, true /* do dexopt */,
+ false /* force dexopt */, false /* defer dexopt */);
+ }
+
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
@@ -1554,6 +1562,37 @@
} // synchronized (mInstallLock)
}
+ private static void pruneDexFiles(File cacheDir) {
+ // If we had to do a dexopt of one of the previous
+ // things, then something on the system has changed.
+ // Consider this significant, and wipe away all other
+ // existing dexopt files to ensure we don't leave any
+ // dangling around.
+ //
+ // Additionally, delete all dex files from the root directory
+ // since there shouldn't be any there anyway.
+ File[] files = cacheDir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (!file.isDirectory()) {
+ Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath());
+ file.delete();
+ } else {
+ File[] subDirList = file.listFiles();
+ if (subDirList != null) {
+ for (File subDirFile : subDirList) {
+ final String fn = subDirFile.getName();
+ if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) {
+ Slog.i(TAG, "Pruning dalvik file: " + fn);
+ subDirFile.delete();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
public boolean isFirstBoot() {
return !mRestoredSettings;
}
@@ -1843,7 +1882,6 @@
PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
- PackageInfo pi;
final PackageSetting ps = (PackageSetting) p.mExtras;
if (ps == null) {
return null;
@@ -3969,7 +4007,8 @@
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
- ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
+ ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
+ getAppInstructionSetFromSettings(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4033,7 +4072,8 @@
+ ps.codePathString + ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
- ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
+ ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
+ getAppInstructionSetFromSettings(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
@@ -4067,8 +4107,6 @@
codePath = pkg.mScanPath;
// Set application objects path explicitly.
setApplicationInfoPaths(pkg, codePath, resPath);
- // Applications can run with the primary Cpu Abi unless otherwise is specified
- pkg.applicationInfo.requiredCpuAbi = null;
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
| SCAN_UPDATE_SIGNATURE, currentTime, user);
@@ -4158,12 +4196,16 @@
}
}
+ @Override
public void performBootDexOpt() {
- HashSet<PackageParser.Package> pkgs = null;
+ enforceSystemOrRoot("Only the system can request dexopt be performed");
+
+ final HashSet<PackageParser.Package> pkgs;
synchronized (mPackages) {
pkgs = mDeferredDexOpt;
mDeferredDexOpt = null;
}
+
if (pkgs != null) {
int i = 0;
for (PackageParser.Package pkg : pkgs) {
@@ -4180,16 +4222,17 @@
PackageParser.Package p = pkg;
synchronized (mInstallLock) {
if (!p.mDidDexOpt) {
- performDexOptLI(p, false, false, true);
+ performDexOptLI(p, false /* force dex */, false /* defer */,
+ true /* include dependencies */);
}
}
}
}
}
+ @Override
public boolean performDexOpt(String packageName) {
enforceSystemOrRoot("Only the system can request dexopt be performed");
-
if (!mNoDexOpt) {
return false;
}
@@ -4202,12 +4245,13 @@
}
}
synchronized (mInstallLock) {
- return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED;
+ return performDexOptLI(p, false /* force dex */, false /* defer */,
+ true /* include dependencies */) == DEX_OPT_PERFORMED;
}
}
- private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer,
- HashSet<String> done) {
+ private void performDexOptLibsLI(ArrayList<String> libs, String instructionSet, boolean forceDex,
+ boolean defer, HashSet<String> done) {
for (int i=0; i<libs.size(); i++) {
PackageParser.Package libPkg;
String libName;
@@ -4221,7 +4265,7 @@
}
}
if (libPkg != null && !done.contains(libName)) {
- performDexOptLI(libPkg, forceDex, defer, done);
+ performDexOptLI(libPkg, instructionSet, forceDex, defer, done);
}
}
}
@@ -4231,24 +4275,29 @@
static final int DEX_OPT_DEFERRED = 2;
static final int DEX_OPT_FAILED = -1;
- private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
- HashSet<String> done) {
- boolean performed = false;
+ private int performDexOptLI(PackageParser.Package pkg, String instructionSetOverride,
+ boolean forceDex,
+ boolean defer, HashSet<String> done) {
+ final String instructionSet = instructionSetOverride != null ?
+ instructionSetOverride : getAppInstructionSet(pkg.applicationInfo);
+
if (done != null) {
done.add(pkg.packageName);
if (pkg.usesLibraries != null) {
- performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done);
+ performDexOptLibsLI(pkg.usesLibraries, instructionSet, forceDex, defer, done);
}
if (pkg.usesOptionalLibraries != null) {
- performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done);
+ performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSet, forceDex, defer, done);
}
}
+
+ boolean performed = false;
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
String path = pkg.mScanPath;
int ret = 0;
try {
- if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName,
- defer)) {
+ if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path,
+ pkg.packageName, instructionSet, defer)) {
if (!forceDex && defer) {
if (mDeferredDexOpt == null) {
mDeferredDexOpt = new HashSet<PackageParser.Package>();
@@ -4256,10 +4305,12 @@
mDeferredDexOpt.add(pkg);
return DEX_OPT_DEFERRED;
} else {
- Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
+ Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName +
+ " (instructionSet=" + instructionSet + ")");
+
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
- pkg.packageName);
+ pkg.packageName, instructionSet);
pkg.mDidDexOpt = true;
performed = true;
}
@@ -4286,17 +4337,58 @@
return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
}
+ private String getAppInstructionSet(ApplicationInfo info) {
+ String instructionSet = getPreferredInstructionSet();
+
+ if (info.requiredCpuAbi != null) {
+ instructionSet = VMRuntime.getInstructionSet(info.requiredCpuAbi);
+ }
+
+ return instructionSet;
+ }
+
+ private String getAppInstructionSetFromSettings(PackageSetting ps) {
+ String instructionSet = getPreferredInstructionSet();
+
+ if (ps.requiredCpuAbiString != null) {
+ instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString);
+ }
+
+ return instructionSet;
+ }
+
+ private static String getPreferredInstructionSet() {
+ if (sPreferredInstructionSet == null) {
+ sPreferredInstructionSet = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+ }
+
+ return sPreferredInstructionSet;
+ }
+
+ private static List<String> getAllInstructionSets() {
+ final String[] allAbis = Build.SUPPORTED_ABIS;
+ final List<String> allInstructionSets = new ArrayList<String>(allAbis.length);
+
+ for (String abi : allAbis) {
+ final String instructionSet = VMRuntime.getInstructionSet(abi);
+ if (!allInstructionSets.contains(instructionSet)) {
+ allInstructionSets.add(instructionSet);
+ }
+ }
+
+ return allInstructionSets;
+ }
+
private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
boolean inclDependencies) {
HashSet<String> done;
- boolean performed = false;
if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
done = new HashSet<String>();
done.add(pkg.packageName);
} else {
done = null;
}
- return performDexOptLI(pkg, forceDex, defer, done);
+ return performDexOptLI(pkg, null /* instruction set override */, forceDex, defer, done);
}
private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
@@ -4951,6 +5043,8 @@
Log.i(TAG, "removed obsolete native libraries for system package "
+ path);
}
+
+ setInternalAppAbi(pkg, pkgSetting);
} else {
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
/*
@@ -4982,6 +5076,28 @@
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 NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+ if (abi >= 0) {
+ pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[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.
+ pkg.applicationInfo.requiredCpuAbi = null;
+ } else {
+ mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ return null;
+ }
+ handle.close();
}
if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
@@ -5058,8 +5174,7 @@
}
if (allowed) {
if (!mSharedLibraries.containsKey(name)) {
- mSharedLibraries.put(name, new SharedLibraryEntry(null,
- pkg.packageName));
+ mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
} else if (!name.equals(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ name + " already exists; skipping");
@@ -5132,6 +5247,12 @@
// writer
synchronized (mPackages) {
+ 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.
+ adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+ true, forceDex, (scanMode & SCAN_DEFER_DEX) != 0);
+ }
// We don't expect installation to fail beyond this point,
if ((scanMode&SCAN_MONITOR) != 0) {
mAppDirs.put(pkg.mPath, pkg);
@@ -5476,6 +5597,54 @@
return pkg;
}
+ public void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
+ boolean doDexOpt, boolean forceDexOpt, boolean deferDexOpt) {
+ String requiredInstructionSet = null;
+ PackageSetting requirer = null;
+ for (PackageSetting ps : packagesForUser) {
+ if (ps.requiredCpuAbiString != null) {
+ final String instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString);
+ if (requiredInstructionSet != null) {
+ if (!instructionSet.equals(requiredInstructionSet)) {
+ // We have a mismatch between instruction sets (say arm vs arm64).
+ //
+ // TODO: We should rescan all the packages in a shared UID to check if
+ // they do contain shared libs for other ABIs in addition to the ones we've
+ // already extracted. For example, the package might contain both arm64-v8a
+ // and armeabi-v7a shared libs, and we'd have chosen arm64-v8a on 64 bit
+ // devices.
+ String errorMessage = "Instruction set mismatch, " + requirer.pkg.packageName
+ + " requires " + requiredInstructionSet + " whereas " + ps.pkg.packageName
+ + " requires " + instructionSet;
+ Slog.e(TAG, errorMessage);
+
+ reportSettingsProblem(Log.WARN, errorMessage);
+ // Give up, don't bother making any other changes to the package settings.
+ return;
+ }
+ } else {
+ requiredInstructionSet = instructionSet;
+ requirer = ps;
+ }
+ }
+ }
+
+ if (requiredInstructionSet != null) {
+ for (PackageSetting ps : packagesForUser) {
+ if (ps.requiredCpuAbiString == null) {
+ ps.requiredCpuAbiString = requirer.requiredCpuAbiString;
+ ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString;
+
+ Slog.i(TAG, "Adjusting ABI for : " + ps.pkg.packageName + " to " + ps.requiredCpuAbiString);
+ if (doDexOpt) {
+ performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true);
+ mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
+ }
+ }
+ }
+ }
+ }
+
private void setUpCustomResolverActivity(PackageParser.Package pkg) {
synchronized (mPackages) {
mResolverReplaced = true;
@@ -5555,6 +5724,31 @@
pkgSetting.nativeLibraryPathString = nativeLibraryPath;
}
+ // Deduces the required ABI of an upgraded system app.
+ private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) {
+ final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+ final String apkName = getApkName(pkg.applicationInfo.sourceDir);
+
+ // 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.requiredCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
+ pkgSetting.requiredCpuAbiString = Build.SUPPORTED_64_BIT_ABIS[0];
+ } else if (lib.exists()) {
+ pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
+ pkgSetting.requiredCpuAbiString = Build.SUPPORTED_32_BIT_ABIS[0];
+ } else {
+ // This is the case where the app has no native code.
+ pkg.applicationInfo.requiredCpuAbi = null;
+ pkgSetting.requiredCpuAbiString = null;
+ }
+ }
+
private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
throws IOException {
if (!nativeLibraryDir.isDirectory()) {
@@ -8197,7 +8391,8 @@
int mRet;
MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
- String packageName, String dataDir, int uid, UserHandle user) {
+ String packageName, String dataDir, String instructionSet,
+ int uid, UserHandle user) {
super(user);
this.srcArgs = srcArgs;
this.observer = observer;
@@ -8206,7 +8401,7 @@
this.uid = uid;
if (srcArgs != null) {
Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
- targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
+ targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet);
} else {
targetArgs = null;
}
@@ -8315,7 +8510,7 @@
}
private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
- String nativeLibraryPath) {
+ String nativeLibraryPath, String instructionSet) {
final boolean isInAsec;
if (installOnSd(flags)) {
/* Apps on SD card are always in ASEC containers. */
@@ -8333,21 +8528,23 @@
if (isInAsec) {
return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
- installOnSd(flags), installForwardLocked(flags));
+ instructionSet, installOnSd(flags), installForwardLocked(flags));
} else {
- return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
+ return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
+ instructionSet);
}
}
// Used by package mover
- private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
+ private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir,
+ String instructionSet) {
if (installOnSd(flags) || installForwardLocked(flags)) {
String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
+ AsecInstallArgs.RES_FILE_NAME);
- return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
+ return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags),
installForwardLocked(flags));
} else {
- return new FileInstallArgs(packageURI, pkgName, dataDir);
+ return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet);
}
}
@@ -8360,11 +8557,12 @@
final String installerPackageName;
final ManifestDigest manifestDigest;
final UserHandle user;
+ final String instructionSet;
InstallArgs(Uri packageURI,
IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user) {
+ UserHandle user, String instructionSet) {
this.packageURI = packageURI;
this.flags = flags;
this.observer = observer;
@@ -8372,6 +8570,7 @@
this.installerPackageName = installerPackageName;
this.manifestDigest = manifestDigest;
this.user = user;
+ this.instructionSet = instructionSet;
}
abstract void createCopyFile();
@@ -8427,11 +8626,12 @@
FileInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
- params.getUser());
+ params.getUser(), null /* instruction set */);
}
- FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
- super(null, null, null, 0, null, null, null);
+ FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
+ String instructionSet) {
+ super(null, null, null, 0, null, null, null, instructionSet);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
@@ -8439,8 +8639,8 @@
libraryPath = nativeLibraryPath;
}
- FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
- super(packageURI, null, null, 0, null, null, null);
+ FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
+ super(packageURI, null, null, 0, null, null, null, instructionSet);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -8699,7 +8899,10 @@
void cleanUpResourcesLI() {
String sourceDir = getCodePath();
if (cleanUp()) {
- int retCode = mInstaller.rmdex(sourceDir);
+ if (instructionSet == null) {
+ throw new IllegalStateException("instructionSet == null");
+ }
+ int retCode = mInstaller.rmdex(sourceDir, instructionSet);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove dex file for package: "
+ " at location "
@@ -8763,14 +8966,14 @@
AsecInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
- params.getUser());
+ params.getUser(), null /* instruction set */);
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
- boolean isExternal, boolean isForwardLocked) {
+ String instructionSet, boolean isExternal, boolean isForwardLocked) {
super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null);
+ null, null, null, instructionSet);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -8779,18 +8982,19 @@
setCachePath(subStr1);
}
- AsecInstallArgs(String cid, boolean isForwardLocked) {
+ AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) {
super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null);
+ null, null, null, instructionSet);
this.cid = cid;
setCachePath(PackageHelper.getSdDir(cid));
}
- AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
+ AsecInstallArgs(Uri packageURI, String cid, String instructionSet,
+ boolean isExternal, boolean isForwardLocked) {
super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null);
+ null, null, null, instructionSet);
this.cid = cid;
}
@@ -8971,7 +9175,10 @@
void cleanUpResourcesLI() {
String sourceFile = getCodePath();
// Remove dex file
- int retCode = mInstaller.rmdex(sourceFile);
+ if (instructionSet == 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 "
@@ -9356,7 +9563,8 @@
res.removedInfo.args = createInstallArgs(0,
deletedPackage.applicationInfo.sourceDir,
deletedPackage.applicationInfo.publicSourceDir,
- deletedPackage.applicationInfo.nativeLibraryDir);
+ deletedPackage.applicationInfo.nativeLibraryDir,
+ getAppInstructionSet(deletedPackage.applicationInfo));
} else {
res.removedInfo.args = null;
}
@@ -9416,7 +9624,8 @@
private int moveDexFilesLI(PackageParser.Package newPackage) {
int retCode;
if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
- retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
+ retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath,
+ getAppInstructionSet(newPackage.applicationInfo));
if (retCode != 0) {
if (mNoDexOpt) {
/*
@@ -10102,7 +10311,8 @@
// Delete application code and resources
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
- ps.resourcePathString, ps.nativeLibraryPathString);
+ ps.resourcePathString, ps.nativeLibraryPathString,
+ getAppInstructionSetFromSettings(ps));
}
return true;
}
@@ -10472,9 +10682,10 @@
boolean dataOnly = false;
String libDirPath = null;
String asecPath = null;
+ PackageSetting ps = null;
synchronized (mPackages) {
p = mPackages.get(packageName);
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.mPackages.get(packageName);
if(p == null) {
dataOnly = true;
if((ps == null) || (ps.pkg == null)) {
@@ -10505,7 +10716,8 @@
}
}
int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath,
- publicSrcDir, asecPath, pStats);
+ publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps),
+ pStats);
if (res < 0) {
return false;
}
@@ -11694,7 +11906,9 @@
continue;
}
- final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
+ final AsecInstallArgs args = new AsecInstallArgs(cid,
+ getAppInstructionSetFromSettings(ps),
+ isForwardLocked(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())) {
@@ -12012,15 +12226,17 @@
* anyway.
*/
if (returnCode != PackageManager.MOVE_SUCCEEDED) {
- processPendingMove(new MoveParams(null, observer, 0, packageName,
+ processPendingMove(new MoveParams(null, observer, 0, packageName, null,
null, -1, user),
returnCode);
} else {
Message msg = mHandler.obtainMessage(INIT_COPY);
+ final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
- pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
+ pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir,
+ instructionSet);
MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
- pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
+ pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user);
msg.obj = mp;
mHandler.sendMessage(msg);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e4dd2d4..678fc92 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -36,6 +36,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.pm.PackageManagerService.DumpState;
+import java.util.Collection;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -302,6 +303,11 @@
return s;
}
+ Collection<SharedUserSetting> getAllSharedUsersLPw() {
+ return mSharedUsers.values();
+ }
+
+
boolean disableSystemPackageLPw(String name) {
final PackageSetting p = mPackages.get(name);
if(p == null) {