您的位置:首页 > 其它

PackageManagerService安装lib库

2017-09-02 14:18 375 查看
          APP开发都会用到动态链路库,即so库。在代码中通常通过System.loadLibrary()来加载so库,但也经常会碰到App在一些手机上没有问题,在另外一些手机上使用时出错,如java.lang.UnsatisfiedLinkError,就是和动态链路库加载错误有关。想要解决这类问题,就要了解系统在安装APK的时候是如何处理so库的。下面从源码上分析这一过程。

       在安装APK时,若APK包含lib库,PKMS也会相应的安装lib库。PKMS安装lib代码在扫描APK函数scanPackageDirtyLI()中。

       安装lib库分为三部分:

1. 创建存放lib库目录

2. 解析APK文件,匹配ABI并拷贝对应ABI目录下的 lib文件到相应目录

3. 在data/data/apk相关目录 下的lib 创建软链接到真正放lib的地方

    在scanPackageDirtyLI()扫描APK中,调用了derivePackageAbi()来安装lib库。

if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
derivePackageAbi(pkg, scanFile, cpuAbiOverride, true /* extract libs */);

// Some system apps still use directory structure for native libraries
// in which case we might end up not detecting abi solely based on apk
// structure. Try to detect abi based on directory structure.
if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() &&
pkg.applicationInfo.primaryCpuAbi == nul
4000
l) {
setBundledAppAbisAndRoots(pkg, pkgSetting);
setNativeLibraryPaths(pkg);
}

} else {
if ((scanFlags & SCAN_MOVE) != 0) {
// We haven't run dex-opt for this move (since we've moved the compiled output too)
// but we already have this packages package info in the PackageSetting. We just
// use that and derive the native library path based on the new codepath.
pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString;
pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString;
}

// Set native library paths again. For moves, the path will be updated based on the
// ABIs we've determined above. For non-moves, the path will be updated based on the
// ABIs we determined during compilation, but the path will depend on the final
// package path (after the rename away from the stage path).
setNativeLibraryPaths(pkg);
}


    以上代码表示如果APK是新安装的,则会调用derivePackageAbi()来安装lib库。derivePackageAbi()如下:

private void derivePackageAbi(PackageParser.Package pkg, File scanFile,
String cpuAbiOverride, boolean extractLibs)
throws PackageManagerException {
// TODO: We can probably be smarter about this stuff. For installed apps,
// we can calculate this information at install time once and for all. For
// system apps, we can probably assume that this information doesn't change
// after the first boot scan. As things stand, we do lots of unnecessary work.

// Give ourselves some initial paths; we'll come back for another
// pass once we've determined ABI below.
setNativeLibraryPaths(pkg);

// We would never need to extract libs for forward-locked and external packages,
// since the container service will do it for us. We shouldn't attempt to
// extract libs from system app when it was not updated.
if (pkg.isForwardLocked() || pkg.applicationInfo.isExternalAsec() ||
(isSystemApp(pkg) && !pkg.isUpdatedSystemApp())) {
extractLibs = false;
}

final String nativeLibraryRootStr = pkg.applicationInfo.nativeLibraryRootDir;
final boolean useIsaSpecificSubdirs = pkg.applicationInfo.nativeLibraryRootRequiresIsa;

NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(pkg);
// TODO(multiArch): This can be null for apps that didn't go through the
// usual installation process. We can calculate it again, like we
// do during install time.
//
// TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
// unnecessary.
final File nativeLibraryRoot = new File(nativeLibraryRootStr);

// Null out the abis so that they can be recalculated.
pkg.applicationInfo.primaryCpuAbi = null;
pkg.applicationInfo.secondaryCpuAbi = null;
if (isMultiArch(pkg.applicationInfo)) {
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
if (pkg.cpuAbiOverride != null
&& !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
}

int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
if (extractLibs) {
abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
}
}

maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 32 bit native libs for multiarch app.", abi32);

if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (extractLibs) {
abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
}
}

maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 64 bit native libs for multiarch app.", abi64);

if (abi64 >= 0) {
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
}

