Android APK 在32bit 和64bit 的区别问题

目前64bit android系统也慢慢的多了,看到也有apk声称支持64bit system,然后就往里面打包搞了个arm64-v8a
目录,放了个64bit的so,但是apk代码里面却不按规范去load so ,导致一系列 file not found 异常。

apk lib目录:

先看下apk中的lib打包的目录:

依次代表不同类型的cpu

PMS安装路径://blog.csdn.net/sergeycao

pms install 流程比较繁杂,只关注so相关的scanPackageDirtyLI函数中:

<code class="hljs r has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
             //invoke installer to do the actual installation  //作为外部apk 创建data目录相关项
             //\frameworks\native\cmds\installd\commands.c  install()中创建
                int ret = **createDataDirsLI**(pkgName, pkg.applicationInfo.uid,
                                           pkg.applicationInfo.seinfo);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

           setBundledAppAbisAndRoots(pkg, pkgSetting);

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

           setNativeLibraryPaths(pkg);  

    }
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
    {
    setNativeLibraryPaths(pkg);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isAsec) {
                        copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                        copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
                                nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
                    }
    setNativeLibraryPaths(pkg);
      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (DEBUG_INSTALL) Slog.i(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Linking native library dir for "</span> + path);
            final int[] userIds = sUserManager.getUserIds();
            synchronized (mInstallLock) {
                // Create a native <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">library</span> symlink only <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> we have native libraries
                // and <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> the native libraries are <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">32</span> bit libraries. We do not provide
                // this symlink <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">64</span> bit libraries.
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pkg.applicationInfo.primaryCpuAbi != null &&
                        **!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)**) {
                    final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (int userId : userIds) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mInstaller.linkNativeLibraryDirectory(pkg.packageName, nativeLibPath, userId) < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)    {
                            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                                    <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Failed linking native library dir (user="</span> + userId + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">")"</span>);
                        }
                    }
                }
            }

    }
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li></ul>

看下system app 的安装配置函数 setBundledAppAbisAndRoots:

//blog.csdn.net/sergeycao

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * Calculate the abis and roots for a bundled app. These can uniquely
     * be determined from the contents of the system partition, i.e whether
     * it contains 64 or 32 bit shared libraries etc. We do not validate any
     * of this information, and instead assume that the system was built
     * sensibly.
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setBundledAppAbisAndRoots</span>(PackageParser.Package pkg,
                                           PackageSetting pkgSetting) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If "/system/lib64/apkname" exists, assume that is the per-package</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// native library directory to use; otherwise use "/system/lib/apkname".</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir);
        setBundledAppAbi(pkg, apkRoot, apkName);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// pkgSetting might be null during rescan following uninstall of updates</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// to a bundled app, so accommodate that possibility.  The settings in</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// that case will be established later from the parsed package.</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If the settings aren't null, sync them up with what we've just derived.</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// note that apkRoot isn't stored in the package settings.</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pkgSetting != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
            pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi;
            pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi;
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

主要是在setBundledAppAbi中:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * Deduces the ABI of a bundled app and sets the relevant fields on the
     * parsed pkg object.
     *
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> apkRoot the root of the installed apk, something like {@code /system} or {@code /oem}
     *        under which system libraries are installed.
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> apkName the name of the installed package.
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setBundledAppAbi</span>(PackageParser.Package pkg, String apkRoot, String apkName) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> File codeFile = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(pkg.codePath);
...
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (has64BitLibs && !has32BitLibs) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The package has 64 bit libs, but not 32 bit libs. Its primary</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ABI should be 64 bit. We can safely assume here that the bundled</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// native libraries correspond to the most preferred ABI in the list.</span>

            pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            pkg.applicationInfo.secondaryCpuAbi = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (has32BitLibs && !has64BitLibs) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The package has 32 bit libs but not 64 bit libs. Its primary</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ABI should be 32 bit.</span>

            pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            pkg.applicationInfo.secondaryCpuAbi = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (has32BitLibs && has64BitLibs) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// The application has both 64 and 32 bit bundled libraries. We check</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// here that the app declares multiArch support, and warn if it doesn't.</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We will be lenient here and record both ABIs. The primary will be the</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ABI that's higher on the list, i.e, a device that's configured to prefer</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 64 bit apps will see a 64 bit primary ABI,</span>

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                Slog.e(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Package: "</span> + pkg + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" has multiple bundled libs, but is not multiarch."</span>);
            }

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) {
                pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
                pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            }
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            pkg.applicationInfo.primaryCpuAbi = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            pkg.applicationInfo.secondaryCpuAbi = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        }
 }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li></ul>

