blob: 7bc9f8bbce521643a410aa6a213168c818531766 [file] [log] [blame]
keunyoung1ab8e182015-09-24 09:25:22 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "VehicleNetwork"
18
19#include <memory>
20
21#include <binder/IPCThreadState.h>
22#include <private/android_filesystem_config.h>
23
24#include <utils/Log.h>
25
26#include <IVehicleNetwork.h>
27#include <IVehicleNetworkHalMock.h>
28#include <VehicleNetworkProto.pb.h>
29
30#include "BinderUtil.h"
31#include "VehicleNetworkProtoUtil.h"
32
33namespace android {
34
35enum {
36 ON_LIST_PROPERTIES = IBinder::FIRST_CALL_TRANSACTION,
37 ON_PROPERTY_SET,
38 ON_PROPERTY_GET,
39 ON_SUBSCRIBE,
40 ON_UNSUBSCRIBE,
41};
42
43// ----------------------------------------------------------------------------
44
45const char IVehicleNetworkHalMock::SERVICE_NAME[] =
46 "com.android.car.vehiclenetwork.IVehicleNetworkHalMock";
47
48// ----------------------------------------------------------------------------
49
50class BpVehicleNetworkHalMock : public BpInterface<IVehicleNetworkHalMock> {
51public:
52 BpVehicleNetworkHalMock(const sp<IBinder> & impl)
53 : BpInterface<IVehicleNetworkHalMock>(impl) {
54 }
55
56 virtual sp<VehiclePropertiesHolder> onListProperties() {
57 sp<VehiclePropertiesHolder> holder;
58 Parcel data, reply;
59 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
60 status_t status = remote()->transact(ON_LIST_PROPERTIES, data, &reply);
61 if (status == NO_ERROR) {
62 reply.readExceptionCode(); // for compatibility with java
63 if (reply.readInt32() == 0) { // no result
64 return holder;
65 }
66 ReadableBlobHolder blob(new Parcel::ReadableBlob());
67 if (blob.blob == NULL) {
68 ALOGE("listProperties, no memory");
69 return holder;
70 }
71 int32_t size = reply.readInt32();
Keun-young Park20539ba2016-10-10 17:57:34 -070072 if (size < 0) {
73 ALOGE("listProperties, bad blob size %d", size);
74 return holder;
75 }
keunyoung1ab8e182015-09-24 09:25:22 -070076 status = reply.readBlob(size, blob.blob);
77 if (status != NO_ERROR) {
78 ALOGE("listProperties, cannot read blob %d", status);
79 return holder;
80 }
keunyoung1ab8e182015-09-24 09:25:22 -070081 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
82 if (configs.get() == NULL) {
83 return holder;
84 }
85 if(!configs->ParseFromArray(blob.blob->data(), size)) {
86 ALOGE("listProperties, cannot parse reply");
87 return holder;
88 }
89 holder = new VehiclePropertiesHolder();
90 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
91 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
92 holder->getList());
93 if (status != NO_ERROR) {
94 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
95 return holder;
96 }
97
98 }
99 return holder;
100 }
101
102 virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
103 Parcel data, reply;
104 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700105 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, value);
106 if (status != NO_ERROR) {
107 return status;
108 }
109 status = remote()->transact(ON_PROPERTY_SET, data, &reply);
keunyoung1ab8e182015-09-24 09:25:22 -0700110 return status;
111 }
112
113 virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
keunyoung7d74e6d2015-10-14 15:43:10 -0700114 if (value == NULL) {
115 return BAD_VALUE;
116 }
keunyoung1ab8e182015-09-24 09:25:22 -0700117 Parcel data, reply;
118 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700119 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, *value);
120 if (status != NO_ERROR) {
121 return status;
122 }
123 status = remote()->transact(ON_PROPERTY_GET, data, &reply);
keunyoung1ab8e182015-09-24 09:25:22 -0700124 if (status == NO_ERROR) {
125 reply.readExceptionCode(); // for compatibility with java
keunyoung7d74e6d2015-10-14 15:43:10 -0700126 status = VehiclePropValueBinderUtil::readFromParcel(reply, value);
keunyoung1ab8e182015-09-24 09:25:22 -0700127 }
128 return status;
129 }
130
Keun-young Park0727f952015-12-21 14:30:07 -0800131 virtual status_t onPropertySubscribe(int32_t property, float sampleRate, int32_t zones) {
keunyoung1ab8e182015-09-24 09:25:22 -0700132 Parcel data, reply;
133 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
134 data.writeInt32(property);
135 data.writeFloat(sampleRate);
Keun-young Park0727f952015-12-21 14:30:07 -0800136 data.writeInt32(zones);
keunyoung1ab8e182015-09-24 09:25:22 -0700137 status_t status = remote()->transact(ON_SUBSCRIBE, data, &reply);
138 return status;
139 }
140
141 virtual void onPropertyUnsubscribe(int32_t property) {
142 Parcel data, reply;
143 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
144 data.writeInt32(property);
145 status_t status = remote()->transact(ON_UNSUBSCRIBE, data, &reply);
146 if (status != NO_ERROR) {
147 ALOGI("onPropertyUnsubscribe property %d failed %d", property, status);
148 }
149 }
150};
151
152IMPLEMENT_META_INTERFACE(VehicleNetworkHalMock, IVehicleNetworkHalMock::SERVICE_NAME);
153
154// ----------------------------------------------------------------------
155
156static bool isSystemUser() {
157 uid_t uid = IPCThreadState::self()->getCallingUid();
158 switch (uid) {
159 // This list will be expanded. Only those UIDs are allowed to access vehicle network
160 // for now. There can be per property based UID check built-in as well.
161 case AID_ROOT:
162 case AID_SYSTEM:
163 case AID_AUDIO: {
164 return true;
165 } break;
166 default: {
167 ALOGE("non-system user tried access, uid %d", uid);
168 } break;
169 }
170 return false;
171}
172
173status_t BnVehicleNetworkHalMock::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
174 uint32_t flags) {
175 if (!isSystemUser()) {
176 return PERMISSION_DENIED;
177 }
178 status_t r;
179 switch (code) {
180 case ON_LIST_PROPERTIES: {
181 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
182 sp<VehiclePropertiesHolder> holder = onListProperties();
183 if (holder.get() == NULL) { // given property not found
184 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
185 return NO_ERROR;
186 }
187 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
188 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
189 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
190 int size = configs->ByteSize();
191 WritableBlobHolder blob(new Parcel::WritableBlob());
192 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
193 BinderUtil::fillObjectResultReply(reply, true);
194 reply->writeInt32(size);
195 reply->writeBlob(size, false, blob.blob);
196 configs->SerializeToArray(blob.blob->data(), size);
197 return NO_ERROR;
198 } break;
199 case ON_PROPERTY_SET: {
200 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
201 if (data.readInt32() == 0) { // java side allows passing null with this.
202 return BAD_VALUE;
203 }
204 ScopedVehiclePropValue value;
205 ReadableBlobHolder blob(new Parcel::ReadableBlob());
206 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
207 int32_t size = data.readInt32();
Keun-young Park20539ba2016-10-10 17:57:34 -0700208 if (size < 0) {
209 ALOGE("setProperty:service, bad blob size %d", size);
210 return BAD_VALUE;
211 }
keunyoung1ab8e182015-09-24 09:25:22 -0700212 r = data.readBlob(size, blob.blob);
213 if (r != NO_ERROR) {
214 ALOGE("setProperty:service, cannot read blob");
215 return r;
216 }
217 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
218 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
219 if (!v->ParseFromArray(blob.blob->data(), size)) {
220 ALOGE("setProperty:service, cannot parse data");
221 return BAD_VALUE;
222 }
223 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
224 if (r != NO_ERROR) {
225 ALOGE("setProperty:service, cannot convert data");
226 return BAD_VALUE;
227 }
228 r = onPropertySet(value.value);
229 BinderUtil::fillNoResultReply(reply);
230 return r;
231 } break;
232 case ON_PROPERTY_GET: {
233 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
234 ScopedVehiclePropValue value;
Keun-young Parkaaeffaf2015-11-25 17:24:10 -0800235 r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
236 false /* deleteMembers */, true /*canIgnoreNoData*/);
237 if (r != NO_ERROR) {
238 ALOGE("onPropertyGet cannot read %d", r);
239 return r;
240 }
keunyoung1ab8e182015-09-24 09:25:22 -0700241 r = onPropertyGet(&(value.value));
242 if (r == NO_ERROR) {
243 BinderUtil::fillObjectResultReply(reply, true);
244 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
245 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
246 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
247 int size = v->ByteSize();
248 WritableBlobHolder blob(new Parcel::WritableBlob());
249 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
250 reply->writeInt32(size);
251 reply->writeBlob(size, false, blob.blob);
252 v->SerializeToArray(blob.blob->data(), size);
253 }
254 return r;
255 } break;
256 case ON_SUBSCRIBE: {
257 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
258 int32_t property = data.readInt32();
259 float sampleRate = data.readFloat();
Keun-young Park0727f952015-12-21 14:30:07 -0800260 int32_t zones = data.readInt32();
261 r = onPropertySubscribe(property, sampleRate, zones);
keunyoung1ab8e182015-09-24 09:25:22 -0700262 BinderUtil::fillNoResultReply(reply);
263 return r;
264 } break;
265 case ON_UNSUBSCRIBE: {
266 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
267 int32_t property = data.readInt32();
268 onPropertyUnsubscribe(property);
269 BinderUtil::fillNoResultReply(reply);
270 return NO_ERROR;
271 } break;
272 default:
273 return BBinder::onTransact(code, data, reply, flags);
274 }
275}
276
277}; // namespace android