从CarAudioManager调用流程开始学习Vendor Interface(Service部分)

接下来就是Vendor的实现了!

如果要作为一个Service来提供,我们应该怎么设计呢?

TODO:

QA:怎么设计比较合理。

首先,在Android 系统启动的时候init进程

/system/core/init

[email protected]


int main(int argc, char** argv) {
  ...
    parser.ParseConfig("/init.rc");
  ...
}


/system/core/rootdir/init.rc


on post-fs
    # Load properties from
    #     /system/build.prop,
    #     /odm/build.prop,
    #     /vendor/build.prop and
    #     /factory/factory.prop
    load_system_props
    # start essential services
    start logd
    start servicemanager
    start hwservicemanager
    start vndservicemanager

post-fs触发之后,在原先(Android O之前)启动servicemanager的时候,把hwservicemanager和vndservicemanager都启动了!

post-fs触发时机:


#节选自system/core/rootdir/init.rc
...
on late-init
...
    trigger post-fs

而late-init是在这触发的:

system/core/init/init.cpp


...
    std::string bootmode = GetProperty("ro.bootmode", "");
    if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
    } else {
        am.QueueEventTrigger("late-init");
    }
...

启动模式不是“charger”就触发这个。。。什么鬼

我们找到hwservicemanager:

先看看编译文件/system/hwservicemanager/Android.bp


...
cc_binary {
    name: "hwservicemanager",
    init_rc: [
        "hwservicemanager.rc",
    ],
    srcs: [
        "AccessControl.cpp",
        "HidlService.cpp",
        "ServiceManager.cpp",
        "service.cpp",
        "TokenManager.cpp",
        "Vintf.cpp",
    ],
  ...

/system/hwservicemanager/hwservicemanager.rc


service hwservicemanager /system/bin/hwservicemanager                                       user system
    disabled
    group system readproc
    critical
    onrestart setprop hwservicemanager.ready false
    onrestart class_restart hal
    onrestart class_restart early_hal
    writepid /dev/cpuset/system-background/tasks
    class animation

会启动一个二进制可执行程序hwservicemanager,目录在/system/bin/

找main函数


//system/hwservicemanager/service.cpp
static std::string serviceName = "default";
int main() {
    ...
    ServiceManager *manager = new ServiceManager();
    if (!manager->add(serviceName, manager)) {
        ALOGE("Failed to register hwservicemanager with itself.");
    }
    TokenManager *tokenManager = new TokenManager();
    if (!manager->add(serviceName, tokenManager)) {
        ALOGE("Failed to register ITokenManager with hwservicemanager.");
    }
    sp<Looper> looper(Looper::prepare(0 /* opts */));
    int binder_fd = -1;
    //请求binder文件描述符
    IPCThreadState::self()->setupPolling(&binder_fd);
    if (binder_fd < 0) {
        ALOGE("Failed to aquire binder FD. Aborting...");
        return -1;
    }
    //刷新下
    IPCThreadState::self()->flushCommands();
    //添加hwbinder文件描述符到Looper
    sp<BinderCallback> cb(new BinderCallback);
    if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
            nullptr) != 1) {
        ALOGE("Failed to add hwbinder FD to Looper. Aborting...");
        return -1;
    }
    //告诉IPCThreadState 我们是service manager
    sp<BnHwServiceManager> service = new BnHwServiceManager(manager);
    IPCThreadState::self()->setTheContextObject(service);
    // 告诉binder kernel
    ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
    ...
    //写入hwservicemanager.ready属性节点
    rc = property_set("hwservicemanager.ready", "true");    
}

最后这个啰嗦一句

前面hwservicemanager.rc中有这个


onrestart setprop hwservicemanager.ready false

系统重启的时候,会将这个属性设置回去。

第二个点是IPCThreadState::self()->setTheContextObject(service);

搜索了下IPCThreadState,有两个结果


./system/libhwbinder/IPCThreadState.cpp
./frameworks/native/libs/binder/IPCThreadState.cpp

根据前面的#include

那么应该是这个专门给hw设计的(另外那个是给普通的binder用的)

setTheContextObject@android::hardware::IPCThreadState


//system/libhwbinder/IPCThreadState.cpp
void IPCThreadState::setTheContextObject(sp<BHwBinder> obj)
{
    mContextObject = obj;
}

到这里hwservicemanager算启动完成了。

/hardware/interfaces/automotive/vehicle/2.0/default/Android.mk


...
###############################################################################
# Vehicle HAL service
###############################################################################
include $(CLEAR_VARS)
LOCAL_MODULE := $(vhal_v2_0)-service
//LOCAL_INIT_RC的详细解释在
///system/core/init/README.md中有
LOCAL_INIT_RC := $(vhal_v2_0)-service.rc
//是否是设备专有模块
LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := hw

LOCAL_SRC_FILES := \
    VehicleService.cpp
    ...

里面的LOCAL_INIT_RC(Android N之后加入的)说明这个rc会被加入到init里,在mount_all执行完成之后,就会被运行(反正大概是这么个意思)!

我们只看看[email protected]这个:[email protected]


service vehicle-hal-2.0 /vendor/bin/hw/[email protected]
    //hal类属,方便同时启动或停止,
    class hal
    //这个看着眼熟
    user vehicle_network
    group system inet

m01/device/qcom/sepolicy/common/hal_audio.te


# Allow hal_audio to read soundcard state under /proc/asound
allow hal_audio proc_audiod:file r_file_perms;

allow hal_audio_default audio_data_file:dir rw_dir_perms;
allow hal_audio_default audio_data_file:file create_file_perms;

# Allow hal_audio_default to read sysfs_thermal dir/files for speaker protection
r_dir_file(hal_audio_default, sysfs_thermal)

