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厂家来做实现啊!
- Android O 中CarAudioManager的调用流程分析
- Android中Camera的调用流程
- 分析Android中应用的启动流程
- 分析Android中应用的启动流程
- vtk中vtkDICOMImageReader调用流程分析
- Android O: 触摸事件传递流程源码分析(上)
- Android O: 触摸事件传递流程源码分析(下)
- Android系统中基于Binder的IPC流程框架分析
- 源码分析Android中View的绘制流程
- Android Recovery 的流程分析
- Android Recovery 的流程分析
- Android Recovery 的流程分析
- Android Recovery 的流程分析
- Android的UEvent流程分析
- Databinding简单的分析ImageView属性android:src="@{resImgId}"的调用流程
- 《Android开发艺术探索》读书笔记——Toast调用流程的源码分析
- socket调用流程分析
- FUSE调用流程分析
- spring-boot-admin基础搭建教程
- 前端基础(2):html语法(1)
- three.js 01-05 之使用 dat.GUI 库简化试验
- Ubuntu 16.10 文件服务器--samba的安装和配置
- GCD
- Android O 中CarAudioManager的调用流程分析
- Python异常处理
- Xcode 创建静态库
- 用HttpServletResponseWrappper 获取jsp 输出内容
- c++ std::function bind
- org.apache.zookeeper.KeeperException$InvalidACLException: KeeperErrorCode = InvalidACL for /f
- 【Android】AndroidStudio2.2.3 切换到AndroidStudio3.0之后问题处理记录
- 对一致性hash算法的理解
- 数据库设计 Step by Step (3)——基本ER模型构件