Merge "Load libraries directly from apk"
This commit is contained in:
@@ -547,6 +547,7 @@ package android {
|
|||||||
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
|
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
|
||||||
field public static final int exported = 16842768; // 0x1010010
|
field public static final int exported = 16842768; // 0x1010010
|
||||||
field public static final int extraTension = 16843371; // 0x101026b
|
field public static final int extraTension = 16843371; // 0x101026b
|
||||||
|
field public static final int extractNativeLibs = 16843990; // 0x10104d6
|
||||||
field public static final int factor = 16843219; // 0x10101d3
|
field public static final int factor = 16843219; // 0x10101d3
|
||||||
field public static final int fadeDuration = 16843384; // 0x1010278
|
field public static final int fadeDuration = 16843384; // 0x1010278
|
||||||
field public static final int fadeEnabled = 16843390; // 0x101027e
|
field public static final int fadeEnabled = 16843390; // 0x101027e
|
||||||
@@ -8368,6 +8369,7 @@ package android.content.pm {
|
|||||||
field public static final int FLAG_ALLOW_TASK_REPARENTING = 32; // 0x20
|
field public static final int FLAG_ALLOW_TASK_REPARENTING = 32; // 0x20
|
||||||
field public static final int FLAG_DEBUGGABLE = 2; // 0x2
|
field public static final int FLAG_DEBUGGABLE = 2; // 0x2
|
||||||
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
|
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
|
||||||
|
field public static final int FLAG_EXTRACT_NATIVE_LIBS = 268435456; // 0x10000000
|
||||||
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
|
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
|
||||||
field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000
|
field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000
|
||||||
field public static final int FLAG_HAS_CODE = 4; // 0x4
|
field public static final int FLAG_HAS_CODE = 4; // 0x4
|
||||||
@@ -17515,7 +17517,7 @@ package android.net.http {
|
|||||||
method public static android.net.http.HttpResponseCache getInstalled();
|
method public static android.net.http.HttpResponseCache getInstalled();
|
||||||
method public int getNetworkCount();
|
method public int getNetworkCount();
|
||||||
method public int getRequestCount();
|
method public int getRequestCount();
|
||||||
method public static android.net.http.HttpResponseCache install(java.io.File, long) throws java.io.IOException;
|
method public static synchronized android.net.http.HttpResponseCache install(java.io.File, long) throws java.io.IOException;
|
||||||
method public long maxSize();
|
method public long maxSize();
|
||||||
method public java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
|
method public java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
|
||||||
method public long size();
|
method public long size();
|
||||||
@@ -41519,7 +41521,7 @@ package java.lang {
|
|||||||
method public static double nextUp(double);
|
method public static double nextUp(double);
|
||||||
method public static float nextUp(float);
|
method public static float nextUp(float);
|
||||||
method public static double pow(double, double);
|
method public static double pow(double, double);
|
||||||
method public static synchronized double random();
|
method public static double random();
|
||||||
method public static double rint(double);
|
method public static double rint(double);
|
||||||
method public static long round(double);
|
method public static long round(double);
|
||||||
method public static int round(float);
|
method public static int round(float);
|
||||||
|
|||||||
@@ -617,6 +617,7 @@ package android {
|
|||||||
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
|
field public static final int expandableListViewWhiteStyle = 16843446; // 0x10102b6
|
||||||
field public static final int exported = 16842768; // 0x1010010
|
field public static final int exported = 16842768; // 0x1010010
|
||||||
field public static final int extraTension = 16843371; // 0x101026b
|
field public static final int extraTension = 16843371; // 0x101026b
|
||||||
|
field public static final int extractNativeLibs = 16843990; // 0x10104d6
|
||||||
field public static final int factor = 16843219; // 0x10101d3
|
field public static final int factor = 16843219; // 0x10101d3
|
||||||
field public static final int fadeDuration = 16843384; // 0x1010278
|
field public static final int fadeDuration = 16843384; // 0x1010278
|
||||||
field public static final int fadeEnabled = 16843390; // 0x101027e
|
field public static final int fadeEnabled = 16843390; // 0x101027e
|
||||||
@@ -8616,6 +8617,7 @@ package android.content.pm {
|
|||||||
field public static final int FLAG_ALLOW_TASK_REPARENTING = 32; // 0x20
|
field public static final int FLAG_ALLOW_TASK_REPARENTING = 32; // 0x20
|
||||||
field public static final int FLAG_DEBUGGABLE = 2; // 0x2
|
field public static final int FLAG_DEBUGGABLE = 2; // 0x2
|
||||||
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
|
field public static final int FLAG_EXTERNAL_STORAGE = 262144; // 0x40000
|
||||||
|
field public static final int FLAG_EXTRACT_NATIVE_LIBS = 268435456; // 0x10000000
|
||||||
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
|
field public static final int FLAG_FACTORY_TEST = 16; // 0x10
|
||||||
field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000
|
field public static final int FLAG_FULL_BACKUP_ONLY = 67108864; // 0x4000000
|
||||||
field public static final int FLAG_HAS_CODE = 4; // 0x4
|
field public static final int FLAG_HAS_CODE = 4; // 0x4
|
||||||
@@ -18843,7 +18845,7 @@ package android.net.http {
|
|||||||
method public static android.net.http.HttpResponseCache getInstalled();
|
method public static android.net.http.HttpResponseCache getInstalled();
|
||||||
method public int getNetworkCount();
|
method public int getNetworkCount();
|
||||||
method public int getRequestCount();
|
method public int getRequestCount();
|
||||||
method public static android.net.http.HttpResponseCache install(java.io.File, long) throws java.io.IOException;
|
method public static synchronized android.net.http.HttpResponseCache install(java.io.File, long) throws java.io.IOException;
|
||||||
method public long maxSize();
|
method public long maxSize();
|
||||||
method public java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
|
method public java.net.CacheRequest put(java.net.URI, java.net.URLConnection) throws java.io.IOException;
|
||||||
method public long size();
|
method public long size();
|
||||||
@@ -44055,7 +44057,7 @@ package java.lang {
|
|||||||
method public static double nextUp(double);
|
method public static double nextUp(double);
|
||||||
method public static float nextUp(float);
|
method public static float nextUp(float);
|
||||||
method public static double pow(double, double);
|
method public static double pow(double, double);
|
||||||
method public static synchronized double random();
|
method public static double random();
|
||||||
method public static double rint(double);
|
method public static double rint(double);
|
||||||
method public static long round(double);
|
method public static long round(double);
|
||||||
method public static int round(float);
|
method public static int round(float);
|
||||||
|
|||||||
@@ -345,6 +345,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27;
|
public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set installer extracts native libs from .apk files.
|
||||||
|
*/
|
||||||
|
public static final int FLAG_EXTRACT_NATIVE_LIBS = 1<<28;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value for {@link #flags}: true if code from this application will need to be
|
* Value for {@link #flags}: true if code from this application will need to be
|
||||||
* loaded into other applications' processes. On devices that support multiple
|
* loaded into other applications' processes. On devices that support multiple
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ public class PackageParser {
|
|||||||
|
|
||||||
public final boolean coreApp;
|
public final boolean coreApp;
|
||||||
public final boolean multiArch;
|
public final boolean multiArch;
|
||||||
|
public final boolean extractNativeLibs;
|
||||||
|
|
||||||
public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
|
public PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
|
||||||
String[] splitCodePaths, int[] splitRevisionCodes) {
|
String[] splitCodePaths, int[] splitRevisionCodes) {
|
||||||
@@ -283,6 +284,7 @@ public class PackageParser {
|
|||||||
this.splitRevisionCodes = splitRevisionCodes;
|
this.splitRevisionCodes = splitRevisionCodes;
|
||||||
this.coreApp = baseApk.coreApp;
|
this.coreApp = baseApk.coreApp;
|
||||||
this.multiArch = baseApk.multiArch;
|
this.multiArch = baseApk.multiArch;
|
||||||
|
this.extractNativeLibs = baseApk.extractNativeLibs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAllCodePaths() {
|
public List<String> getAllCodePaths() {
|
||||||
@@ -309,10 +311,12 @@ public class PackageParser {
|
|||||||
public final Signature[] signatures;
|
public final Signature[] signatures;
|
||||||
public final boolean coreApp;
|
public final boolean coreApp;
|
||||||
public final boolean multiArch;
|
public final boolean multiArch;
|
||||||
|
public final boolean extractNativeLibs;
|
||||||
|
|
||||||
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
|
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
|
||||||
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
|
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
|
||||||
Signature[] signatures, boolean coreApp, boolean multiArch) {
|
Signature[] signatures, boolean coreApp, boolean multiArch,
|
||||||
|
boolean extractNativeLibs) {
|
||||||
this.codePath = codePath;
|
this.codePath = codePath;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.splitName = splitName;
|
this.splitName = splitName;
|
||||||
@@ -323,6 +327,7 @@ public class PackageParser {
|
|||||||
this.signatures = signatures;
|
this.signatures = signatures;
|
||||||
this.coreApp = coreApp;
|
this.coreApp = coreApp;
|
||||||
this.multiArch = multiArch;
|
this.multiArch = multiArch;
|
||||||
|
this.extractNativeLibs = extractNativeLibs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1269,6 +1274,7 @@ public class PackageParser {
|
|||||||
int revisionCode = 0;
|
int revisionCode = 0;
|
||||||
boolean coreApp = false;
|
boolean coreApp = false;
|
||||||
boolean multiArch = false;
|
boolean multiArch = false;
|
||||||
|
boolean extractNativeLibs = true;
|
||||||
|
|
||||||
for (int i = 0; i < attrs.getAttributeCount(); i++) {
|
for (int i = 0; i < attrs.getAttributeCount(); i++) {
|
||||||
final String attr = attrs.getAttributeName(i);
|
final String attr = attrs.getAttributeName(i);
|
||||||
@@ -1307,14 +1313,17 @@ public class PackageParser {
|
|||||||
final String attr = attrs.getAttributeName(i);
|
final String attr = attrs.getAttributeName(i);
|
||||||
if ("multiArch".equals(attr)) {
|
if ("multiArch".equals(attr)) {
|
||||||
multiArch = attrs.getAttributeBooleanValue(i, false);
|
multiArch = attrs.getAttributeBooleanValue(i, false);
|
||||||
break;
|
}
|
||||||
|
if ("extractNativeLibs".equals(attr)) {
|
||||||
|
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
|
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
|
||||||
revisionCode, installLocation, verifiers, signatures, coreApp, multiArch);
|
revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
|
||||||
|
extractNativeLibs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2567,6 +2576,12 @@ public class PackageParser {
|
|||||||
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
|
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sa.getBoolean(
|
||||||
|
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
|
||||||
|
true)) {
|
||||||
|
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
|
||||||
|
}
|
||||||
|
|
||||||
String str;
|
String str;
|
||||||
str = sa.getNonConfigurationString(
|
str = sa.getNonConfigurationString(
|
||||||
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
|
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import android.content.pm.PackageParser.PackageLite;
|
|||||||
import android.content.pm.PackageParser.PackageParserException;
|
import android.content.pm.PackageParser.PackageParserException;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.SELinux;
|
import android.os.SELinux;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -74,6 +75,7 @@ public class NativeLibraryHelper {
|
|||||||
|
|
||||||
final long[] apkHandles;
|
final long[] apkHandles;
|
||||||
final boolean multiArch;
|
final boolean multiArch;
|
||||||
|
final boolean extractNativeLibs;
|
||||||
|
|
||||||
public static Handle create(File packageFile) throws IOException {
|
public static Handle create(File packageFile) throws IOException {
|
||||||
try {
|
try {
|
||||||
@@ -86,14 +88,16 @@ public class NativeLibraryHelper {
|
|||||||
|
|
||||||
public static Handle create(Package pkg) throws IOException {
|
public static Handle create(Package pkg) throws IOException {
|
||||||
return create(pkg.getAllCodePaths(),
|
return create(pkg.getAllCodePaths(),
|
||||||
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0);
|
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0,
|
||||||
|
(pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Handle create(PackageLite lite) throws IOException {
|
public static Handle create(PackageLite lite) throws IOException {
|
||||||
return create(lite.getAllCodePaths(), lite.multiArch);
|
return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Handle create(List<String> codePaths, boolean multiArch) throws IOException {
|
private static Handle create(List<String> codePaths, boolean multiArch,
|
||||||
|
boolean extractNativeLibs) throws IOException {
|
||||||
final int size = codePaths.size();
|
final int size = codePaths.size();
|
||||||
final long[] apkHandles = new long[size];
|
final long[] apkHandles = new long[size];
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
@@ -108,12 +112,13 @@ public class NativeLibraryHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Handle(apkHandles, multiArch);
|
return new Handle(apkHandles, multiArch, extractNativeLibs);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle(long[] apkHandles, boolean multiArch) {
|
Handle(long[] apkHandles, boolean multiArch, boolean extractNativeLibs) {
|
||||||
this.apkHandles = apkHandles;
|
this.apkHandles = apkHandles;
|
||||||
this.multiArch = multiArch;
|
this.multiArch = multiArch;
|
||||||
|
this.extractNativeLibs = extractNativeLibs;
|
||||||
mGuard.open("close");
|
mGuard.open("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +151,8 @@ public class NativeLibraryHelper {
|
|||||||
|
|
||||||
private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
|
private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
|
||||||
|
|
||||||
private native static int nativeCopyNativeBinaries(long handle,
|
private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath,
|
||||||
String sharedLibraryPath, String abiToCopy);
|
String abiToCopy, boolean extractNativeLibs, boolean hasNativeBridge);
|
||||||
|
|
||||||
private static long sumNativeBinaries(Handle handle, String abi) {
|
private static long sumNativeBinaries(Handle handle, String abi) {
|
||||||
long sum = 0;
|
long sum = 0;
|
||||||
@@ -167,7 +172,8 @@ public class NativeLibraryHelper {
|
|||||||
*/
|
*/
|
||||||
public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
|
public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
|
||||||
for (long apkHandle : handle.apkHandles) {
|
for (long apkHandle : handle.apkHandles) {
|
||||||
int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi);
|
int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi,
|
||||||
|
handle.extractNativeLibs, HAS_NATIVE_BRIDGE);
|
||||||
if (res != INSTALL_SUCCEEDED) {
|
if (res != INSTALL_SUCCEEDED) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -218,7 +224,8 @@ public class NativeLibraryHelper {
|
|||||||
/**
|
/**
|
||||||
* Remove the native binaries of a given package. This deletes the files
|
* Remove the native binaries of a given package. This deletes the files
|
||||||
*/
|
*/
|
||||||
public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot, boolean deleteRootDir) {
|
public static void removeNativeBinariesFromDirLI(File nativeLibraryRoot,
|
||||||
|
boolean deleteRootDir) {
|
||||||
if (DEBUG_NATIVE) {
|
if (DEBUG_NATIVE) {
|
||||||
Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
|
Slog.w(TAG, "Deleting native binaries from: " + nativeLibraryRoot.getPath());
|
||||||
}
|
}
|
||||||
@@ -247,7 +254,8 @@ public class NativeLibraryHelper {
|
|||||||
// asked to or this will prevent installation of future updates.
|
// asked to or this will prevent installation of future updates.
|
||||||
if (deleteRootDir) {
|
if (deleteRootDir) {
|
||||||
if (!nativeLibraryRoot.delete()) {
|
if (!nativeLibraryRoot.delete()) {
|
||||||
Slog.w(TAG, "Could not delete native binary directory: " + nativeLibraryRoot.getPath());
|
Slog.w(TAG, "Could not delete native binary directory: " +
|
||||||
|
nativeLibraryRoot.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,6 +424,9 @@ public class NativeLibraryHelper {
|
|||||||
// We don't care about the other return values for now.
|
// We don't care about the other return values for now.
|
||||||
private static final int BITCODE_PRESENT = 1;
|
private static final int BITCODE_PRESENT = 1;
|
||||||
|
|
||||||
|
private static final boolean HAS_NATIVE_BRIDGE =
|
||||||
|
!"0".equals(SystemProperties.get("ro.dalvik.vm.native.bridge", "0"));
|
||||||
|
|
||||||
private static native int hasRenderscriptBitcode(long apkHandle);
|
private static native int hasRenderscriptBitcode(long apkHandle);
|
||||||
|
|
||||||
public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
|
public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
|
||||||
|
|||||||
@@ -586,6 +586,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
|
|||||||
char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
|
char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
|
||||||
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
|
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
|
||||||
char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
|
char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
|
||||||
|
char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];
|
||||||
|
|
||||||
bool checkJni = false;
|
bool checkJni = false;
|
||||||
property_get("dalvik.vm.checkjni", propBuf, "");
|
property_get("dalvik.vm.checkjni", propBuf, "");
|
||||||
@@ -859,6 +860,18 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
|
|||||||
// Dalvik-cache pruning counter.
|
// Dalvik-cache pruning counter.
|
||||||
parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
|
parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
|
||||||
"-Xzygote-max-boot-retry=");
|
"-Xzygote-max-boot-retry=");
|
||||||
|
#if defined(__LP64__)
|
||||||
|
const char* cpu_abilist_property_name = "ro.product.cpu.abilist64";
|
||||||
|
#else
|
||||||
|
const char* cpu_abilist_property_name = "ro.product.cpu.abilist32";
|
||||||
|
#endif // defined(__LP64__)
|
||||||
|
property_get(cpu_abilist_property_name, propBuf, "");
|
||||||
|
if (propBuf[0] == '\0') {
|
||||||
|
ALOGE("%s is not expected to be empty", cpu_abilist_property_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf);
|
||||||
|
addOption(cpuAbiListBuf);
|
||||||
|
|
||||||
initArgs.version = JNI_VERSION_1_4;
|
initArgs.version = JNI_VERSION_1_4;
|
||||||
initArgs.options = mOptions.editArray();
|
initArgs.options = mOptions.editArray();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -173,7 +174,11 @@ sumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char
|
|||||||
static install_status_t
|
static install_status_t
|
||||||
copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
|
copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
|
||||||
{
|
{
|
||||||
jstring* javaNativeLibPath = (jstring*) arg;
|
void** args = reinterpret_cast<void**>(arg);
|
||||||
|
jstring* javaNativeLibPath = (jstring*) args[0];
|
||||||
|
jboolean extractNativeLibs = *(jboolean*) args[1];
|
||||||
|
jboolean hasNativeBridge = *(jboolean*) args[2];
|
||||||
|
|
||||||
ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
|
ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
|
||||||
|
|
||||||
size_t uncompLen;
|
size_t uncompLen;
|
||||||
@@ -181,13 +186,31 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
|
|||||||
long crc;
|
long crc;
|
||||||
time_t modTime;
|
time_t modTime;
|
||||||
|
|
||||||
if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) {
|
int method;
|
||||||
|
off64_t offset;
|
||||||
|
|
||||||
|
if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, NULL, &offset, &when, &crc)) {
|
||||||
ALOGD("Couldn't read zip entry info\n");
|
ALOGD("Couldn't read zip entry info\n");
|
||||||
return INSTALL_FAILED_INVALID_APK;
|
return INSTALL_FAILED_INVALID_APK;
|
||||||
} else {
|
}
|
||||||
struct tm t;
|
|
||||||
ZipUtils::zipTimeToTimespec(when, &t);
|
if (!extractNativeLibs) {
|
||||||
modTime = mktime(&t);
|
// check if library is uncompressed and page-aligned
|
||||||
|
if (method != ZipFileRO::kCompressStored) {
|
||||||
|
ALOGD("Library '%s' is compressed - will not be able to open it directly from apk.\n",
|
||||||
|
fileName);
|
||||||
|
return INSTALL_FAILED_INVALID_APK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset % PAGE_SIZE != 0) {
|
||||||
|
ALOGD("Library '%s' is not page-aligned - will not be able to open it directly from"
|
||||||
|
" apk.\n", fileName);
|
||||||
|
return INSTALL_FAILED_INVALID_APK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasNativeBridge) {
|
||||||
|
return INSTALL_SUCCEEDED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build local file path
|
// Build local file path
|
||||||
@@ -208,6 +231,9 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only copy out the native file if it's different.
|
// Only copy out the native file if it's different.
|
||||||
|
struct tm t;
|
||||||
|
ZipUtils::zipTimeToTimespec(when, &t);
|
||||||
|
modTime = mktime(&t);
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
|
if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
|
||||||
return INSTALL_SUCCEEDED;
|
return INSTALL_SUCCEEDED;
|
||||||
@@ -465,10 +491,12 @@ static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supported
|
|||||||
|
|
||||||
static jint
|
static jint
|
||||||
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
|
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
|
||||||
jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi)
|
jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi,
|
||||||
|
jboolean extractNativeLibs, jboolean hasNativeBridge)
|
||||||
{
|
{
|
||||||
|
void* args[] = { &javaNativeLibPath, &extractNativeLibs, &hasNativeBridge };
|
||||||
return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,
|
return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,
|
||||||
copyFileIfChanged, &javaNativeLibPath);
|
copyFileIfChanged, reinterpret_cast<void*>(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong
|
static jlong
|
||||||
@@ -548,7 +576,7 @@ static JNINativeMethod gMethods[] = {
|
|||||||
"(J)V",
|
"(J)V",
|
||||||
(void *)com_android_internal_content_NativeLibraryHelper_close},
|
(void *)com_android_internal_content_NativeLibraryHelper_close},
|
||||||
{"nativeCopyNativeBinaries",
|
{"nativeCopyNativeBinaries",
|
||||||
"(JLjava/lang/String;Ljava/lang/String;)I",
|
"(JLjava/lang/String;Ljava/lang/String;ZZ)I",
|
||||||
(void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
|
(void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
|
||||||
{"nativeSumNativeBinaries",
|
{"nativeSumNativeBinaries",
|
||||||
"(JLjava/lang/String;)J",
|
"(JLjava/lang/String;)J",
|
||||||
|
|||||||
@@ -1021,6 +1021,10 @@
|
|||||||
<p>The default value of this attribute is <code>false</code>. -->
|
<p>The default value of this attribute is <code>false</code>. -->
|
||||||
<attr name="resumeWhilePausing" format="boolean" />
|
<attr name="resumeWhilePausing" format="boolean" />
|
||||||
|
|
||||||
|
<!-- When set installer will extract native libraries. If set to false
|
||||||
|
libraries in the apk must be stored and page-aligned. -->
|
||||||
|
<attr name="extractNativeLibs" format="boolean"/>
|
||||||
|
|
||||||
<!-- The <code>manifest</code> tag is the root of an
|
<!-- The <code>manifest</code> tag is the root of an
|
||||||
<code>AndroidManifest.xml</code> file,
|
<code>AndroidManifest.xml</code> file,
|
||||||
describing the contents of an Android package (.apk) file. One
|
describing the contents of an Android package (.apk) file. One
|
||||||
@@ -1151,8 +1155,8 @@
|
|||||||
@hide -->
|
@hide -->
|
||||||
<attr name="usesCleartextTraffic" />
|
<attr name="usesCleartextTraffic" />
|
||||||
<attr name="multiArch" />
|
<attr name="multiArch" />
|
||||||
|
<attr name="extractNativeLibs" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<!-- The <code>permission</code> tag declares a security permission that can be
|
<!-- The <code>permission</code> tag declares a security permission that can be
|
||||||
used to control access from other packages to specific components or
|
used to control access from other packages to specific components or
|
||||||
features in your package (or other packages). See the
|
features in your package (or other packages). See the
|
||||||
|
|||||||
@@ -2598,4 +2598,5 @@
|
|||||||
<public type="style" name="Theme.DeviceDefault.Dialog.Alert" />
|
<public type="style" name="Theme.DeviceDefault.Dialog.Alert" />
|
||||||
<public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
|
<public type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" />
|
||||||
|
|
||||||
|
<public type="attr" name="extractNativeLibs" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
libnativehelper
|
libnativehelper
|
||||||
|
|
||||||
LOCAL_MODULE := libframeworks_coretests_jni
|
LOCAL_MODULE := libframeworks_coretests_jni
|
||||||
|
|
||||||
|
# this does not prevent build system
|
||||||
|
# from installing library to /system/lib
|
||||||
LOCAL_MODULE_TAGS := tests
|
LOCAL_MODULE_TAGS := tests
|
||||||
|
|
||||||
|
# .. we want to avoid that... so we put it somewhere
|
||||||
|
# bionic linker cant find it without outside help (nativetests):
|
||||||
|
LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
|
||||||
|
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ static JNINativeMethod sMethods[] = {
|
|||||||
{ "checkFunction", "()I", (void*) checkFunction },
|
{ "checkFunction", "()I", (void*) checkFunction },
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_com_android_framework_coretests_JNITests(JNIEnv* env) {
|
int register_com_android_frameworks_coretests_JNITests(JNIEnv* env) {
|
||||||
return jniRegisterNativeMethods(env, "com/android/framework/coretests/JNITests", sMethods,
|
return jniRegisterNativeMethods(env, "com/android/frameworks/coretests/JNITests", sMethods,
|
||||||
NELEM(sMethods));
|
NELEM(sMethods));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
|||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = android::register_com_android_framework_coretests_JNITests(e)) < 0) {
|
if ((status = android::register_com_android_frameworks_coretests_JNITests(e)) < 0) {
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
LOCAL_PATH:= $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := $(call all-subdir-java-files)
|
||||||
|
|
||||||
|
LOCAL_PACKAGE_NAME := install_jni_lib_open_from_apk
|
||||||
|
|
||||||
|
LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS := -0
|
||||||
|
LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES := true
|
||||||
|
|
||||||
|
include $(FrameworkCoreTests_BUILD_PACKAGE)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.android.frameworks.coretests.install_jni_lib_open_from_apk">
|
||||||
|
|
||||||
|
<application android:hasCode="true" android:label="@string/app_name" android:extractNativeLibs="false">
|
||||||
|
<activity android:name="com.android.frameworks.coretests.OpenFromApkActivity"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2015 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string name="app_name">Load From Apk Test</string>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.frameworks.coretests;
|
||||||
|
|
||||||
|
public class JNITests {
|
||||||
|
static {
|
||||||
|
System.loadLibrary("frameworks_coretests_jni");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native int checkFunction();
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.frameworks.coretests;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class OpenFromApkActivity extends Activity {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
TextView tv = new TextView(this);
|
||||||
|
|
||||||
|
int i = JNITests.checkFunction();
|
||||||
|
|
||||||
|
tv.setText("All is well: i=" + i);
|
||||||
|
|
||||||
|
setContentView(tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user