* commit '0fd40cb100bccbd5d9ad6109ca39c818a857f889': Re-implement native library search and copies.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user