am 0fd40cb1: am 80413c9f: Merge "Re-implement native library search and copies."

* commit '0fd40cb100bccbd5d9ad6109ca39c818a857f889':
  Re-implement native library search and copies.
This commit is contained in:
Narayan Kamath
2014-04-10 09:26:44 +00:00
committed by Android Git Automerger
6 changed files with 356 additions and 116 deletions

View File

@@ -674,6 +674,25 @@ public abstract class PackageManager {
*/
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
/**
* Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
* if the system failed to install the package because its packaged native code did not
* match any of the ABIs supported by the system.
*
* @hide
*/
public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -112;
/**
* Internal return code for NativeLibraryHelper methods to indicate that the package
* being processed did not contain any native code. This is placed here only so that
* it can belong to the same value space as the other install failure codes.
*
* @hide
*/
public static final int NO_NATIVE_LIBRARIES = -113;
/**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.

View File

@@ -74,7 +74,14 @@ public class Build {
/** A hardware serial number, if available. Alphanumeric only, case-insensitive. */
public static final String SERIAL = getString("ro.serialno");
/**
* A list of ABIs (in priority) order supported by this device.
*
* @hide
*/
public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(",");
/** Various version strings. */
public static class VERSION {
/**

View File

@@ -16,7 +16,7 @@
package com.android.internal.content;
import android.os.Build;
import android.content.pm.PackageManager;
import android.util.Slog;
import java.io.File;
@@ -31,38 +31,76 @@ public class NativeLibraryHelper {
private static final boolean DEBUG_NATIVE = false;
private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);
/**
* Sums the size of native binaries in an APK.
* A handle to an opened APK. Used as input to the various NativeLibraryHelper
* methods. Allows us to scan and parse the APK exactly once instead of doing
* it multiple times.
*
* @param apkFile APK file to scan for native libraries
* @return size of all native binary files in bytes
* @hide
*/
public static long sumNativeBinariesLI(File apkFile) {
final String cpuAbi = Build.CPU_ABI;
final String cpuAbi2 = Build.CPU_ABI2;
return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2);
public static class ApkHandle {
final String apkPath;
final long apkHandle;
public ApkHandle(String path) {
apkPath = path;
apkHandle = nativeOpenApk(apkPath);
}
public ApkHandle(File apkFile) {
apkPath = apkFile.getPath();
apkHandle = nativeOpenApk(apkPath);
}
public void close() {
nativeClose(apkHandle);
}
}
private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
String cpuAbi, String cpuAbi2);
private static native long nativeOpenApk(String path);
private static native void nativeClose(long handle);
private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
/**
* Sums the size of native binaries in an APK for a given ABI.
*
* @return size of all native binary files in bytes
*/
public static long sumNativeBinariesLI(ApkHandle handle, String abi) {
return nativeSumNativeBinaries(handle.apkHandle, abi);
}
private native static int nativeCopyNativeBinaries(long handle,
String sharedLibraryPath, String abiToCopy);
/**
* Copies native binaries to a shared library directory.
*
* @param apkFile APK file to scan for native libraries
* @param handle APK file to scan for native libraries
* @param sharedLibraryDir directory for libraries to be copied to
* @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
* error code from that class if not
*/
public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
final String cpuAbi = Build.CPU_ABI;
final String cpuAbi2 = Build.CPU_ABI2;
return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi,
cpuAbi2);
public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir,
String abi) {
return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi);
}
/**
* Checks if a given APK contains native code for any of the provided
* {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
* ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
* APK doesn't contain any native code, and
* {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
*/
public static int findSupportedAbi(ApkHandle handle, String[] supportedAbis) {
return nativeFindSupportedAbi(handle.apkHandle, supportedAbis);
}
private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
// Convenience method to call removeNativeBinariesFromDirLI(File)
public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));

View File

