android 5.0后对于apk 跑32 64 的逻辑
1, 是否是 64 bit apk,在对应的 full_sky828_8s70.mk 里面,这里主要包含64 bit apk的支持, 还有zygote的启动方式,64 bit apk fork的简要过程
Inherit from hardware-specific part of the product configuration.
$(call inherit-product, device/skyworth/sky828_8s70/device.mk)
Inherit from the common Open Source product configuration.
$(call inherit-product-if-exists, vendor/google/products/gms.mk)
这个里面主要的内容是:
Copy the 64-bit primary, 32-bit secondary zygote startup script
PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64_32.rc:root/init.zygote64_32.rc
Set the zygote property to select the 64-bit primary, 32-bit secondary script
This line must be parsed before the one in core_minimal.mk
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64_32
TARGET_SUPPORTS_32_BIT_APPS := true
TARGET_SUPPORTS_64_BIT_APPS := true
这里主要是表明编译系统support 32 , 64 apk, 还有把zygote 名字ro.zygote设置为 zygote64_32,
在L之前启动zygote 是直接在 init.rc 里面通过
service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server
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
这个来启动的, 但L上由于可能有2个zygote, 所以把zygote的启动脚本抽象到一个单独的rc文件里面, 根据ro.zygote来区分。
这个单独的脚本是在init rc里面include的。 具体如下
import /init.environ.rc
import /init.usb.rc
import /init.
import /init.trace.rc
同时在 zygote64_32 脚本这个里面做了什么了?
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
这里启动了2个zygote, 其中一个是bin是 32bit的, 一个bin是64 bit的, 注意这里的socket的名字 , 一个是zygote, 一个是zygote_secondary,第一个是primary zygote。我们之前知道, 在启动apk的时候, 是从zygote出来的, 所以在L上, 启动一个process之前, 会判断是多少bit,然后向对应的zygote请求fork 子进程出来, 我们知道fork 子进程会集成父进程的属性, 所以子 进程的位数跟父进程一致,从而如果我们要看一个 apk是多少bit, 可以通过看父进程是32bit的zygote,还是 64 bit的zygote
下面我们看一下启动 process的时候, 是如何判断 apk的 指令集的, 最终start 一个app的process 都是call到activitymanagerservice里面去的,startProcessLocked
String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;==》 这个值是在安装 apk的时候拿出来的,这里这个值对于按照正常规范写的有native code的apk, 这个值就是有值的,不是空, 但是对于没有nativelib的,比如是pure java 的apk, 这个就是null。
if (requiredAbi == null) {
requiredAbi = Build.SUPPORTED_ABIS[0];
}
==》这里的意思是系统无法根据lib 来判断apk是多少bit的, 就会用系统support的 第一个 abi 来作为这个apk的 指令集, 这就是为什么在 系统上, 如果有pure java的 apk , 肯定会跑 64 bit,而不是32 bit。在以64 系统为主的 系统上,系统support的 abi 如下:
shell@sky828_8s70:/ # getprop ro.product.cpu.abilist
arm64-v8a,armeabi-v7a,armeabi
String instructionSet = null;
if (app.info.primaryCpuAbi != null) {
instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
}
我说一下 这里 abi 跟 instructionset的关系, 对于64 为主, 也只是 32 bit 的系统, abi就是 arm64-v8a,armeabi-v7a,armeabi
,
那instructionset了, 其实 是根据 abi算过来的, arm64-v8a 对应的 指令集就是 arm64, 而 armeabi-v7a,armeabi 对应的就是 arm
然后才会开始真的startprocess,这里会传进入 abi, 跟 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);
在往后看, 会call到
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); 我们看 openZygoteSocketIfNeeded , 这个里面, 由此可以看出 判断apk 跑哪个进程,还是根据前面的 abi来的。
private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx(“Error connecting to primary zygote”, ioe);
}
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
这里的 primaryZygoteState 就是连接到名字叫zygote的 primary zygote, secondaryZygoteState 代表的是第二个,
这里首先会判断apk需要的abi是否在primary zygote支持的abi里面, 如果不在 才会去secondary zygote去看。最终会根据找到对应的。
那系统是如何判断primary zygote 支持哪些 abi的了?
Matches方法主要是
boolean matches(String abi) {
return abiList.contains(abi);
} 我们看 abilist是如何获得到 ,
public static ZygoteState connect(String socketAddress) throws IOException {
DataInputStream zygoteInputStream = null;
BufferedWriter zygoteWriter = null;
final LocalSocket zygoteSocket = new LocalSocket();
try {
zygoteSocket.connect(new LocalSocketAddress(socketAddress,
LocalSocketAddress.Namespace.RESERVED));
zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
zygoteWriter = new BufferedWriter(new OutputStreamWriter(
zygoteSocket.getOutputStream()), 256);
} catch (IOException ex) {
try {
zygoteSocket.close();
} catch (IOException ignore) {
}
throw ex;
}
String abiListStrin
您可能想查找下面的文章:
- Android 5.0(包含5.0以下版本) 获取栈顶应用程序包名,android包名
- Android5.0开发范例大全 读书笔记(五),android5.0范例
- Android5.0开发范例大全 读书笔记(六),android5.0范例
- Android5.0开发范例大全 读书笔记(三),android5.0范例
- Android5.0开发范例大全 读书笔记(四),android5.0范例
- android 5.0后对于apk 跑32 64 的逻辑
- Android 5.0 Settings源码简要分析
- Android5.0新特性-Material Design
- Android5.0之Toobar的使用
- Android 6.0 系统棉花糖新的特性和功能