Android O 中CarAudioManager的调用流程分析

来源:互联网 发布:后拱辰享雪面霜知乎 编辑:程序博客网 时间:2024/05/22 06:52

RadioDemo中

CarAudioManger的初始化
//从CarService中取出Audio的mCarAudioManager = (CarAudioManager) mCarApi.getCarManager(android.car.Car.AUDIO_SERVICE);
请求AudioFocus
mCarAudioManager.requestAudioFocus(this, mRadioAudioAttributes,AudioManager.AUDIOFOCUS_GAIN, 0);//requestAudioFocus@CarAudioMangermAudioManager.requestAudioFocus

好吧,和普通手机的一样,本集终!

看看最常用的setStreamVolume吧

mCarAudioManager.setStreamVolume(mStreamType, progress, AudioManager.FLAG_PLAY_SOUND);//setStreamVolume@CarAudioService.java//检查Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME权限enforceAudioVolumePermission();mVolumeService.setStreamVolume(streamType, index, flags);//setStreamVolume@CarVolumeServicegetController().setStreamVolume(streamType, index, flags);//工厂mCarVolumeController = CarVolumeControllerFactory.createCarVolumeController(mContext,mAudioService, mAudioHal, mInputService);

CarVolumeController是CarVolumeService的内部类
CarVolumeControllerFactory内部又定义了两个CarVolumeController的子类:

SimpleCarVolumeController

//software mixer level
//还是最普通的,本分支剧终
mAudioManager.setStreamVolume(stream, index, flags);

CarExternalVolumeController

//直接跟audio模块,芯片交互?
setStreamVolume@CarExternalVolumeController@CarVolumeControllerFactory

setStreamVolumeInternalLocked(carContext, index, flags);

carContext的解释:

Currently car context and android logical stream are not
one-to-one mapping. In this API, Android side asks us to change a logical stream volume. If the current car audio context maps to this logical stream, then we change the volume for the current car audio context. Otherwise, we change the volume for the primary mapped car audio context.

setStreamVolumeInternalLocked@CarExternalVolumeController

//Convert an car context to the car stream.int carStream = carContextToCarStream(carContext);// For single channel, only adjust the volume when the audio context is the current one.    mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_HAL, carStream, index));    ...//MSG_UPDATE_HAL    case MSG_UPDATE_HAL:        ...        mHal.setStreamVolume(stream, volume);

且看看mHal:
private final AudioHalService mHal;

public class AudioHalService extends HalServiceBase
HalServiceBase是什么东西?

setStreamVolume@AudioHalService

int[] payload = {streamType, index, 0};mVehicleHal.set(VehicleProperty.AUDIO_VOLUME).to(payload);

mVehicleHal是什么?

private final VehicleHal mVehicleHal;public class VehicleHal extends IVehicleCallback.Stub

Abstraction for vehicle HAL. This class handles interface with native HAL and do basic parsing
of received data (type check). Then each event is sent to corresponding {@link HalServiceBase}
implementation. It is responsibility of {@link HalServiceBase} to convert data to corresponding
Car*Service for Car*Manager API.

mVehicleHal.set(VehicleProperty.AUDIO_VOLUME).to(payload);
set操作仅仅是说要修改的值,to操作才是真正传值!

packages/services/Car/service/src/com/android/car/hal/VehicleHal.java

void set(VehiclePropValue propValue) throws PropertyTimeoutException {         mHalClient.setValue(propValue);     }     @CheckResult     VehiclePropValueSetter set(int propId) {         return new VehiclePropValueSetter(mHalClient, propId, NO_AREA);     }     @CheckResult     VehiclePropValueSetter set(int propId, int areaId) {         return new VehiclePropValueSetter(mHalClient, propId, areaId);     }

调用to函数

void to(int[] values) throws PropertyTimeoutException {             for (int value : values) {                 mPropValue.value.int32Values.add(value);             }             submit();}void submit() throws PropertyTimeoutException {...HalClient client =  mClient.get();client.setValue(mPropValue);...}

setValue@HalClient

import android.hardware.automotive.vehicle.V2_0.IVehicle;IVehicle mVehicle;    ...mVehicle.set(propValue);    ...

IVehicle.java:
/out/target/common/gen/JAVA_LIBRARIES/android.hardware.automotive.vehicle-V2.0-java_intermediates/android/hardware/automotive/vehicle/V2_0

我们再往前追溯下:
mVehicle最终来自:
services/Car/service/src/com/android/car/CarService.java:

private static IVehicle getVehicle(@Nullable String interfaceName) {...    vehicle = android.hardware.automotive.vehicle.V2_0.IVehicle                         .getService();...}

即自动生成的IVehicle.java中的:

//没有参数的,默认getServicepublic static IVehicle getService() throws android.os.RemoteException {          return IVehicle.asInterface(android.os.HwBinder.getService("android.hardware.automotive.vehicle@2.0::IVehicle","default"));}

这个地方不能错过的一点是:

asInterface的参数:
android.os.HwBinder.getService("android.hardware.automotive.vehicle@2.0::IVehicle","default")
//一个新加入的类
//getService@android.os.HwBinder

public static native final IHwBinder getService(            String iface,            String serviceName)        throws RemoteException, NoSuchElementException;

竟然是native方法!

JHwBinder_native_getService@android_os_HwBinder.cpp

//获取hardware那边的ServiceManager//Android O中,每个硬件模块都会启动一个Service进程auto manager = hardware::defaultServiceManager();//在这里就是"android.hardware.automotive.vehicle@2.0::IVehicle"const char *ifaceNameCStr = env->GetStringUTFChars(ifaceNameObj, NULL);std::string ifaceName(ifaceNameCStr);...//C++层的vehicle@2.0,配有自己的rc,//这个地方取到的十有八九都是C++层的vehicle@2.0服务了//目前先不去详细论证了Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceNameHStr, serviceNameHStr);sp<hardware::IBinder> service = hardware::toBinder<            hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase>(ret);return JHwRemoteBinder::NewObject(env, service);

即相当于
binder = (各种转换)JHwRemoteBinder::NewObject(env, 名字为“android.hardware.automotive.vehicle@2.0::IVehicle”的服务);

JHwRemoteBinder::NewObject

// staticjobject JHwRemoteBinder::NewObject(        JNIEnv *env, const sp<hardware::IBinder> &binder) {        //CLASS_PATH = android/os/HwRemoteBinder    ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));    // XXX Have to look up the constructor here because otherwise that static    // class initializer isn't called and gProxyOffsets.constructID is undefined :(    jmethodID constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");    //构造了一个java的HwRemoteBinder对象    jobject obj = env->NewObject(clazz.get(), constructID);    //GetNativeContext获取    //上一步生成的HwRemoteBinder对象的mNativeContext变量    //应该是之前设置过    //然后调用setBinder    //之后调用getBinder取到的就是这个IVehicle服务了    JHwRemoteBinder::GetNativeContext(env, obj)->setBinder(binder);    return obj;}

到这一步结束,隐隐yueyue地,java和C++关联起来了!

上回说到,IVehicle.java中
getService中,调用了
IVehicle.asInterface(上边的native层的Vehicle服务相关的binder)

static IVehicle asInterface(android.os.IHwBinder binder) {...IVehicle proxy = new IVehicle.Proxy(binder);...return proxy;...}

构造函数Proxy@IVehicle

public Proxy(android.os.IHwBinder remote) {            mRemote = java.util.Objects.requireNonNull(remote);        }

那前面调用的set函数应该是这个:

public static final class Proxy implements IVehicle{...@Override         public int set(VehiclePropValue propValue)                 throws android.os.RemoteException {             android.os.HwParcel _hidl_request = new android.os.HwParcel();             _hidl_request.writeInterfaceToken(IVehicle.kInterfaceName);             propValue.writeToParcel(_hidl_request);             android.os.HwParcel _hidl_reply = new android.os.HwParcel();             try {                 mRemote.transact(4 /* set */, _hidl_request, _hidl_reply, 0 /* flags */);                 _hidl_reply.verifySuccess();                 _hidl_request.releaseTemporaryStorage();                  int _hidl_out_status = _hidl_reply.readInt32();                 return _hidl_out_status;             } finally {                 _hidl_reply.release();             }         }...}

注意:该文件中有onTransact的一端。应该是提供给另外一种调用方式的,我之前就走歪了!

这时候算是走完了Framework端的进程了。也就是所谓的Vendor Interface
接下来就是Vendor的实现了!

首先,看看这个:
android.hardware.automotive.vehicle@2.0-service.rc

service vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service    //hal类属,方便同时启动或停止,    class hal    //这个看着眼熟    user vehicle_network    group system inet

//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。
欣喜地可以发现:
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<impl::EmulatedVehicleHal>(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厂家来做实现啊!

原创粉丝点击