@@ -19,11 +19,12 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
#include <ScopedUtfChars.h>
#include <UniquePtr.h>
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
#include <utils/Log.h>
#include <utils/Vector.h>
#include <zlib.h>
@@ -54,17 +55,19 @@
namespace android {
// These match PackageManager.java install codes
typedef enum {
enum install_status_t {
INSTALL_SUCCEEDED = 1,
INSTALL_FAILED_INVALID_APK = -2,
INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
INSTALL_FAILED_CONTAINER_ERROR = -18,
INSTALL_FAILED_INTERNAL_ERROR = -110,
} install_status_t;
INSTALL_FAILED_NO_MATCHING_ABIS = -112,
NO_NATIVE_LIBRARIES = -113
};
typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
// Equivalent to isFilenameSafe
// Equivalent to android.os.FileUtils.isFilenameSafe
static bool
isFilenameSafe(const char* filename)
{
@@ -268,126 +271,252 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
return INSTALL_SUCCEEDED;
}
static install_status_t
iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
iterFunc callFunc, void* callArg) {
ScopedUtfChars filePath(env, javaFilePath);
ScopedUtfChars cpuAbi(env, javaCpuAbi);
ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str()));
if (zipFile.get() == NULL) {
ALOGI("Couldn't open APK %s\n", filePath.c_str());
return INSTALL_FAILED_INVALID_APK;
/*
* An iterator over all shared libraries in a zip file. An entry is
* considered to be a shared library if all of the conditions below are
* satisfied :
*
* - The entry is under the lib/ directory.
* - The entry name ends with ".so" and the entry name starts with "lib",
* an exception is made for entries whose name is "gdbserver".
* - The entry filename is "safe" (as determined by isFilenameSafe).
*
*/
class NativeLibrariesIterator {
private:
NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie)
: mZipFile(zipFile), mCookie(cookie), mLastSlash(NULL) {
fileName[0] = '\0';
}
public:
static NativeLibrariesIterator* create(ZipFileRO* zipFile) {
void* cookie = NULL;
if (!zipFile->startIteration(&cookie)) {
return NULL;
}
return new NativeLibrariesIterator(zipFile, cookie);
}
ZipEntryRO next() {
ZipEntryRO next = NULL;
while ((next = mZipFile->nextEntry(mCookie)) != NULL) {
// Make sure this entry has a filename.
if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
continue;
}
// Make sure we're in the lib directory of the ZIP.
if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
continue;
}
// Make sure the filename is at least to the minimum library name size.
const size_t fileNameLen = strlen(fileName);
static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
if (fileNameLen < minLength) {
continue;
}
const char* lastSlash = strrchr(fileName, '/');
ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
// Exception: If we find the gdbserver binary, return it.
if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
break;
}
// Make sure the filename starts with lib and ends with ".so".
if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
|| strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) {
continue;
}
// Make sure the filename is safe.
if (!isFilenameSafe(lastSlash + 1)) {
continue;
}
mLastSlash = lastSlash;
break;
}
return next;
}
inline const char* currentEntry() const {
return fileName;
}
inline const char* lastSlash() const {
return mLastSlash;
}
virtual ~NativeLibrariesIterator() {
mZipFile->endIteration(mCookie);
}
private:
char fileName[PATH_MAX];
bool hasPrimaryAbi = false;
ZipFileRO* const mZipFile;
void* mCookie;
const char* mLastSlash;
};
void* cookie = NULL;
if (!zipFile->startIteration(&cookie)) {
ALOGI("Couldn't iterate over APK%s\n", filePath.c_str());
static install_status_t
iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
iterFunc callFunc, void* callArg) {
ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
if (zipFile == NULL) {
return INSTALL_FAILED_INVALID_APK;
}
UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
if (it.get() == NULL) {
return INSTALL_FAILED_INVALID_APK;
}
const ScopedUtfChars cpuAbi(env, javaCpuAbi);
if (cpuAbi.c_str() == NULL) {
// This would've thrown, so this return code isn't observable by
// Java.
return INSTALL_FAILED_INVALID_APK;
}
ZipEntryRO entry = NULL;
while ((entry = zipFile->nextEntry(cookie)) != NULL) {
// Make sure this entry has a filename.
if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) {
continue;
}
// Make sure we're in the lib directory of the ZIP.
if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
continue;
}
// Make sure the filename is at least to the minimum library name size.
const size_t fileNameLen = strlen(fileName);
static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
if (fileNameLen < minLength) {
continue;
}
const char* lastSlash = strrchr(fileName, '/');
ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
while ((entry = it->next()) != NULL) {
const char* fileName = it->currentEntry();
const char* lastSlash = it->lastSlash();
// Check to make sure the CPU ABI of this file is one we support.
const char* cpuAbiOffset = fileName + APK_LIB_LEN;
const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
if (cpuAbi.size() == cpuAbiRegionSize
&& *(cpuAbiOffset + cpuAbi.size()) == '/'
&& !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
ALOGV("Using primary ABI %s\n", cpuAbi.c_str());
hasPrimaryAbi = true;
} else if (cpuAbi2.size() == cpuAbiRegionSize
&& *(cpuAbiOffset + cpuAbi2.size()) == '/'
&& !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
/*
* If this library matches both the primary and secondary ABIs,
* only use the primary ABI.
*/
if (hasPrimaryAbi) {
ALOGV("Already saw primary ABI, skipping secondary ABI %s\n", cpuAbi2.c_str());
continue;
} else {
ALOGV("Using secondary ABI %s\n", cpuAbi2.c_str());
}
} else {
ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
continue;
}
// If this is a .so file, check to see if we need to copy it.
if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
&& !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
&& isFilenameSafe(lastSlash + 1))
|| !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1);
if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1);
if (ret != INSTALL_SUCCEEDED) {
ALOGV("Failure for entry %s", lastSlash + 1);
zipFile->endIteration(cookie);
return ret;
}
}
}
zipFile->endIteration(cookie);
return INSTALL_SUCCEEDED;
}
static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) {
const int numAbis = env->GetArrayLength(supportedAbisArray);
Vector<ScopedUtfChars*> supportedAbis;
for (int i = 0; i < numAbis; ++i) {
supportedAbis.add(new ScopedUtfChars(env,
(jstring) env->GetObjectArrayElement(supportedAbisArray, i)));
}
ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
if (zipFile == NULL) {
return INSTALL_FAILED_INVALID_APK;
}
UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
if (it.get() == NULL) {
return INSTALL_FAILED_INVALID_APK;
}
ZipEntryRO entry = NULL;
char fileName[PATH_MAX];
int status = NO_NATIVE_LIBRARIES;
while ((entry = it->next()) != NULL) {
// We're currently in the lib/ directory of the APK, so it does have some native
// code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the
// libraries match.
if (status == NO_NATIVE_LIBRARIES) {
status = INSTALL_FAILED_NO_MATCHING_ABIS;
}
const char* fileName = it->currentEntry();
const char* lastSlash = it->lastSlash();
// Check to see if this CPU ABI matches what we are looking for.
const char* abiOffset = fileName + APK_LIB_LEN;
const size_t abiSize = lastSlash - abiOffset;
for (int i = 0; i < numAbis; i++) {
const ScopedUtfChars* abi = supportedAbis[i];
if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) {
// The entry that comes in first (i.e. with a lower index) has the higher priority.
if (((i < status) && (status >= 0)) || (status < 0) ) {
status = i;
}
}
}
}
for (int i = 0; i < numAbis; ++i) {
delete supportedAbis[i];
}
return status;
}
static jint
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi)
{
return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,
copyFileIfChanged, &javaNativeLibPath);
}
static jlong
com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
jlong apkHandle, jstring javaCpuAbi)
{
size_t totalSize = 0;
iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize);
return totalSize;
}
static jint
com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
jlong apkHandle, jobjectArray javaCpuAbisToSearch)
{
return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
}
static jlong
com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
{
ScopedUtfChars filePath(env, apkPath);
ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str());
return reinterpret_cast<jlong>(zipFile);
}
static void
com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle)
{
delete reinterpret_cast<ZipFileRO*>(apkHandle);
}
static JNINativeMethod gMethods[] = {
{"nativeOpenApk",
"(Ljava/lang/String;)J",
(void *)com_android_internal_content_NativeLibraryHelper_openApk},
{"nativeClose",
"(J)V",
(void *)com_android_internal_content_NativeLibraryHelper_close},
{"nativeCopyNativeBinaries",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
"(JLjava/lang/String;Ljava/lang/String;)I",
(void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
{"nativeSumNativeBinaries",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
"(JLjava/lang/String;)J",
(void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
{"nativeFindSupportedAbi",
"(J[Ljava/lang/String;)I",
(void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
};

View File

@@ -30,6 +30,7 @@ import android.content.pm.PackageParser;
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
@@ -39,10 +40,8 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
import com.android.internal.app.IMediaContainerService;
@@ -343,11 +342,13 @@ public class DefaultContainerService extends IntentService {
// The .apk file
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
// Calculate size of container needed to hold base APK.
final int sizeMb;
try {
sizeMb = calculateContainerSize(codeFile, isForwardLocked);
sizeMb = calculateContainerSize(handle, codeFile, abi, isForwardLocked);
} catch (IOException e) {
Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
return null;
@@ -410,7 +411,14 @@ public class DefaultContainerService extends IntentService {
final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
if (sharedLibraryDir.mkdir()) {
int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir);
int ret = PackageManager.INSTALL_SUCCEEDED;
if (abi >= 0) {
ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
sharedLibraryDir, Build.SUPPORTED_ABIS[abi]);
} else if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
ret = abi;
}
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
PackageHelper.destroySdDir(newCid);
@@ -824,6 +832,17 @@ public class DefaultContainerService extends IntentService {
return availSdMb > sizeMb;
}
private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
try {
return calculateContainerSize(handle, apkFile, abi, forwardLocked);
} finally {
handle.close();
}
}
/**
* Calculate the container size for an APK. Takes into account the
*
@@ -831,7 +850,8 @@ public class DefaultContainerService extends IntentService {
* @return size in megabytes (2^20 bytes)
* @throws IOException when there is a problem reading the file
*/
private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
private int calculateContainerSize(NativeLibraryHelper.ApkHandle apkHandle,
File apkFile, int abiIndex, boolean forwardLocked) throws IOException {
// Calculate size of container needed to hold base APK.
long sizeBytes = apkFile.length();
if (sizeBytes == 0 && !apkFile.exists()) {
@@ -840,7 +860,10 @@ public class DefaultContainerService extends IntentService {
// Check all the native files that need to be copied and add that to the
// container size.
sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
if (abiIndex >= 0) {
sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkHandle,
Build.SUPPORTED_ABIS[abiIndex]);
}
if (forwardLocked) {
sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null);

View File

@@ -60,8 +60,8 @@ import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ContainerEncryptionParams;
@@ -73,14 +73,15 @@ import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
import android.content.pm.ManifestDigest;
import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageStats;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -88,7 +89,6 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.ManifestDigest;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
@@ -99,6 +99,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
@@ -115,7 +116,6 @@ import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Environment.UserEnvironment;
import android.os.UserManager;
import android.security.KeyStore;
import android.security.SystemKeyStore;
@@ -4732,7 +4732,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
try {
if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
Slog.e(TAG, "Unable to copy native libraries");
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
@@ -5291,7 +5292,21 @@ public class PackageManagerService extends IPackageManager.Stub {
* If this is an internal application or our nativeLibraryPath points to
* the app-lib directory, unpack the libraries if necessary.
*/
return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
try {
int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
if (abi >= 0) {
int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
}
return abi;
} finally {
handle.close();
}
}
private void killApplication(String pkgName, int appId, String reason) {
@@ -8180,7 +8195,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
try {
int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
return copyRet;
}
} catch (IOException e) {
@@ -11590,8 +11605,17 @@ public class PackageManagerService extends IPackageManager.Stub {
final File newNativeDir = new File(newNativePath);
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
NativeLibraryHelper.copyNativeBinariesIfNeededLI(
new File(newCodePath), newNativeDir);
// NOTE: We do not report any errors from the APK scan and library
// copy at this point.
NativeLibraryHelper.ApkHandle handle =
new NativeLibraryHelper.ApkHandle(newCodePath);
final int abi = NativeLibraryHelper.findSupportedAbi(
handle, Build.SUPPORTED_ABIS);
if (abi >= 0) {
NativeLibraryHelper.copyNativeBinariesIfNeededLI(
handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
}
handle.close();
}
final int[] users = sUserManager.getUserIds();
for (int user : users) {