根据file 查找 确定primaryCpuAbi secondaryCpuAbi 变量值,这个也就决定了 这个 apk 由64bit 还是32bit 的zygote去fork 还有nativelibrary 查找的path

其中nativelibrary的几个主要函数 setNativeLibraryPaths:

//blog.csdn.net/sergeycao

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * Derive and set the location of native libraries for the given package,
     * which varies depending on where and how the package was installed.
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setNativeLibraryPaths</span>(PackageParser.Package pkg) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ApplicationInfo info = pkg.applicationInfo;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String codePath = pkg.codePath;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> File codeFile = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(codePath);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> asecApp = isForwardLocked(info) || isExternal(info);

        info.nativeLibraryRootDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        info.nativeLibraryRootRequiresIsa = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        info.nativeLibraryDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        info.secondaryNativeLibraryDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (isApkFile(codeFile)) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Monolithic install</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (bundledApp) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// If "/system/lib64/apkname" exists, assume that is the per-package</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// native library directory to use; otherwise use "/system/lib/apkname".</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String apkRoot = calculateBundledApkRoot(info.sourceDir);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> is64Bit = VMRuntime.is64BitInstructionSet(
                        getPrimaryInstructionSet(info));

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// This is a bundled system app so choose the path based on the ABI.</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// is just the default path.</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String apkName = deriveCodePathName(codePath);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
                info.nativeLibraryRootDir = Environment.buildPath(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkRoot), libDir,
                        apkName).getAbsolutePath();

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.secondaryCpuAbi != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
                    info.secondaryNativeLibraryDir = Environment.buildPath(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkRoot),
                            secondaryLibDir, apkName).getAbsolutePath();
                }
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (asecApp) {
                info.nativeLibraryRootDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(codeFile.getParentFile(), LIB_DIR_NAME)
                        .getAbsolutePath();
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String apkName = deriveCodePathName(codePath);
                info.nativeLibraryRootDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(mAppLib32InstallDir, apkName)
                        .getAbsolutePath();
            }

            info.nativeLibraryRootRequiresIsa = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
            info.nativeLibraryDir = info.nativeLibraryRootDir;
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Cluster install</span>
            info.nativeLibraryRootDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(codeFile, LIB_DIR_NAME).getAbsolutePath();
            info.nativeLibraryRootRequiresIsa = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;

            info.nativeLibraryDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(info.nativeLibraryRootDir,
                    getPrimaryInstructionSet(info)).getAbsolutePath();

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.secondaryCpuAbi != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                info.secondaryNativeLibraryDir = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(info.nativeLibraryRootDir,
                        VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath();
            }
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li></ul>

根据pkg application info 来确定nativelibrarydir 依赖info中的 info.primaryCpuAbi

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> String <span class="hljs-title" style="box-sizing: border-box;">getPrimaryInstructionSet</span>(ApplicationInfo info) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info.primaryCpuAbi == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> getPreferredInstructionSet();
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> VMRuntime.getInstructionSet(info.primaryCpuAbi);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

非system apk 会调用 NativeLibraryHelper 的 findSupportedAbi 去解析 .apk 文件,根据系统suportabilist 去查找 lib目录下的打包子目录 找到匹配的abi