if (abi32 >= 0) {
final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
if (abi64 >= 0) {
if (pkg.use32bitAbi) {
pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
pkg.applicationInfo.primaryCpuAbi = abi;
} else {
pkg.applicationInfo.secondaryCpuAbi = abi;
}
} else {
pkg.applicationInfo.primaryCpuAbi = abi;
}
}

} else {
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;

// Enable gross and lame hacks for apps that are built with old
// SDK tools. We must scan their APKs for renderscript bitcode and
// not launch them if it's present. Don't bother checking on devices
// that don't have 64 bit support.
boolean needsRenderScriptOverride = false;
if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
abiList = Build.SUPPORTED_32_BIT_ABIS;
needsRenderScriptOverride = true;
}

final int copyRet;
if (extractLibs) {
copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
} else {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
}

if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Error unpackaging native libs for app, errorCode=" + copyRet);
}

if (copyRet >= 0) {
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
} else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
} else if (needsRenderScriptOverride) {
pkg.applicationInfo.primaryCpuAbi = abiList[0];
}
}
} catch (IOException ioe) {
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
} finally {
IoUtils.closeQuietly(handle);
}

// Now that we've calculated the ABIs and determined if it's an internal app,
// we will go ahead and populate the nativeLibraryPath.
setNativeLibraryPaths(pkg);
}


derivePackageAbi()做了以下几件事:

1.调用setNativeLibraryPaths(pkg)创建lib目录

2.  如果需要提取lib库,即extractLibs为true,则调用NativeLibraryHelper.copyNativeBinariesForSupportedAbi()匹配ABI并拷贝对应 ABI目录下的 lib文件到相应目录

     如果不需要lib库,则调用NativeLibraryHelper.findSupportedAbi()匹配ABI。

     对于新安装的APK,都是需要提取lib库,即extractLibs为true。

3.设置APKprimaryCpuAbi、secondaryCpuAbi(APK设置了支持多核架构时设置)。

     下面具体实现,创建lib目录方法setNativeLibraryPaths(pkg)如下:

private void setNativeLibraryPaths(PackageParser.Package pkg) {
final ApplicationInfo info = pkg.applicationInfo;
final String codePath = pkg.codePath;
final File codeFile = new File(codePath);
final boolean bundledApp = info.isSystemApp() && !info.isUpdatedSystemApp();
final boolean asecApp = info.isForwardLocked() || info.isExternalAsec();

info.nativeLibraryRootDir = null;
info.nativeLibraryRootRequiresIsa = false;
info.nativeLibraryDir = null;
info.secondaryNativeLibraryDir = null;

if (isApkFile(codeFile)) {
// Monolithic install
if (bundledApp) {
// If "/system/lib64/apkname" exists, assume that is the per-package
// native library directory to use; otherwise use "/system/lib/apkname".
final String apkRoot = calculateBundledApkRoot(info.sourceDir);
final boolean is64Bit = VMRuntime.is64BitInstructionSet(
getPrimaryInstructionSet(info));

// This is a bundled system app so choose the path based on the ABI.
// if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this
// is just the default path.
final String apkName = deriveCodePathName(codePath);
final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
info.nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir,
apkName).getAbsolutePath();

if (info.secondaryCpuAbi != null) {
final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
info.secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot),
secondaryLibDir, apkName).getAbsolutePath();
}
} else if (asecApp) {
info.nativeLibraryRootDir = new File(codeFile.getParentFile(), LIB_DIR_NAME)
.getAbsolutePath();
} else {
final String apkName = deriveCodePathName(codePath);
info.nativeLibraryRootDir = new File(mAppLib32InstallDir, apkName)
.getAbsolutePath();
}

info.nativeLibraryRootRequiresIsa = false;
info.nativeLibraryDir = info.nativeLibraryRootDir;
} else {
// Cluster install
info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
info.nativeLibraryRootRequiresIsa = true;

info.nativeLibraryDir = new File(info.nativeLibraryRootDir,
getPrimaryInstructionSet(info)).getAbsolutePath();

if (info.secondaryCpuAbi != null) {
info.secondaryNativeLibraryDir = new File(info.nativeLibraryRootDir,
VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath();
}
}
}


