1.需求
解决系统升级困难的问题(模块化)
a.以前用.h头文件的形式,各自Vendor有各自的so去实现硬件功能。
现在改成.hal文件的形式(Binder化),类似.aidl.
Thegoal of HIDL is that the framework can be replaced without having torebuild HALs. HALs will be built by vendors or SOC makers and put ina /vendor partitionon the device, enabling the framework, in its own partition, to bereplaced with an OTA without recompiling the HALs.
b.以前的输出打包进system里的一个个so
现在整个Vendor的东西应该是单独的一个啥?是一个vendor.img(里头有so),那么系统升级的时候,system.img就可以单拿出来。不用找各个硬件供应商,就可以用升级过的system.img去做替换升级
屁话少说,放码过来。
「Talk is cheap. Show me the code」
RadioDemo中
CarAudioManger的初始化
//从CarService中取出Audio的
mCarAudioManager = (CarAudioManager) mCarApi.getCarManager(android.car.Car.AUDIO_SERVICE);
请求AudioFocus
mCarAudioManager.requestAudioFocus(this, mRadioAudioAttributes,AudioManager.AUDIOFOCUS_GAIN, 0);
//requestAudioFocus@CarAudioManger
mAudioManager.requestAudioFocus
好吧,和普通手机的一样,本集终!
看看最常用的setStreamVolume吧
mCarAudioManager.setStreamVolume(mStreamType, progress, AudioManager.FLAG_PLAY_SOUND);
//[email protected]
//检查Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME权限
enforceAudioVolumePermission();
mVolumeService.setStreamVolume(streamType, index, flags);
//setStreamVolume@CarVolumeService
getController().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模块,audio hal交互?
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.
山寨翻译:
当前的car context和安卓逻辑流不是一对一的。在这个API中,安卓侧请求我们改变一个逻辑流音量。如果当前car audio context匹配这个逻辑流,我们为当前的car audio context改变音量。否则,我们为主匹配的car audio context音量。WTF,我也没懂。
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
CarService for CarManager API.
山寨翻译:
车机HAL的抽象。这个类处理和native HAL相关的interface,做一些收到数据的基本处理(类型检查)。然后每一个event被送到对应的实现(HalServiceBase).它有责任为CarManager API转换数据到对应的CarService.
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);
...
这个地方要插一句
hardware/interfaces/automotive/vehicle/2.0/types.hal中定义的
VehicleProperty.这个基本机构,基本包括了音量,空调温度,转向等等一些车相关的属性。
也即
车机相关的东西控制,基本可以通过mVehicle.set(propValue)这种方式去控制
当然了,这里除了mVehicle.set,也有public VehiclePropValue get(int propertyId)这样的方法
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中的:
//没有参数的,默认getService
public static IVehicle getService() throws android.os.RemoteException {
return IVehicle.asInterface(android.os.HwBinder.getService("[email protected]::IVehicle","default"));
}
这个地方不能错过的一点是:
asInterface的参数:
android.os.HwBinder.getService(“[email protected]::IVehicle”,”default”)
//一个新加入的类
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();
//在这里就是"[email protected]::IVehicle"
const char *ifaceNameCStr = env->GetStringUTFChars(ifaceNameObj, NULL);
std::string ifaceName(ifaceNameCStr);
...
//C++层的[email protected],配有自己的rc,
//这个地方取到的十有八九都是C++层的[email protected]服务了
//目前先不去详细论证了
Return> ret = manager->get(ifaceNameHStr, serviceNameHStr);
sp service = hardware::toBinder<
hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase>(ret);
return JHwRemoteBinder::NewObject(env, service);
即相当于
binder = (各种转换)JHwRemoteBinder::NewObject(env, 名字为“[email protected]::IVehicle”的服务);
JHwRemoteBinder::NewObject
// static
jobject JHwRemoteBinder::NewObject(
JNIEnv *env, const sp &binder) {
//CLASS_PATH = android/os/HwRemoteBinder
ScopedLocalRef 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(), "", "()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的客户端。
接下来说说
从CarAudioManager调用流程开始学习Vendor Interface(Service部分)