向文章开头的那个 lib目录 ,在64bit 机器上suportabilist为:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String[] SUPPORTED_ABIS = getStringList(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ro.product.cpu.abilist"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">","</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
<code class="hljs ruby has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">[email protected]<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:/</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># getprop ro.product.cpu.abilist                                 </span>
arm64-v8a,armeabi-v7a,armeabi</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

会匹配arm64-v8a 赋值给 info.primaryCpuAbi

copyNativeBinariesForSupportedAbi 会去copy 前面匹配的lib 目录到本地

最后设置NativeLibraryPaths ,

如果匹配的是64bit的,也就是arm64-v8a 那么就不为/data/data/../lib 建立软链接,这是与32bit 不同的地方


system.loadlibrary

作为动态库加载的标准接口,直接看实现:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">loadLibrary</span>(String libName) {
        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

到Runtime.java中:

<code class="hljs javascript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
     * Searches for and loads the given shared library using the given ClassLoader.
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> loadLibrary(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> libraryName, ClassLoader loader) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (loader != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> filename = loader.findLibrary(libraryName);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (filename == <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// It's not necessarily true that the ClassLoader used</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// System.mapLibraryName, but the default setup does, and it's</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// misleading to say we didn't find "libMyLibrary.so" when we</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// actually searched for "liblibMyLibrary.so.so".</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsatisfiedLinkError(loader + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" couldn't find \""</span> +
                                               System.mapLibraryName(libraryName) + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\""</span>);
            }
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> error = doLoad(filename, loader);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (error != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsatisfiedLinkError(error);
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> filename = System.mapLibraryName(libraryName);
        List<<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>> candidates = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span>>();
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> lastError = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> directory : mLibPaths) {
            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> candidate = directory + filename;
            candidates.add(candidate);

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (IoUtils.canOpenReadOnly(candidate)) {
                <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> error = doLoad(candidate, loader);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (error == <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) {
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// We successfully loaded the library. Job done.</span>
                }
                lastError = error;
            }
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (lastError != <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">null</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsatisfiedLinkError(lastError);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsatisfiedLinkError(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Library "</span> + libraryName + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" not found; tried "</span> + candidates);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li></ul>

这里的 ClassLoader loader 实际上会在 apk启动的时候 初始化好一些相关的 子类 父类 还有参数

大体记录一下 启动时 初始流程 :

<code class="hljs scala has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">ActivityThread.java   - handleBindApplication
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> ContextImpl appContext = ContextImpl.createAppContext(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>, data.info);
  LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);

ContextImpl.java  -getClassLoader()
LoadedApk.java    -getClassLoader()     :  mLibDir = aInfo.nativeLibraryDir;
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
                        mBaseClassLoader);
ApplicationLoaders.java    -getClassLoader(...)
 PathClassLoader pathClassloader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PathClassLoader(zip, libPath, parent);   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里的libPath 就是上面传下来的aInfo.nativeLibraryDir</span>

public <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">PathClassLoader</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">BaseDexClassLoader</span></span>
public <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">BaseDexClassLoader</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ClassLoader</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

loader.findLibrary(libraryName);

<code class="hljs applescript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    /**
     * Finds <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> named native code library <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span></span> any <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">of</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> library
     * directories pointed <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">at</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">by</span> this instance. This will find <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span>
     * one <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> earliest listed directory, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">ignoring</span> any <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">that</span> are <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">not</span>
     * readable regular files.
     *
     * @<span class="hljs-constant" style="box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> complete <span class="hljs-command" style="box-sizing: border-box;">path to</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> library <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> {@code null} <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> no
     * library was found
     */
    public String findLibrary(String libraryName) {
        String fileName = System.mapLibraryName(libraryName);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (File directory : nativeLibraryDirectories) {
            String path = new File(directory, fileName).getPath();
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (IoUtils.canOpenReadOnly(path)) {
<span class="hljs-command" style="box-sizing: border-box;">                return</span> path;
            }
        }
<span class="hljs-command" style="box-sizing: border-box;">        return</span> null;
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

这里的nativeLibraryDirectories 即为前面一系列 构造时 设置了值 其中就有 aInfo.nativeLibraryDir

后面的逻辑就不去叙述了, 根据名字在这个目录下去找 ,然后调用到本地JNI 最终调用 dlopen 加载打开so,必须是相同位数, 而这个关乎当前进程是属于64bit 还是 32bit,这个会在zygote fork时区分, 同样也是由PMS解析时得到的 info.primaryCpuAbi

AMS 请求zygote fork app process选择

只关心 相关代码 startProcessLocked函数:

<code class="hljs r has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

 String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (requiredAbi == null) {
                requiredAbi = Build.SUPPORTED_ABIS[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];
            }

            String instructionSet = null;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (app.info.primaryCpuAbi != null) {
                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
            }

            app.gids = gids;
            app.requiredAbi = requiredAbi;
            app.instructionSet = instructionSet;

            // Start the process.  It will either succeed and <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> a result containing
            // the PID of the new process, or <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (entryPoint == null) entryPoint = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"android.app.ActivityThread"</span>;
            checkTime(startTime, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"startProcess: asking zygote to start proc"</span>);
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"startProcess: returned from zygote!"</span>);

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