若是系统内置APK,则在系统APK目录下创建lib目录,如system/lib、vendor/lib,若是用户自己安装的APK,则得data目录下创建lib目录,如data/app-lib下建apk目录。

创建完lib目录后,就是拷贝so库了。为了在不同的手机平台下能运行,开发这也会准备不同CPU架构下的so库。
在Eclipse或者Android Studio的project\app\src\main\jniLibs\经常可以看到下面这样的部分



同样不同的手机CPU架构不同,因此支持的ABI也不同,通过命令可以查看手机支持的abi

adb shell getprop ro.product.cpu.abilist,查看手机配置项。

如下是华为某手机所支持的ABI。

[ro.product.cpu.abilist32]: [armeabi-v7a,armeabi]

[ro.product.cpu.abilist64]: [arm64-v8a]

[ro.product.cpu.abilist]: [arm64-v8a,armeabi-v7a,armeabi]

可以看出该手机支持的abi有 [arm64-v8a,armeabi-v7a,armeabi],若某APK仅提供了x86构架下的so库,则APK没法在该手机上运行。

手机支持的abi和apk提供的so库都不止一个,具体该如何匹配,即最后到底用了那个架构的so库呢。匹配原则在NativeLibraryHelper.copyNativeBinariesForSupportedAbi()中:

public static int copyNativeBinariesForSupportedAbi(Handle handle, File libraryRoot,
String[] abiList, boolean useIsaSubdir) throws IOException {
createNativeLibrarySubdir(libraryRoot);

/*
* If this is an internal application or our nativeLibraryPath poin
cafe
ts to
* the app-lib directory, unpack the libraries if necessary.
*/
int abi = findSupportedAbi(handle, abiList);
if (abi >= 0) {
/*
* If we have a matching instruction set, construct a subdir under the native
* library root that corresponds to this instruction set.
*/
final String instructionSet = VMRuntime.getInstructionSet(abiList[abi]);
final File subDir;
if (useIsaSubdir) {
final File isaSubdir = new File(libraryRoot, instructionSet);
createNativeLibrarySubdir(isaSubdir);
subDir = isaSubdir;
} else {
subDir = libraryRoot;
}

int copyRet = copyNativeBinaries(handle, subDir, abiList[abi]);
if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
return copyRet;
}
}

return abi;
}

首先通过findSupportedAbi()找到匹配到的abi,然后根据abi,调用copyNativeBinaries()把对应abi下的so库靠别到指定的目录。

public static int findSupportedAbi(Handle handle, String[] supportedAbis) {
int finalRes = NO_NATIVE_LIBRARIES;
for (long apkHandle : handle.apkHandles) {
final int res = nativeFindSupportedAbi(apkHandle, supportedAbis);
if (res == NO_NATIVE_LIBRARIES) {
// No native code, keep looking through all APKs.
} else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) {
// Found some native code, but no ABI match; update our final
// result if we haven't found other valid code.
if (finalRes < 0) {
finalRes = INSTALL_FAILED_NO_MATCHING_ABIS;
}
} else if (res >= 0) {
// Found valid native code, track the best ABI match
if (finalRes < 0 || res < finalRes) {
finalRes = res;
}
} else {
// Unexpected error; bail
return res;
}
}
return finalRes;
}


最终调用native方法nativeFindSupportedAbi()。

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;
}
int status = NO_NATIVE_LIBRARIES;
if (initApkScanLib() == LIB_INITED_AND_SUCCESS) {
PFilterObject filter = GetFilterObjectFunc(zipFile->getFileDescriptor());
if (filter != NULL) {
LibFileAbiDealer param;
param.status = status;
param.numAbis = numAbis;
param.supportedAbis = &supportedAbis;
int ret = FilterLibraryFunc(filter, dealLibAbiFile, ¶m);
if ((0 == ret) || (1 == ret)) {
status = param.status;
for (int i = 0; i < numAbis; ++i) {
delete supportedAbis[i];
}
return status;
}
}
}

UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
if (it.get() == NULL) {
return INSTALL_FAILED_INVALID_APK;
}

