最终在 CarServiceHelperService 中通过 bindServiceAsUser 启动 CarService
frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
"com.android.internal.car.CarServiceHelperService";
private void run() {
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
}
private void startOtherServices() {
mActivityManagerService.systemReady(() -> {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
}
}
}
}
frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java
public class CarServiceHelperService extends SystemService {
private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
@Override
public void onStart() {
Intent intent = new Intent();
intent.setPackage("com.android.car");
intent.setAction(CAR_SERVICE_INTERFACE);
getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE,
UserHandle.SYSTEM)
System.loadLibrary("car-framework-service-jni");
}
}
通过 ICarImpl 实现
ackages/services/Car/service/src/com/android/car/CarService.java
package com.android.car;
public class CarService extends Service {
private ICarImpl mICarImpl;
private IVehicle mVehicle;
public void onCreate() {
// mVehicle 实际 VehicleService
mVehicle = getVehicle();
mICarImpl = new ICarImpl(this,
mVehicle,
SystemInterface.Builder.defaultSystemInterface(this).build(),
mCanBusErrorNotifier,
mVehicleInterfaceName);
mICarImpl.init();
ServiceManager.addService("car_service", mICarImpl);
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return mICarImpl;
}
// 获取 VehicleService
private static IVehicle getVehicle() {
return android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
}
}
packages/services/Car/service/src/com/android/car/ICarImpl.java
public class ICarImpl extends ICar.Stub {
private final CarPowerManagementService mCarPowerManagementService;
private final CarPropertyService mCarPropertyService;
private final CarServiceBase[] mAllServices;
// 参数二实际为 VehicleService
public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
mHal = new VehicleHal(vehicle);
mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),systemInterface);
// mHal.getPropertyHal() -> PropertyHalService
mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
mCarAudioService = new CarAudioService(serviceContext, mCarPowerManagementService,
mCarPropertyService);
List allServices = new ArrayList<>();
allServices.add(mCarPowerManagementService);
allServices.add(mCarPropertyService);
allServices.add(mCarAudioService);
mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}
@Override
public IBinder getCarService(String serviceName) {
switch (serviceName) {
case Car.CABIN_SERVICE:
case Car.HVAC_SERVICE:
return mCarPropertyService;
}
}
}
1) createCar()构建Car实例,
2) void connect() 与CarService建立连接,
3) getCarManager() 通过service_name获取CarService端细分服务的IBinder,通过装饰模式封装到本地对应的xxManager中.
右键查看图片
getCarService 通过 aidl 实现
packages/services/Car/car-lib/src/android/car/ICar.aidl
package android.car;
interface ICar {
oneway void setCarServiceHelper(in IBinder helper) = 0;
IBinder getCarService(in String serviceName) = 1;
int getCarConnectionType() = 2;
}
packages/services/Car/car-lib/src/android/car/Car.java
private final HashMap mServiceMap = new HashMap<>();
1) createCar()
public static Car createCar(Context context, ServiceConnection serviceConnectionListener,
@Nullable Handler handler) {
return new Car(context, serviceConnectionListener, handler);
}
public Car(Context context, ICar service, @Nullable Handler handler) {
mEventHandler = determineEventHandler(handler);
mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
mService = service;
}
private synchronized ICar getICarOrThrow(){
return mService;
}
2) connect()
public void connect() throws IllegalStateException {
mConnectionState = STATE_CONNECTING;
startCarService();
}
private void startCarService() {
Intent intent = new Intent();
intent.setPackage(CAR_SERVICE_PACKAGE); //"com.android.car"
intent.setAction(Car.CAR_SERVICE_INTERFACE_NAME); //"android.car.ICar"
boolean bound = mContext.bindServiceAsUser(intent, mServiceConnectionListener,
Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF);
}
3) getCarManager
public Object getCarManager(String serviceName){
CarManagerBase manager;
ICar service = getICarOrThrow();
manager = mServiceMap.get(serviceName);
//如果 service 未启动,则通过 createCarManager 创建启动 service,并最终放入 HashMap中
if (manager == null) {
IBinder binder = service.getCarService(serviceName);
manager = createCarManager(serviceName, binder);
mServiceMap.put(serviceName, manager);
}
return manager;
}
private CarManagerBase createCarManager(String serviceName, IBinder binder){
CarManagerBase manager = null;
switch (serviceName) {
case AUDIO_SERVICE:
manager = new CarAudioManager(binder, mContext, mEventHandler);
break;
case HVAC_SERVICE:
manager = new CarHvacManager(binder, mContext, mEventHandler);
break;
}
return manager;
}
CarHvacManager(hearting ventilation air conditioning) 通风空调
packages/apps/Car/Hvac/src/com/android/car/hvac/HvacController.java
@Override
public void onCreate() {
super.onCreate();
mCarApiClient = Car.createCar(this, mCarConnectionCallback);
mCarApiClient.connect();
}
private final CarConnectionCallback mCarConnectionCallback =
new CarConnectionCallback() {
@Override
public void onConnected(Car car) {
initHvacManager((CarHvacManager) mCarApiClient.getCarManager(android.car.Car.HVAC_SERVICE));
mHvacManagerReady.notifyAll();
}
}
private void initHvacManager(CarHvacManager carHvacManager) {
mHvacManager = carHvacManager;
}
关键通过 setBooleanProperty()、getBooleanProperty() 接口实现属性切换,功能控制。
public void requestRefresh(final Runnable r, final Handler h) {
final AsyncTask task = new AsyncTask() {
@Override
protected Void doInBackground(Void... unused) {
fetchTemperature(DRIVER_ZONE_ID);
fetchTemperature(PASSENGER_ZONE_ID);
fetchAcState();
fetchHvacPowerState();
}
}
}
// 空调开关设置,实际通过 getCarManager("android.car.Car.hvac") 获取 manager调用对应方法
private void fetchAcState() {
mDataStore.setAcState(mHvacManager.getBooleanProperty(CarHvacManager.ID_ZONED_AC_ON,
SEAT_ALL));
}
public void setAcState(final boolean state) {
final AsyncTask task = new AsyncTask() {
protected Void doInBackground(Void... unused) {
mHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON,
SEAT_ALL, state);
}
};
task.execute();
}
private void fetchHvacPowerState() {
mDataStore.setHvacPowerState(mHvacManager.getBooleanProperty(
CarHvacManager.ID_ZONED_HVAC_POWER_ON, SEAT_ALL));
}
public void setHvacPowerState(final boolean state) {
mHvacManager.setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON, SEAT_ALL, state);
mDataStore.setHvacPowerState(state);
}
CarHvacManager -> CarPropertyManager -> ICarProperty
packages/services/Car/car-lib/src/android/car/hardware/hvac/CarHvacManager.java
public final class CarHvacManager implements CarManagerBase {
private final CarPropertyManager mCarPropertyMgr;
public CarHvacManager(IBinder service, Context context, Handler handler) {
mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
}
public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val){
mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
}
}
packages/services/Car/car-lib/src/android/car/hardware/property/CarPropertyManager.java
public CarPropertyManager(IBinder service, @Nullable Handler handler, boolean dbg, String tag) {
mService = ICarProperty.Stub.asInterface(service);
}
public void setBooleanProperty(int prop, int area, boolean val){
setProperty(Boolean.class, prop, area, val);
}
private final ICarProperty mService;
public void setProperty(Class clazz, int propId, int area, E val){
mService.setProperty(new CarPropertyValue<>(propId, area, val));
}
packages/services/Car/car-lib/src/android/car/hardware/property/ICarProperty.aidl
package android.car.hardware.property;
interface ICarProperty {
CarPropertyValue getProperty(int prop, int zone) = 3;
void setProperty(in CarPropertyValue prop) = 4;
void setProps(in List props) = 5;
}
CarPropertyService 是 ICarProperty 接口的实现服务
packages/services/Car/service/src/com/android/car/CarPropertyService.java
public class CarPropertyService extends ICarProperty.Stub {
private final PropertyHalService mHal;
public CarPropertyService(Context context, PropertyHalService hal) {
mHal = hal;
mContext = context;
}
@Override
public void setProperty(CarPropertyValue prop) {
int propId = prop.getPropertyId();
ICarImpl.assertPermission(mContext, mHal.getWritePermission(propId));
mHal.setProperty(prop);
}
}
packages/services/Car/service/src/com/android/car/hal/PropertyHalService.java
private final VehicleHal mVehicleHal;
public PropertyHalService(VehicleHal vehicleHal) {
mPropIds = new PropertyHalServiceIds();
mSubscribedPropIds = new HashSet();
// 实际指向 VehicleHal
mVehicleHal = vehicleHal;
}
public void setProperty(CarPropertyValue prop) {
int halPropId = managerToHalPropId(prop.getPropertyId());
VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
mVehicleHal.set(halProp);
}
packages/services/Car/service/src/com/android/car/hal/VehicleHal.java
public class VehicleHal extends IVehicleCallback.Stub {
private final ArrayList mAllServices = new ArrayList<>();
// vehicle 实际为 VehicleService
public VehicleHal(IVehicle vehicle) {
mHandlerThread = new HandlerThread("VEHICLE-HAL");
mPowerHal = new PowerHalService(this);
//将 VehicleHal 注入 PropertyHalService 中
mPropertyHal = new PropertyHalService(this);
mInputHal = new InputHalService(this);
mVmsHal = new VmsHalService(this);
mDiagnosticHal = new DiagnosticHalService(this);
mAllServices.addAll(Arrays.asList(mPowerHal,
mInputHal,
mPropertyHal,
mDiagnosticHal,
mVmsHal));
mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
}
public PropertyHalService getPropertyHal() {
return mPropertyHal;
}
void set(VehiclePropValue propValue){
mHalClient.setValue(propValue);
setEventEnqueue(propValue);
}
packages/services/Car/service/src/com/android/car/hal/HalClient.java
// 同样 vehicle 实际为 VehicleService
HalClient(IVehicle vehicle, Looper looper, IVehicleCallback callback) {
mVehicle = vehicle;
Handler handler = new CallbackHandler(looper, callback);
mInternalCallback = new VehicleCallback(handler);
}
public void setValue(VehiclePropValue propValue) {
// 所以实际 VehicleService.set() 方法
return mVehicle.set(propValue);
}
hardware/interfaces/automotive/vehicle/2.0/types.hal
enum VehicleArea : int32_t {
GLOBAL = 0x01000000,
/** WINDOW maps to enum VehicleAreaWindow */
WINDOW = 0x03000000,
/** MIRROR maps to enum VehicleAreaMirror */
MIRROR = 0x04000000,
/** SEAT maps to enum VehicleAreaSeat */
SEAT = 0x05000000,
/** DOOR maps to enum VehicleAreaDoor */
DOOR = 0x06000000,
/** WHEEL maps to enum VehicleAreaWheel */
WHEEL = 0x07000000,
MASK = 0x0f000000,
};
enum VehiclePropertyGroup : int32_t {
SYSTEM = 0x10000000,
VENDOR = 0x20000000,
MASK = 0xf0000000,
}
enum VehicleProperty : int32_t {
INFO_VIN = (
0x0100
| VehiclePropertyGroup:SYSTEM
| VehiclePropertyType:STRING
| VehicleArea:GLOBAL),
}
struct VehiclePropValue {
int64_t timestamp;
int32_t areaId;
int32_t prop;
VehiclePropertyStatus status;
RawValue value;
}
hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal
package [email protected];
interface IVehicle {
// 获取 Vehicle property 值
get(VehiclePropValue requestedPropValue)
generates (StatusCode status, VehiclePropValue propValue);
// 设置 Vehicle property 值
set(VehiclePropValue propValue) generates (StatusCode status);
}
hardware/interfaces/automotive/vehicle/2.0/default/VehicleService.cpp
int main(int /* argc */, char* /* argv */ []) {
auto store = std::make_unique();
auto hal = std::make_unique(store.get());
// 以 EmulatedVehicleHal 为入参构造,新建线程以 SocketComm 封装,读取 socket 消息
auto emulator = std::make_unique(hal.get());
auto service = std::make_unique(hal.get());
status_t status = service->registerAsService();
}
使用时,通过 IVehicle::getService()->xxx()使用
hardware/interfaces/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
class VehicleHalManager : public IVehicle {
public:
VehicleHalManager(VehicleHal* vehicleHal)
: mHal(vehicleHal),
mSubscriptionManager(std::bind(&VehicleHalManager::onAllClientsUnsubscribed,
this, std::placeholders::_1)) {
init();
}
private:
VehicleHal* mHal;
}
hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
Return VehicleHalManager::set(const VehiclePropValue &value) {
auto prop = value.prop;
const auto* config = getPropConfigOrNull(prop);
handlePropertySetEvent(value);
// mHal 实际为 EmulatedVehicleHal
auto status = mHal->set(value);
}
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
: mPropStore(propStore), /*实际为 VehiclePropertyStore */
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
{}
StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
auto currentPropValue = mPropStore->readValueOrNull(propValue);
mPropStore->writeValue(propValue, shouldUpdateStatus)
getEmulatorOrDie()->doSetValueFromClient(propValue);
}
hardware/interfaces/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
using PropertyMap = std::map;
PropertyMap mPropertyValues;
const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
const VehiclePropertyStore::RecordId& recId) const {
auto it = mPropertyValues.find(recId);
return it == mPropertyValues.end() ? nullptr : &it->second;
}
bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
bool updateStatus) {
RecordId recId = getRecordIdLocked(propValue);
VehiclePropValue* valueToUpdate = const_cast(getValueOrNullLocked(recId));
if (valueToUpdate == nullptr) {
mPropertyValues.insert({ recId, propValue });
} else {
valueToUpdate->timestamp = propValue.timestamp;
valueToUpdate->value = propValue.value;
if (updateStatus) {
valueToUpdate->status = propValue.status;
}
}
}
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
// VehicleService.cpp 中 auto emulator = std::make_unique(hal.get());
class VehicleEmulator {
public:
VehicleEmulator(EmulatedVehicleHalIface* hal, std::unique_ptr comm = CommFactory::create())
: mHal { hal }, mComm(comm.release()),
// mThread 线程,执行方法 rxThread
mThread { &VehicleEmulator::rxThread, this}
{
// 所以 EmulatedVehicleHal -> registerEmulator(VehicleEmulator)
// getEmulatorOrDie() 实际返回的也是 VehicleEmulator 对象
mHal->registerEmulator(this);
}
private:
std::unique_ptr mComm;
std::thread mThread;
}
class EmulatedVehicleHalIface : public VehicleHal {
public:
void registerEmulator(VehicleEmulator* emulator) {
mEmulator = emulator;
}
protected:
VehicleEmulator* getEmulatorOrDie() {
return mEmulator;
}
private:
VehicleEmulator* mEmulator;
}
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
static constexpr int DEBUG_SOCKET = 33452;//通信端口
int SocketComm::open() {
mSockFd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(DEBUG_SOCKET);
bind(mSockFd, reinterpret_cast(&servAddr), sizeof(servAddr));
listen(mSockFd, 1);
}
int SocketComm::connect() {
// 接受客户端连接,后续用新的 socketFd 进行读写通信
int cSockFd = accept(mSockFd, reinterpret_cast(&cliAddr), &cliLen);
mCurSockFd = cSockFd;
}
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
std::unique_ptr CommFactory::create() {
// 新建 socket 通信对象指针,用户tx/rx 读写消息
return std::make_unique();
}
// 读取消息线程,在 VehicleService 启动并新建 VehicleEmulator 对象,该线程即启动
void VehicleEmulator::rxThread() {
// 网络通信初始化,socket bind/listen
int retVal = mComm->open();
while (!mExit) {
// 等待客户端新的连接请求
retVal = mComm->connect();
if (retVal >= 0) {
rxMsg();//处理消息
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void VehicleEmulator::rxMsg() {
while (!mExit) {
std::vector msg = mComm->read();
if (msg.size() > 0) {
parseRxProtoBuf(msg);
}
}
}
void VehicleEmulator::parseRxProtoBuf(std::vector& msg) {
emulator::EmulatorMessage rxMsg;
emulator::EmulatorMessage respMsg;
if (rxMsg.ParseFromArray(msg.data(), static_cast(msg.size()))) {
switch (rxMsg.msg_type()) {
case emulator::GET_PROPERTY_CMD:
doGetProperty(rxMsg, respMsg);
break;
case emulator::SET_PROPERTY_CMD:
doSetProperty(rxMsg, respMsg);
break;
}
txMsg(respMsg);
}
}
void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) {
int numBytes = txMsg.ByteSize();
std::vector msg(static_cast(numBytes));
int retVal = mComm->write(msg);
}
void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
emulator::EmulatorMessage msg;
emulator::VehiclePropValue *val = msg.add_value();
populateProtoVehiclePropValue(val, &propValue);
// 通过 socket 发送消息(状态,消息类型)
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_status((emulator::VehiclePropStatus)(val->status));
protoVal->set_area_id(val->areaId);
}
void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) {
int numBytes = txMsg.ByteSize();
std::vector msg(static_cast(numBytes));
int retVal = mComm->write(msg);
}
void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg)
{
emulator::VehiclePropGet getProp = rxMsg.prop(0);
int32_t propId = getProp.prop();
respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
{
VehiclePropValue request = { .prop = propId, .areaId = areaId };
auto val = mHal->get(request, &halStatus);
if (val != nullptr) {
emulator::VehiclePropValue* protoVal = respMsg.add_value();
populateProtoVehiclePropValue(protoVal, val.get());
}
}
respMsg.set_status(status);
}
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
syntax = "proto2";
package emulator; //会变成 namespace emulator {}
enum MsgType {}
message VehicleAreaConfig {}
message VehiclePropValue {}
message EmulatorMessage{}
编译生成代码:
out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/default/impl/
vhal_v2_0/proto/[email protected]/android_arm64_armv8-a_vendor_static/gen/proto/
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.pb.h
namespace emulator {
class VehiclePropValue : public ::google::protobuf::MessageLite {
::google::protobuf::int32 prop_;
::google::protobuf::int32 value_type_;
::google::protobuf::int64 timestamp_;
void set_prop(::google::protobuf::int32 value);
void set_value_type(::google::protobuf::int32 value);
}
class EmulatorMessage : public ::google::protobuf::MessageLite {
public:
EmulatorMessage();
const ::emulator::VehiclePropValue& value(int index) const;
::emulator::VehiclePropValue* add_value();
private:
int msg_type_;
int status_;
::google::protobuf::RepeatedPtrField< ::emulator::VehiclePropGet > prop_;
::google::protobuf::RepeatedPtrField< ::emulator::VehiclePropConfig > config_;
::google::protobuf::RepeatedPtrField< ::emulator::VehiclePropValue > value_;
}
class VehiclePropGet : public ::google::protobuf::MessageLite {
public:
VehiclePropGet();
::google::protobuf::int32 prop() const;
void set_prop(::google::protobuf::int32 value);
}
}
out/soong/intermediates/hardware/interfaces/automotive/vehicle/2.0/default/impl/
vhal_v2_0/proto/[email protected]/android_arm64_armv8-a_vendor_static/gen/proto/
hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.pb.cc
::google::protobuf::int32 VehiclePropValue::prop() const {
// @@protoc_insertion_point(field_get:emulator.VehiclePropValue.prop)
return prop_;
}
void VehiclePropValue::set_prop(::google::protobuf::int32 value) {
set_has_prop();
prop_ = value;
// @@protoc_insertion_point(field_set:emulator.VehiclePropValue.prop)
}
::emulator::VehiclePropValue* EmulatorMessage::add_value() {
// @@protoc_insertion_point(field_add:emulator.EmulatorMessage.value)
return value_.Add();
}
::google::protobuf::int32 VehiclePropGet::prop() const {
// @@protoc_insertion_point(field_get:emulator.VehiclePropGet.prop)
return prop_;
}
void VehiclePropGet::set_prop(::google::protobuf::int32 value) {
set_has_prop();
prop_ = value;
// @@protoc_insertion_point(field_set:emulator.VehiclePropGet.prop)
}
const ::google::protobuf::RepeatedPtrField< ::emulator::VehiclePropGet >&
EmulatorMessage::prop() const {
// @@protoc_insertion_point(field_list:emulator.EmulatorMessage.prop)
return prop_;
}