Process中真正的socket 请求实现:

<code class="hljs scss has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">return <span class="hljs-function" style="box-sizing: border-box;">zygoteSendArgsAndGetResult(<span class="hljs-function" style="box-sizing: border-box;">openZygoteSocketIfNeeded(abi)</span>, argsForZygote)</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

openZygoteSocketIfNeeded 会根据传下来的abi 去选择 通信的socket

而在64bit 机器上,启动时会 启动 两个 zygote service ,用于接收 64 32 的apk 请求:

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">service zygote /<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>/bin/app_process64 -Xzygote /<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>/bin <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--zygote --start-system-server --socket-name=zygote</span>
    class main
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">socket</span> zygote stream <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">660</span> root <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>
    onrestart <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">write</span> /sys/android_power/request_state wake
    onrestart <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">write</span> /sys/power/state <span class="hljs-command" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span></span>
    onrestart restart media
    onrestart restart netd

service zygote_secondary /<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>/bin/app_process32 -Xzygote /<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>/bin <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">--zygote --socket-name=zygote_secondary</span>
    class main
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">socket</span> zygote_secondary stream <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">660</span> root <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">system</span>
    onrestart restart zygote</code>

pms install 流程比较繁杂,只关注so相关的scanpackageDirtyLI函数中:

private PackageParser.Package scanPackageDirtyLI(PackageParser.Package
pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { ... //invoke installer to do the actual installation //作为外部apk 创建data目录相关项 //\frameworks\native\cmds\installd\commands.c
install()中创建 int ret = **createDataDirsLI**(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.seinfo); ... if (isSystemApp(pkg) && !isupdatedSystemApp(pkg))
{ ... setBundledAppAbisAndRoots(pkg, pkgSetting); ... setNativeLibraryPaths(pkg); } else { setNativeLibraryPaths(pkg); ... if (isAsec) { copyRet =
NativeLibraryHelper.findSupportedAbi(handle, abiList); } else { copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle, nativeLibraryRoot, abiList, useIsaSpecificSubdirs); } setNativeLibraryPaths(pkg); if (DEBUG_INSTALL)
Slog.i(TAG, "Linking native library dir for " + path); final int[] userIds = sUserManager.getUserIds(); synchronized (mInstallLock) { // 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 (pkg.applicationInfo.primaryCpuAbi
!= null && **!VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)**) { final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir; for (int userId : userIds) { if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
nativeLibPath, userId) < 0) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Failed linking native library dir (user=" + userId + ")"); } } } } } }

看下system app 的安装配置函数 setBundledAppAbisAndRoots:

/** * Calculate the abis and roots for a
bundled app. These can uniquely * be determined from the contents of the system partition, i.e whether * it contains 64 or 32 bit shared libraries etc. We do not validate any * of this information, and instead assume that the system was built * sensibly. */ private void setBundledAppAbisAndRoots(PackageParser.Package
pkg, PackageSetting pkgSetting) { final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath()); // 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(pkg.applicationInfo.sourceDir); setBundledAppAbi(pkg, apkRoot, apkName); // pkgSetting might be null during rescan
following uninstall of updates // to a bundled app, so accommodate that possibility. The settings in // that case will be established later from the parsed package. // //
If the settings aren‘t null, sync them up with what we‘ve just derived. // note that apkRoot isn‘t stored in the package settings. if (pkgSetting != null) { pkgSetting.primaryCpuAbiString
= pkg.applicationInfo.primaryCpuAbi; pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; } }

主要是在setBundledAppAbi中:

/** * Deduces the ABI of a bundled app and
sets the relevant fields on the * parsed pkg object. * * @param apkRoot the root of the installed apk, something like {@code /system} or {@code /oem} * under which system libraries are installed. * @param apkName
the name of the installed package. */ private static void setBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) { final File
codeFile = new File(pkg.codePath); ... if (has64BitLibs && !has32BitLibs) { // The package has 64 bit libs, but not 32 bit libs. Its primary // ABI should be 64 bit. We can safely
assume here that the bundled // native libraries correspond to the most preferred ABI in the list. pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; pkg.applicationInfo.secondaryCpuAbi = null;
} else if (has32BitLibs && !has64BitLibs) { // The package has 32 bit libs but not 64 bit libs. Its primary // ABI should be 32 bit. pkg.applicationInfo.primaryCpuAbi =
Build.SUPPORTED_32_BIT_ABIS[0]; pkg.applicationInfo.secondaryCpuAbi = null; } else if (has32BitLibs && has64BitLibs) { // The application has both 64 and
32 bit bundled libraries. We check // here that the app declares multiArch support, and warn if it doesn‘t. // // We will be lenient here and record both ABIs. The primary will be the //
ABI that‘s higher on the list, i.e, a device that‘s configured to prefer // 64 bit apps will see a 64 bit primary ABI, if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0)
{ Slog.e(TAG, "Package: " + pkg + " has multiple bundled libs, but is not multiarch."); } if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) { pkg.applicationInfo.primaryCpuAbi
= Build.SUPPORTED_64_BIT_ABIS[0]; pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; } else { pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
pkg.applicationInfo.secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; } } else { pkg.applicationInfo.primaryCpuAbi = null; pkg.applicationInfo.secondaryCpuAbi = null; }
}

根据file 查找 确定primaryCpuAbi secondaryCpuAbi 变量值,这个也就决定了 这个 apk 由64bit 还是32bit 的zygote去fork 还有nativelibrary 查找的path

其中nativelibrary的几个主要函数 setNativeLibraryPaths:

/** * Derive and set the location of native
libraries for the given package, * which varies depending on where and how the package was installed. */ 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 = isSystemApp(info)
&& !isUpdatedSystemApp(info); final boolean asecApp = isForwardLocked(info) || isExternal(info); 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(); } } }

根据pkg application info 来确定nativelibrarydir 依赖info中的 info.primaryCpuAbi

private static String getPrimaryInstructionSet(ApplicationInfo
info) { if (info.primaryCpuAbi == null) { return getPreferredInstructionSet(); } return VMRuntime.getInstructionSet(info.primaryCpuAbi); }

非system apk 会调用 NativeLibraryHelper 的 findSupportedAbi 去解析 .apk 文件,根据系统suportabilist 去查找 lib目录下的打包子目录 找到匹配的abi

文章开头的那个 lib目录 ,在64bit 机器上suportabilist为:

public static final String[]
SUPPORTED_ABIS = getStringList("ro.product.cpu.abilist", ",");

[email protected]:/ # getprop ro.product.cpu.abilist arm64-v8a,armeabi-v7a,armeabi

会匹配arm64-v8a 赋值给 info.primaryCpuAbi

copyNativeBinariesForSupportedAbi 会去copy 前面匹配的lib 目录到本地

最后设置NativeLibraryPaths ,

如果匹配的是64bit的,也就是arm64-v8a 那么就不为/data/data/../lib 建立软链接,这是与32bit 不同的地方


system.loadlibrary

作为动态库加载的标准接口,直接看实现:

public static void loadLibrary(String
libName) { Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); }

到Runtime.Java中:

/* * Searches for and loads the given
shared library using the given ClassLoader. */ void loadLibrary(String libraryName, ClassLoader loader) { if (loader != null) { String filename
= loader.findLibrary(libraryName); if (filename == null) { // It‘s not necessarily true that the ClassLoader used // System.mapLibraryName, but the default setup does, and it‘s //
misleading to say we didn‘t find "libMyLibrary.so" when we // actually searched for "liblibMyLibrary.so.so". throw new UnsatisfiedLinkError(loader + " couldn‘t find \"" +
System.mapLibraryName(libraryName) + "\""); } String error = doLoad(filename, loader); if (error != null) { throw new UnsatisfiedLinkError(error);
} return; } String filename = System.mapLibraryName(libraryName); List<String> candidates = new ArrayList<String>(); String lastError
= null; for (String directory : mLibPaths) { String candidate = directory + filename; candidates.add(candidate); if (IoUtils.canOpenReadOnly(candidate))
{ String error = doLoad(candidate, loader); if (error == null) { return; // We successfully loaded the library. Job done. } lastError = error; } } if (lastError
!= null) { throw new UnsatisfiedLinkError(lastError); } throw new UnsatisfiedLinkError("Library " + libraryName + "
not found; tried " + candidates); }

这里的 ClassLoader loader 实际上会在 apk启动的时候 初始化好一些相关的 子类 父类 还有参数

大体记录一下 启动时 初始流程 :

ActivityThread.java - handleBindApplication final ContextImpl
appContext = ContextImpl.createAppContext(this, data.info); LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); ContextImpl.java
-getClassLoader() LoadedApk.java -getClassLoader() : mLibDir = aInfo.nativeLibraryDir; mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib, mBaseClassLoader); ApplicationLoaders.java -getClassLoader(...) PathClassLoader pathClassloader = new PathClassLoader(zip,
libPath, parent); //这里的libPath 就是上面传下来的aInfo.nativeLibraryDir public class PathClassLoader extends BaseDexClassLoader public class BaseDexClassLoader extends ClassLoader

loader.findLibrary(libraryName);

/** * Finds the named native
code library on any of the library * directories pointed at by this instance. This will find the * one in the earliest
listed directory, ignoring any that are not * readable regular files. * * @return the complete path to the library or {@code
null} if no * library was found */ public String findLibrary(String libraryName) { String fileName = System.mapLibraryName(libraryName); for (File directory : nativeLibraryDirectories) { String path = new File(directory,
fileName).getPath(); if (IoUtils.canOpenReadOnly(path)) { return path; } } return null; }

这里的nativeLibraryDirectories 即为前面一系列 构造时 设置了值 其中就有 aInfo.nativeLibraryDir

后面的逻辑就不去叙述了, 根据名字在这个目录下去找 ,然后调用到本地JNI 最终调用 dlopen 加载打开so,必须是相同位数, 而这个关乎当前进程是属于64bit 还是 32bit,这个会在zygote fork时区分, 同样也是由PMS解析时得到的 info.primaryCpuAbi

AMS 请求zygote fork app process选择

只关心 相关代码 startProcessLocked函数:

private final void startProcessLocked(ProcessRecord app, String
hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null)
{ requiredAbi = Build.SUPPORTED_ABIS[0]; } String instructionSet = null; if (app.info.primaryCpuAbi != null) { instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } app.gids = gids; app.requiredAbi
= requiredAbi; app.instructionSet = instructionSet; // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. boolean isActivityProcess
= (entryPoint == null); if (entryPoint == null) entryPoint = "android.app.ActivityThread"; checkTime(startTime, "startProcess: asking zygote to start proc"); Process.ProcessStartResult startResult
= Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkversion,
app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); checkTime(startTime, "startProcess: returned from zygote!"); ... }

Process中真正的socket 请求实现:

return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
argsForZygote);

openZygoteSocketIfNeeded 会根据传下来的abi 去选择 通信的socket

而在64bit 机器上,启动时会 启动 两个 zygote service ,用于接收 64 32 的apk 请求:

service zygote /system/bin/app_process64
-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state
wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote
--socket-name=zygote_secondary class main socket zygote_secondary stream 660 root system onrestart restart zygote

可以看到两个 zygote 进程,基本一致 ,区别在于 64bit 32bit ,注册socket不同

关于这两个 zygote 进程启动时的socket 注册

时间: 2024-08-01 23:01:32

Android APK 在32bit 和64bit 的区别问题的相关文章

Android——APK 在32bit/64bit平台 动态库问题

目前64bit android系统也慢慢的多了,看到也有apk声称支持64bit system,然后就往里面打包搞了个arm64-v8a 目录,放了个64bit的so,但是apk代码里面却不按规范去load so ,导致一系列 file not found 异常~ 撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/47101815本文来自 [jscese]的博客! apk lib目录: 先看下apk中的lib打包的目录: 依次代表不

Android apk打包过程

概述 android打包过程,下面这张图取自Android开发权威指南,非常清晰. 整个过程使用的工具有 名称 功能介绍 在操作系统中的路径 aapt Android资源打包工具 ${ANDROID_SDK_HOME}/platform-tools/appt aidl Android接口描述语言转化为.java文件的工具 ${ANDROID_SDK_HOME}/platform-tools/aidl javac Java Compiler ${JDK_HOME}/javac或/usr/bin/j

在 java 1.8.0 版本的环境下,进行 android apk 的签名操作

注:文章参考了 android 开发者社区的签名指引说明文章,但由于在国内 android 开发者社区已经无法正常访问,因此在这里做下记录. 地址:http://developer.android.com/tools/publishing/app-signing.html#considerations 在开发 android 应用程序的时候,到最后程序都需要进行签名后才可以发布,目前针对 android 应用开发的 ide 一般都会自带了签名的功能,例如 android studio.eclip

Android apk动态加载机制的研究(二):资源加载和activity生命周期管理

出处:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (来自singwhatiwanna的csdn博客) 前言 为了更好地阅读本文,你需要先阅读Android apk动态加载机制的研究这篇文章,在此文中,博主分析了Android中apk的动态加载机制,并在文章的最后指出需要解决的两个复杂问题:资源的访问和activity生命周期的管理,而本文将会分析这两个复杂问题的解决方法.需要说明的一点是,我们不可能调起任何一个未安装的

实例具体解释:反编译Android APK,改动字节码后再回编译成APK

本文具体介绍了怎样反编译一个未被混淆过的Android APK,改动smali字节码后,再回编译成APK并更新签名,使之可正常安装.破译后的apk不管输入什么样的username和password都能够成功进入到第二个Activity. 有时难免要反编译一个APK.改动当中的若干关键推断点,然后再回编译成一个全新的可用的apk,这全然是可实现的. 若要完毕上述工作,须要以下工具,杂家后面会把下载链接也附上.这些软件截止本文公布时,经过杂家确认都是最新的版本号. 1.APK-Multi-Toolv

Linux Kernel sys_call_table、Kernel Symbols Export Table Generation Principle、Difference Between System Calls Entrance In 32bit、64bit Linux(undone)

目录 1. sys_call_table:系统调用表 2. 内核符号导出表.kallsyms_lookup_name 3. Linux 32bit.64bit下系统调用入口的异同 1. sys_call_table:系统调用表 Relevant Link: 2. 内核符号导出表.kallsyms_lookup_name Relevant Link: 3. Linux 32bit.64bit下系统调用入口的异同 以sys_execve.sys_socketcall.sys_init_module这

android finish和system.exit(0)的区别

finish是Activity的类,仅仅针对Activity,当调用finish()时,只是将活动推向后台,并没有立即释放内存,活动的资源并没有被清理:当调用System.exit(0)时,杀死了整个进程, 这时候活动所占的资源也会被释放. 在开发android应用时,常常通过按返回键(即keyCode == KeyEvent.KEYCODE_BACK)就能关闭程序,其实大多情况下该应用还在任务里运行着,其实这不是我们想要的结果. 我们可以这样做,当用户点击自定义的退出按钮或返回键时(需要捕获动

反编译Android APK及防止APK程序被反编译

原文出处 反编译Android APK及防止APK程序被反编译 怎么逆向工程对Android Apk 进行反编译 google Android开发是开源的,开发过程中有些时候会遇到一些功能,自己不知道该怎么做,然而别的软件里面已经有了,这个时候可以采用反编译的方式,解开其他的程序,来了解一些它 的做法,同时啊,还可以借鉴别人的软件结构,资源文件:作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看.此方式主要目的是为了促进开发者学习,借鉴好的代

android apk 防止反编译技术第一篇-加壳技术

做android framework方面的工作将近三年的时间了,现在公司让做一下android apk安全方面的研究,于是最近就在网上找大量的资料来学习.现在将最近学习成果做一下整理总结.学习的这些成果我会做成一个系列慢慢写出来与大家分享,共同进步.这篇主要讲apk的加壳技术,废话不多说了直接进入正题. 一.加壳技术原理 所谓apk的加壳技术和pc exe的加壳原理一样,就是在程序的外面再包裹上另外一段代码,保护里面的代码不被非法修改或反编译,在程序运行的时候优先取得程序的控制权做一些我们自己想