Add vehicle HAL mocking with carsystem and carsystemtest API
- System API and system test API for testing only added. Client
should link only one of them.
- vehicle HAL mocking allows mocking vehicle HAL completely.
- Once mocking is started, for now, all previous states are forgotton,
so stopping mocking does not return to original state. It is
better to simply restart framework after test.
- Added skeleton code for audio focus handling. Detailed implementaiton
will be added later.
bug: 24874617
Change-Id: I6e60daab3dc96769a94acc09a695f8f49dbb8536
(cherry picked from commit a32e24f50d5895a94d3a13d6ec2233af6e43dac5)
diff --git a/libvehiclenetwork/native/IVehicleNetworkHalMock.cpp b/libvehiclenetwork/native/IVehicleNetworkHalMock.cpp
new file mode 100644
index 0000000..8652f17
--- /dev/null
+++ b/libvehiclenetwork/native/IVehicleNetworkHalMock.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VehicleNetwork"
+
+#include <memory>
+
+#include <binder/IPCThreadState.h>
+#include <private/android_filesystem_config.h>
+
+#include <utils/Log.h>
+
+#include <IVehicleNetwork.h>
+#include <IVehicleNetworkHalMock.h>
+#include <VehicleNetworkProto.pb.h>
+
+#include "BinderUtil.h"
+#include "VehicleNetworkProtoUtil.h"
+
+namespace android {
+
+enum {
+ ON_LIST_PROPERTIES = IBinder::FIRST_CALL_TRANSACTION,
+ ON_PROPERTY_SET,
+ ON_PROPERTY_GET,
+ ON_SUBSCRIBE,
+ ON_UNSUBSCRIBE,
+};
+
+// ----------------------------------------------------------------------------
+
+const char IVehicleNetworkHalMock::SERVICE_NAME[] =
+ "com.android.car.vehiclenetwork.IVehicleNetworkHalMock";
+
+// ----------------------------------------------------------------------------
+
+class BpVehicleNetworkHalMock : public BpInterface<IVehicleNetworkHalMock> {
+public:
+ BpVehicleNetworkHalMock(const sp<IBinder> & impl)
+ : BpInterface<IVehicleNetworkHalMock>(impl) {
+ }
+
+ virtual sp<VehiclePropertiesHolder> onListProperties() {
+ sp<VehiclePropertiesHolder> holder;
+ Parcel data, reply;
+ data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
+ status_t status = remote()->transact(ON_LIST_PROPERTIES, data, &reply);
+ if (status == NO_ERROR) {
+ reply.readExceptionCode(); // for compatibility with java
+ if (reply.readInt32() == 0) { // no result
+ return holder;
+ }
+ ReadableBlobHolder blob(new Parcel::ReadableBlob());
+ if (blob.blob == NULL) {
+ ALOGE("listProperties, no memory");
+ return holder;
+ }
+ int32_t size = reply.readInt32();
+ status = reply.readBlob(size, blob.blob);
+ if (status != NO_ERROR) {
+ ALOGE("listProperties, cannot read blob %d", status);
+ return holder;
+ }
+ //TODO make this more memory efficient
+ std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
+ if (configs.get() == NULL) {
+ return holder;
+ }
+ if(!configs->ParseFromArray(blob.blob->data(), size)) {
+ ALOGE("listProperties, cannot parse reply");
+ return holder;
+ }
+ holder = new VehiclePropertiesHolder();
+ ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
+ status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
+ holder->getList());
+ if (status != NO_ERROR) {
+ ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
+ return holder;
+ }
+
+ }
+ return holder;
+ }
+
+ virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
+ data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
+ std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
+ ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
+ VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
+ int size = v->ByteSize();
+ WritableBlobHolder blob(new Parcel::WritableBlob());
+ ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
+ data.writeInt32(size);
+ data.writeBlob(size, false, blob.blob);
+ v->SerializeToArray(blob.blob->data(), size);
+ status_t status = remote()->transact(ON_PROPERTY_SET, data, &reply);
+ return status;
+ }
+
+ virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
+ // only needs to send property itself.
+ data.writeInt32(value->prop);
+ status_t status = remote()->transact(ON_PROPERTY_GET, data, &reply);
+ if (status == NO_ERROR) {
+ reply.readExceptionCode(); // for compatibility with java
+ if (reply.readInt32() == 0) { // no result
+ return BAD_VALUE;
+ }
+ ReadableBlobHolder blob(new Parcel::ReadableBlob());
+ ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
+ int32_t size = reply.readInt32();
+ status = reply.readBlob(size, blob.blob);
+ if (status != NO_ERROR) {
+ ALOGE("getProperty, cannot read blob");
+ return status;
+ }
+ std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
+ ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
+ if (!v->ParseFromArray(blob.blob->data(), size)) {
+ ALOGE("getProperty, cannot parse reply");
+ return BAD_VALUE;
+ }
+ status = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), *value);
+ }
+ return status;
+ }
+
+ virtual status_t onPropertySubscribe(int32_t property, float sampleRate) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
+ data.writeInt32(property);
+ data.writeFloat(sampleRate);
+ status_t status = remote()->transact(ON_SUBSCRIBE, data, &reply);
+ return status;
+ }
+
+ virtual void onPropertyUnsubscribe(int32_t property) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
+ data.writeInt32(property);
+ status_t status = remote()->transact(ON_UNSUBSCRIBE, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGI("onPropertyUnsubscribe property %d failed %d", property, status);
+ }
+ }
+};
+
+IMPLEMENT_META_INTERFACE(VehicleNetworkHalMock, IVehicleNetworkHalMock::SERVICE_NAME);
+
+// ----------------------------------------------------------------------
+
+static bool isSystemUser() {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ switch (uid) {
+ // This list will be expanded. Only those UIDs are allowed to access vehicle network
+ // for now. There can be per property based UID check built-in as well.
+ case AID_ROOT:
+ case AID_SYSTEM:
+ case AID_AUDIO: {
+ return true;
+ } break;
+ default: {
+ ALOGE("non-system user tried access, uid %d", uid);
+ } break;
+ }
+ return false;
+}
+
+status_t BnVehicleNetworkHalMock::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ if (!isSystemUser()) {
+ return PERMISSION_DENIED;
+ }
+ status_t r;
+ switch (code) {
+ case ON_LIST_PROPERTIES: {
+ CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
+ sp<VehiclePropertiesHolder> holder = onListProperties();
+ if (holder.get() == NULL) { // given property not found
+ BinderUtil::fillObjectResultReply(reply, false /* isValid */);
+ return NO_ERROR;
+ }
+ std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
+ ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
+ VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
+ int size = configs->ByteSize();
+ WritableBlobHolder blob(new Parcel::WritableBlob());
+ ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
+ BinderUtil::fillObjectResultReply(reply, true);
+ reply->writeInt32(size);
+ reply->writeBlob(size, false, blob.blob);
+ configs->SerializeToArray(blob.blob->data(), size);
+ return NO_ERROR;
+ } break;
+ case ON_PROPERTY_SET: {
+ CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
+ if (data.readInt32() == 0) { // java side allows passing null with this.
+ return BAD_VALUE;
+ }
+ ScopedVehiclePropValue value;
+ ReadableBlobHolder blob(new Parcel::ReadableBlob());
+ ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
+ int32_t size = data.readInt32();
+ r = data.readBlob(size, blob.blob);
+ if (r != NO_ERROR) {
+ ALOGE("setProperty:service, cannot read blob");
+ return r;
+ }
+ std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
+ ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
+ if (!v->ParseFromArray(blob.blob->data(), size)) {
+ ALOGE("setProperty:service, cannot parse data");
+ return BAD_VALUE;
+ }
+ r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
+ if (r != NO_ERROR) {
+ ALOGE("setProperty:service, cannot convert data");
+ return BAD_VALUE;
+ }
+ r = onPropertySet(value.value);
+ BinderUtil::fillNoResultReply(reply);
+ return r;
+ } break;
+ case ON_PROPERTY_GET: {
+ CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
+ ScopedVehiclePropValue value;
+ value.value.prop = data.readInt32();
+ r = onPropertyGet(&(value.value));
+ if (r == NO_ERROR) {
+ BinderUtil::fillObjectResultReply(reply, true);
+ std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
+ ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
+ VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
+ int size = v->ByteSize();
+ WritableBlobHolder blob(new Parcel::WritableBlob());
+ ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
+ reply->writeInt32(size);
+ reply->writeBlob(size, false, blob.blob);
+ v->SerializeToArray(blob.blob->data(), size);
+ }
+ return r;
+ } break;
+ case ON_SUBSCRIBE: {
+ CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
+ int32_t property = data.readInt32();
+ float sampleRate = data.readFloat();
+ r = onPropertySubscribe(property, sampleRate);
+ BinderUtil::fillNoResultReply(reply);
+ return r;
+ } break;
+ case ON_UNSUBSCRIBE: {
+ CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
+ int32_t property = data.readInt32();
+ onPropertyUnsubscribe(property);
+ BinderUtil::fillNoResultReply(reply);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android