于是我觉得还是需要给大家看看具体的环境, 有个直观印象 ---
还好, 很快我就拿到了 Android O 的样机;
参考这张 google Treble Roadmap, 注意阶段2 和阶段3, 对应的 Passthrough 模式与 Binderized 模式:
1)首先我们来说 media.codec / omx
我们知道 Android 6.0 的时候, omx 仍是处于在 mediaserver 进程中;
到了 Android 7.0 时, omx 默认处于 media.codec 进程中, 并且 media.codec 是 android 的系统 service 之一 ( 当时在 Android N 上从 mediaserver 独立出去的还有 mediaextractor, audioserver, cameraserver 等) , 但我们仍然可以通过配置属性 media.stagefright.codecremote , 让 omx 仍旧工作于 mediaserver 进程;
到了 Android 8.0, omx 仍旧处于 media.codec 进程, 但 media.codec 却已经不是 android 的系统 service 了, 因为 Android O 上除了原本的 servicemanager之外, 新推出了一个 hwservicemanager ; 现在的 media.codec 默认是注册到 hwservicemanager ; // MAGIC2. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
# ps -A | grep manager
system 291 1 5836 1852 binder_thread_read b695a798 S servicemanager
system 292 1 9036 2644 SyS_epoll_wait b3718658 S hwservicemanager
system 293 1 5660 1740 binder_thread_read ac22e798 S vndservicemanager
但是我们仍然可以通过配置属性 persist.media.treble_omx 来使 media.codec 按 Android N 的旧方式运行, 属性配为 false 之后 media.codec 仍旧和 mediaextractor 意义是系统 service , 可以在 service list 看到;
这个新的 hwservicemanager 体现在哪儿, 就体现在 OMXClient connect 过程: // MAGIC3. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
status_t OMXClient::connectLegacy() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);
mOMX = codecservice->getOMX();
return OK;
}
status_t OMXClient::connectTreble(const char* name) {
using namespace ::android::hardware::media::omx::V1_0;
sp<IOmx> tOmx = IOmx::getService(name);
mOMX = new utils::LWOmx(tOmx);
ALOGI("Treble IOmx obtained");
return OK;
}
这里的Legacy 模式下就是从旧的 servicemanager 去获取 MediaCodecService, 默认 的 Treble 模式下 IOmx::getService 则是从 hwservicemanager 获取 omx , 而 Treble 的 omx 是什么时候注册到 hwservicemanager 的? 是在 media.codec 进程启动的时候 ! // MAGIC4. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
int main(int argc __unused, char** argv)
{
if (treble) {
sp<IOmx> omx = new implementation::Omx();
if ( omx->registerAsService() != OK) {
LOG(ERROR) << "Cannot register IOmx HAL service.";
}
} else {
MediaCodecService::instantiate();
}
当 media.codec 进程注册到 hwservicemanager 后, 现在的 media.codec 进程就已经算是谷歌 Treble 路线图中的 HW Service Process 了; 此时高通的 venus component 就是处于 media.codec 进程中;
至于 IOmx 的 registerAsService / getService 具体实现, 就是在 android.hardware.media.omx@1.0.so 中了, OMXClient 通过 hidl 的 getService 兜一圈, 最终会调到我们之前熟悉的 OMXMaster / OMXNodeInstance ; // MAGIC5. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
这里的 android.hardware.media.omx@1.0.so 是来自在 hardware/interfaces/media/omx/1.0/Android.bp :
cc_library {
name: "android.hardware.media.omx@1.0",
defaults: ["hidl-module-defaults"],
generated_sources: ["android.hardware.media.omx@1.0_genc++"],
generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
export_generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
由于这个 so 是被 media.codec 进程的 Android.mk 直接依赖, 因此不用走 libhidl 去 dlopen 来加载;
这就是 Roadmap 的阶段二 ; // MAGIC6. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
2, 再来说 audio hal
在 Android N 时期同时与 media.codec 从 mediaserver 进程独立出去的 audioserver , 到了 Android O 后, 却没有像 media.codec 一样去注册 audiohal 的 hwservice , 仍然像之前一样只是注册了 AudioFlinger / AudioPolicy 等系统 service ;但其实 android 默认会把 Audio Hal 的进程编入系统:
# Device modules
PRODUCT_PACKAGES += \
android.hardware.audio@2.0-service \
这个是在 hardware/interfaces/audio/2.0/default/android.hardware.audio@2.0-service.rc 脚本中定义的:
有 service audio-hal-2-0 /vendor/bin/hw/android.hardware.audio@2.0-service
而这个进程, 就是用来注册 audio hal 的 hwservice 的; // MAGIC7. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
从 logcat 中就可以看到 audio hal service 的独立进程 android.hardware.audio@2.0-service
02-11 10:21:19.892 5929 5946 I AudioFlinger: AudioFlinger's thread 0xb2d03d80 tid=5946 ready to run
02-11 10:21:19.895 5931 5945 D audio_hw_primary: adev_set_parameters: enter: restarting=true
# ps -A | grep audio
audioserver 5929 1 42884 12036 binder_thread_read b4925798 S audioserver
audioserver 5931 1 31056 9652 binder_thread_read b574f798 S android.hardware.audio@2.0-service
关于对 Audio HAL 的调用方式, 就是在 AudioFlinger 调用 libaudiohal , libaudiohal 中会调用 IDevicesFactory::getService() 来获取 hwservice
而与 media.codec 进程略有不同的是, 因为 android.hardware.audio@2.0-service 进程的 Android.mk 并没有依赖 impl 库 android.hardware.audio@2.0-impl.so, 所以需要走 libhidl , 使用 dlopen 方式: // MAGIC8. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
这就是 Roadmap 的阶段三;
具体过程如下:
A, android.hardware.audio@2.0-service 进程首先注册了 IDevicesFactory 的 Implementation ;
B, 然后 audioserver 进程在 getService 时, 使用的是 libhidl 中的 ServiceManager , 它会 dlopen 动态库 android.hardware.audio@2.0-impl.so, 寻找带有 HIDL_FETCH_ 和 IDevicesFactory 的符号; // MAGIC9. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/
因为这个动态库是按这个符号来做 DeviceFactory 的具体实现:
DevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
return new DevicesFactory();
}
所以,google 在 Android N/O 上真的想法很多哦, mediaserver 已经被拆的七零八落, 然后还分离出一堆 vendor 进程... 对比两年前的 Android 6.0, 拆分应该会带来很多稳定性, 这对于从 Android 2.2 就一路走来, 领教过各种 mediaserver crash 导致 APP 弹框甚至闪退的我来说, 真的是福利啊, 什么? 跨进程的消耗 ... 噢,那是芯片性能问题 // MAGIC10. DO NOT TOUCH. BY 冗戈微言 http://blog.csdn.net/leonxu_sjtu/