userdebug_or_eng(`
  diag_use(hal_audio)
  #Allow access to debug fs
  allow hal_audio_default debugfs:dir r_dir_perms;
  allow hal_audio_default qti_debugfs:dir r_dir_perms;
  allow hal_audio_default qti_debugfs:file rw_file_perms;
')

#Allow access to firmware
allow hal_audio firmware_file:dir r_dir_perms;
allow hal_audio firmware_file:file r_file_perms;
#Split A2dp specific
binder_call(hal_audio,bluetooth)

#for perf hal call
hal_client_domain(hal_audio_default, hal_perf)
#allow acess to wcd_cpe
allow hal_audio sysfs_audio:file rw_file_perms;
allow hal_audio sysfs_audio:dir r_dir_perms ; 

//VehicleService.cpp


int main(int /* argc */, char* /* argv */ []) {
    auto store = std::make_unique<VehiclePropertyStore>();
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    auto service = std::make_unique<VehicleHalManager>(hal.get());

    configureRpcThreadpool(4, true /* callerWillJoin */);

    ALOGI("Registering as service...");
    service->registerAsService();
    ALOGI("Ready");
    joinRpcThreadpool();
}

make_unique是C++11中的语法,和new差不多总之,这里就是构造一个VehiclePropertyStore作为参数构造一个EmulatedVehicleHal,再作为参数。。。最后,生成VehicleHalManager对象,然后registerAsService。

registerAsService的实现:


///out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/[email protected]_genc++/gen/android/hardware/automotive/vehicle/2.0/VehicleAll.cpp
::android::status_t IVehicle::registerAsService(const std::string &serviceName) {
    ::android::hardware::details::onRegistration("[email protected]", "IVehicle", serviceName);

    const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm
            = ::android::hardware::defaultServiceManager();
    if (sm == nullptr) {
        return ::android::INVALID_OPERATION;
    }
    ::android::hardware::Return<bool> ret = sm->add(serviceName.c_str(), this);
    return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;
}

我们找到defaultServiceManager的位置(这个CPP的名字是XXXXManagement让我极度怀疑是不是作者拼错了)


//system/libhidl/transport/ServiceManagement.cpp
sp<IServiceManager> defaultServiceManager() {
    ...
      details::gDefaultServiceManager =
                    fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
                        ProcessState::self()->getContextObject(NULL));
    ...
}

上面传的一个参数,所以是这个,另外还有一个重载接受两个参数的

getContextObject@android::hardware::ProcessState


sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

分析不下去了(手动尴尬)!

百度了下,这个是分析普通的binder的:讲的挺好的

http://wangkuiwu.github.io/2014/09/04/Binder-defaultServiceManager/

总之,这个地方的sm应该就是前面特别早就启动的hwservicemanager(虽然流程没接上)。

继续上面的main函数分析

欣喜地可以发现:class VehicleHalManager : public IVehicle我们要找的就是它啦!它是一个被init.rc起来的后台服务!上文的set调用就流向这里了


//VehicleHalManager::set
...
auto status = mHal->set(value);
...

mHal是在VehicleHalManager的构造函数初始化列表里赋值的:


VehicleHalManager(VehicleHal* vehicleHal)
: mHal(vehicleHal),
...

vehicleHal就是auto hal = std::make_unique(store.get());类似于(new EmulatedVehicleHal).get.


VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
    VehiclePropValuePtr v = nullptr;

    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
    if (internalPropValue != nullptr) {
        v = getValuePool()->obtain(*internalPropValue);
    }

    *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
    return v;
}

v是一个VehicleHal::VehiclePropValuePtr即recyclable_ptr可回收指针?VehiclePropValue是在types.hal中定义的一个struct.最终体现在out目录下,types.h里。

VehiclePropValue这个struct没有set方法啊。而且命名上来说,它也不应该是mHal的一种类型啊!什么情况。

以下,先强行分析下

这个地方,其实应该是EmulatedVehicleHal调用的是它的set方法:


mPropStore->writeValue(propValue)
...
getEmulatorOrDie()->doSetValueFromClient(propValue);
...

再然后:VehiclePropertyStore::writeValue,一个很普通的方法!


VehicleEmulator* getEmulatorOrDie() {
        std::lock_guard<std::mutex> g(mEmulatorLock);
        if (mEmulator == nullptr) abort();
        return mEmulator;
    }
void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
    emulator::EmulatorMessage msg;
    emulator::VehiclePropValue *val = msg.add_value();
    //这个疑似
    populateProtoVehiclePropValue(val, &propValue);
    msg.set_status(emulator::RESULT_OK);
    msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
    txMsg(msg);
}
//我的天啊
void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
                                                    const VehiclePropValue* val) {
    protoVal->set_prop(val->prop);
    protoVal->set_value_type(toInt(getPropType(val->prop)));
    protoVal->set_timestamp(val->timestamp);
    protoVal->set_area_id(val->areaId);

    // Copy value data if it is set.
    //  - for bytes and strings, this is indicated by size > 0
    //  - for int32, int64, and float, copy the values if vectors have data
    if (val->value.stringValue.size() > 0) {
        protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
    }

    if (val->value.bytes.size() > 0) {
        protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
    }

    for (auto& int32Value : val->value.int32Values) {
        protoVal->add_int32_values(int32Value);
    }

    for (auto& int64Value : val->value.int64Values) {
        protoVal->add_int64_values(int64Value);
    }

    for (auto& floatValue : val->value.floatValues) {
        protoVal->add_float_values(floatValue);
    }
}

然后呢?没有然后了?类名叫车机仿真。难道这就算设置成功了?看来,需要有具体的Vendor厂家来做实现啊!

你可能感兴趣的:(安卓)