ZipEntryRO entry = NULL;

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;
}


      supportedAbis保存了系统支持的abi,系统abilist中是按优先级保存abi,即若apk中arm64-v8a的so库,findSupportedAbi 函数其实就是遍历 apk(其实就是一个压缩文件)中的所有文件,如果文件全路径中包含 abilist 中的某个 abi
字符串,则记录该 abi 字符串的索引,最终返回所有记录索引中最靠前的,即排在 abilist 中最前面的索引。

举个例子,假如我们的 app 中的 so 地址中有包含 arm64-v8a、armeabi-v7a 的字符串,同时 abilist 是 arm64-v8a,armeabi-v7a,armeab,那么这里就会返回 arm64-v8a。

      确定好abi后,就是把对应abi下的so库靠别到指定的目录。调用方法copyNativeBinaries(),同样最终实现在native方法iterateOverNativeFiles()中

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;
}
if (initApkScanLib() == LIB_INITED_AND_SUCCESS) {
PFilterObject filter = GetFilterObjectFunc(zipFile->getFileDescriptor());
if (filter != NULL) {
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;
}
LibFileDealer param;
param.zipFile = zipFile;
param.callFunc = callFunc;
param.env = env;
param.callArg = callArg;
param.cpuAbi = &cpuAbi;
param.ret = INSTALL_SUCCEEDED;
if (0 == FilterLibraryFunc(filter, dealLibFile, ¶m)) {
return param.ret;
}
}
}
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 = 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;

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);
return ret;
}
}
}

return INSTALL_SUCCEEDED;
}

解压APK,根据确定的找到的CPUABI,只拷贝对应目录下的so库。

拷贝完so库后,就要设置primaryCpuAbi和secondaryCpuAbi,primaryCpuAbi 的值来决定我们的程序是运行在32位还是64位下的。

primaryCpuAbi和secondaryCpuAbi设置的逻辑在derivePackageAbi()中。

if (isMultiArch(pkg.applicationInfo)) {
// Warn if we've set an abiOverride for multi-lib packages..
// By definition, we need to copy both 32 and 64 bit libraries for
// such packages.
if (pkg.cpuAbiOverride != null
&& !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
Slog.w(TAG, "Ignoring abiOverride for multi arch application.");
}

int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
if (extractLibs) {
abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi32 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_32_BIT_ABIS);
}
}

maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 32 bit native libs for multiarch app.", abi32);

if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (extractLibs) {
abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
useIsaSpecificSubdirs);
} else {
abi64 = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
}
}

maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 64 bit native libs for multiarch app.", abi64);

if (abi64 >= 0) {
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
}

if (abi32 >= 0) {
final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
if (abi64 >= 0) {
if (pkg.use32bitAbi) {
pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
pkg.applicationInfo.primaryCpuAbi = abi;
} else {
pkg.applicationInfo.secondaryCpuAbi = abi;
}
} else {
pkg.applicationInfo.primaryCpuAbi = abi;
}
}

} else {
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;

// Enable gross and lame hacks for apps that are built with old
// SDK tools. We must scan their APKs for renderscript bitcode and
// not launch them if it's present. Don't bother checking on devices
// that don't have 64 bit support.
boolean needsRenderScriptOverride = false;
if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null &&
NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
abiList = Build.SUPPORTED_32_BIT_ABIS;
needsRenderScriptOverride = true;
}

final int copyRet;
if (extractLibs) {
copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
} else {
copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
}

if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
"Error unpackaging native libs for app, errorCode=" + copyRet);
}

if (copyRet >= 0) {
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
} else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
} else if (needsRenderScriptOverride) {
pkg.applicationInfo.primaryCpuAbi = abiList[0];
}
}



3.在data/data/apk相关目录 下的lib 创建软链接到真正放lib的地方

   调用到了installd,最后调用symlink来创建软链接

if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
// Create a native library symlink only if we have native libraries
// and if the native libraries are 32 bit libraries. We do not provide
// this symlink for 64 bit libraries.
if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) {
final String nativeLibPath = app.nativeLibraryDir;
try {
mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName,
nativeLibPath, userId);
} catch (InstallerException e) {
Slog.e(TAG, "Failed to link native for " + packageName + ": " + e);
}
}
}


   可以查看手机目录




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: