blob: 0ceb1a0b2f4c541ad9055ddce8958b8c64ec8341 [file] [log] [blame]
keunyounge18e25d2015-08-28 15:57:19 -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 <VehicleNetworkProto.pb.h>
28
keunyoung15882e52015-09-16 16:57:58 -070029#include "BinderUtil.h"
keunyounge18e25d2015-08-28 15:57:19 -070030#include "VehicleNetworkProtoUtil.h"
31
32namespace android {
33
34enum {
35 LIST_PROPERTIES = IBinder::FIRST_CALL_TRANSACTION,
36 SET_PROPERTY,
37 GET_PROPERTY,
38 SUBSCRIBE,
39 UNSUBSCRIBE,
keunyoung1ab8e182015-09-24 09:25:22 -070040 INJECT_EVENT,
41 START_MOCKING,
42 STOP_MOCKING,
Keun-young Park28dd4702015-11-19 18:06:04 -080043 INJECT_HAL_ERROR,
44 START_ERROR_LISTENING,
45 STOP_ERROR_LISTENING,
46 START_HAL_RESTART_MONITORING,
47 STOP_HAL_RESTART_MONITORING
keunyounge18e25d2015-08-28 15:57:19 -070048};
49
50// ----------------------------------------------------------------------------
51
keunyoung15882e52015-09-16 16:57:58 -070052const char IVehicleNetwork::SERVICE_NAME[] = "com.android.car.vehiclenetwork.IVehicleNetwork";
keunyounge18e25d2015-08-28 15:57:19 -070053
54// ----------------------------------------------------------------------------
55
56class BpVehicleNetwork : public BpInterface<IVehicleNetwork> {
57public:
58 BpVehicleNetwork(const sp<IBinder> & impl)
59 : BpInterface<IVehicleNetwork>(impl) {
60 }
61
62 virtual sp<VehiclePropertiesHolder> listProperties(int32_t property) {
63 sp<VehiclePropertiesHolder> holder;
64 Parcel data, reply;
65 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
66 data.writeInt32(property);
67 status_t status = remote()->transact(LIST_PROPERTIES, data, &reply);
68 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -070069 reply.readExceptionCode(); // for compatibility with java
keunyounge18e25d2015-08-28 15:57:19 -070070 if (reply.readInt32() == 0) { // no result
71 return holder;
72 }
73 ReadableBlobHolder blob(new Parcel::ReadableBlob());
74 if (blob.blob == NULL) {
75 ALOGE("listProperties, no memory");
76 return holder;
77 }
78 int32_t size = reply.readInt32();
79 status = reply.readBlob(size, blob.blob);
80 if (status != NO_ERROR) {
81 ALOGE("listProperties, cannot read blob %d", status);
82 return holder;
83 }
84 //TODO make this more memory efficient
85 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
86 if (configs.get() == NULL) {
87 return holder;
88 }
89 if(!configs->ParseFromArray(blob.blob->data(), size)) {
90 ALOGE("listProperties, cannot parse reply");
91 return holder;
92 }
keunyoungd32f4e62015-09-21 11:33:06 -070093 holder = new VehiclePropertiesHolder();
94 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
95 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
96 holder->getList());
keunyounge18e25d2015-08-28 15:57:19 -070097 if (status != NO_ERROR) {
98 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
99 return holder;
100 }
keunyoungd32f4e62015-09-21 11:33:06 -0700101
keunyounge18e25d2015-08-28 15:57:19 -0700102 }
103 return holder;
104 }
105
106 virtual status_t setProperty(const vehicle_prop_value_t& value) {
107 Parcel data, reply;
108 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700109 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, value);
110 if (status != NO_ERROR) {
111 return status;
112 }
113 status = remote()->transact(SET_PROPERTY, data, &reply);
keunyounge18e25d2015-08-28 15:57:19 -0700114 return status;
115 }
116
117 virtual status_t getProperty(vehicle_prop_value_t* value) {
118 Parcel data, reply;
keunyoung7d74e6d2015-10-14 15:43:10 -0700119 if (value == NULL) {
120 return BAD_VALUE;
121 }
keunyounge18e25d2015-08-28 15:57:19 -0700122 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700123 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, *value);
124 if (status != NO_ERROR) {
125 ALOGE("getProperty, cannot write");
126 return status;
127 }
128 status = remote()->transact(GET_PROPERTY, data, &reply);
keunyounge18e25d2015-08-28 15:57:19 -0700129 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700130 reply.readExceptionCode(); // for compatibility with java
keunyoung7d74e6d2015-10-14 15:43:10 -0700131 status = VehiclePropValueBinderUtil::readFromParcel(reply, value);
keunyounge18e25d2015-08-28 15:57:19 -0700132 }
133 return status;
134 }
135
136 virtual status_t subscribe(const sp<IVehicleNetworkListener> &listener, int32_t property,
137 float sampleRate) {
138 Parcel data, reply;
139 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
140 data.writeStrongBinder(IInterface::asBinder(listener));
141 data.writeInt32(property);
142 data.writeFloat(sampleRate);
143 status_t status = remote()->transact(SUBSCRIBE, data, &reply);
144 return status;
145 }
146
147 virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property) {
148 Parcel data, reply;
149 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
150 data.writeStrongBinder(IInterface::asBinder(listener));
151 data.writeInt32(property);
152 status_t status = remote()->transact(UNSUBSCRIBE, data, &reply);
153 if (status != NO_ERROR) {
154 ALOGI("unsubscribing property %d failed %d", property, status);
155 }
156 }
keunyoung1ab8e182015-09-24 09:25:22 -0700157
158 virtual status_t injectEvent(const vehicle_prop_value_t& value) {
159 Parcel data, reply;
160 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
161 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
162 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
163 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
164 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
165 int size = v->ByteSize();
166 WritableBlobHolder blob(new Parcel::WritableBlob());
167 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
168 data.writeInt32(size);
169 data.writeBlob(size, false, blob.blob);
170 v->SerializeToArray(blob.blob->data(), size);
171 status_t status = remote()->transact(INJECT_EVENT, data, &reply);
172 return status;
173 }
174
175 virtual status_t startMocking(const sp<IVehicleNetworkHalMock>& mock) {
176 Parcel data, reply;
177 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
178 data.writeStrongBinder(IInterface::asBinder(mock));
179 status_t status = remote()->transact(START_MOCKING, data, &reply);
180 return status;
181 }
182
183 virtual void stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
184 Parcel data, reply;
185 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
186 data.writeStrongBinder(IInterface::asBinder(mock));
187 status_t status = remote()->transact(STOP_MOCKING, data, &reply);
188 if (status != NO_ERROR) {
189 ALOGI("stop mocking failed %d", status);
190 }
191 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800192
193 status_t injectHalError(int32_t errorCode, int32_t property, int32_t operation) {
194 Parcel data, reply;
195 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
196 data.writeInt32(errorCode);
197 data.writeInt32(property);
198 data.writeInt32(operation);
199 status_t status = remote()->transact(INJECT_HAL_ERROR, data, &reply);
200 return status;
201 }
202
203 virtual status_t startErrorListening(const sp<IVehicleNetworkListener> &listener) {
204 Parcel data, reply;
205 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
206 data.writeStrongBinder(IInterface::asBinder(listener));
207 status_t status = remote()->transact(START_ERROR_LISTENING, data, &reply);
208 return status;
209 }
210
211 virtual void stopErrorListening(const sp<IVehicleNetworkListener> &listener) {
212 Parcel data, reply;
213 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
214 data.writeStrongBinder(IInterface::asBinder(listener));
215 status_t status = remote()->transact(STOP_ERROR_LISTENING, data, &reply);
216 if (status != NO_ERROR) {
217 ALOGI("stopErrorListening %d", status);
218 }
219 }
220
221 virtual status_t startHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
222 Parcel data, reply;
223 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
224 data.writeStrongBinder(IInterface::asBinder(listener));
225 status_t status = remote()->transact(START_HAL_RESTART_MONITORING, data, &reply);
226 return status;
227 }
228
229 virtual void stopHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
230 Parcel data, reply;
231 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
232 data.writeStrongBinder(IInterface::asBinder(listener));
233 status_t status = remote()->transact(STOP_HAL_RESTART_MONITORING, data, &reply);
234 if (status != NO_ERROR) {
235 ALOGI("stopHalRestartMonitoring %d", status);
236 }
237 }
keunyounge18e25d2015-08-28 15:57:19 -0700238};
239
240IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);
241
242// ----------------------------------------------------------------------
243
244static bool isSystemUser() {
245 uid_t uid = IPCThreadState::self()->getCallingUid();
246 switch (uid) {
247 // This list will be expanded. Only those UIDs are allowed to access vehicle network
248 // for now. There can be per property based UID check built-in as well.
249 case AID_ROOT:
250 case AID_SYSTEM:
251 case AID_AUDIO: {
252 return true;
253 } break;
keunyoung15882e52015-09-16 16:57:58 -0700254 default: {
255 ALOGE("non-system user tried access, uid %d", uid);
256 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700257 }
258 return false;
259}
260
261status_t BnVehicleNetwork::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
262 uint32_t flags) {
263 if (!isSystemUser()) {
264 return PERMISSION_DENIED;
265 }
266 status_t r;
267 switch (code) {
268 case LIST_PROPERTIES: {
269 CHECK_INTERFACE(IVehicleNetwork, data, reply);
270 int32_t property = data.readInt32();
271 sp<VehiclePropertiesHolder> holder = listProperties(property);
272 if (holder.get() == NULL) { // given property not found
keunyoung15882e52015-09-16 16:57:58 -0700273 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
274 return NO_ERROR;
keunyounge18e25d2015-08-28 15:57:19 -0700275 }
276 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
277 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
keunyoungd32f4e62015-09-21 11:33:06 -0700278 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
keunyounge18e25d2015-08-28 15:57:19 -0700279 int size = configs->ByteSize();
280 WritableBlobHolder blob(new Parcel::WritableBlob());
281 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
keunyoung15882e52015-09-16 16:57:58 -0700282 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700283 reply->writeInt32(size);
284 reply->writeBlob(size, false, blob.blob);
285 configs->SerializeToArray(blob.blob->data(), size);
286 return NO_ERROR;
287 } break;
288 case SET_PROPERTY: {
289 CHECK_INTERFACE(IVehicleNetwork, data, reply);
keunyounge18e25d2015-08-28 15:57:19 -0700290 ScopedVehiclePropValue value;
keunyoung7d74e6d2015-10-14 15:43:10 -0700291 r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
292 false /* deleteMembers */);
keunyounge18e25d2015-08-28 15:57:19 -0700293 if (r != NO_ERROR) {
keunyounge18e25d2015-08-28 15:57:19 -0700294 return r;
295 }
keunyounge18e25d2015-08-28 15:57:19 -0700296 r = setProperty(value.value);
keunyoung15882e52015-09-16 16:57:58 -0700297 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700298 return r;
299 } break;
300 case GET_PROPERTY: {
301 CHECK_INTERFACE(IVehicleNetwork, data, reply);
302 ScopedVehiclePropValue value;
keunyoung7d74e6d2015-10-14 15:43:10 -0700303 r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
304 false /* deleteMembers */, true /*canIgnoreNoData*/);
305 if (r != NO_ERROR) {
306 ALOGE("getProperty cannot read %d", r);
307 return r;
308 }
keunyounge18e25d2015-08-28 15:57:19 -0700309 r = getProperty(&(value.value));
310 if (r == NO_ERROR) {
keunyoung7d74e6d2015-10-14 15:43:10 -0700311 reply->writeNoException();
312 r = VehiclePropValueBinderUtil::writeToParcel(*reply, value.value);
keunyounge18e25d2015-08-28 15:57:19 -0700313 }
314 return r;
315 } break;
316 case SUBSCRIBE: {
317 CHECK_INTERFACE(IVehicleNetwork, data, reply);
318 sp<IVehicleNetworkListener> listener =
319 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
320 int32_t property = data.readInt32();
321 float sampleRate = data.readFloat();
322 r = subscribe(listener, property, sampleRate);
keunyoung15882e52015-09-16 16:57:58 -0700323 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700324 return r;
325 } break;
326 case UNSUBSCRIBE: {
327 CHECK_INTERFACE(IVehicleNetwork, data, reply);
328 sp<IVehicleNetworkListener> listener =
329 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
330 int32_t property = data.readInt32();
331 unsubscribe(listener, property);
keunyoung15882e52015-09-16 16:57:58 -0700332 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700333 return NO_ERROR;
334 } break;
keunyoung1ab8e182015-09-24 09:25:22 -0700335 case INJECT_EVENT: {
336 CHECK_INTERFACE(IVehicleNetwork, data, reply);
337 if (data.readInt32() == 0) { // java side allows passing null with this.
338 return BAD_VALUE;
339 }
340 ScopedVehiclePropValue value;
341 ReadableBlobHolder blob(new Parcel::ReadableBlob());
342 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
343 int32_t size = data.readInt32();
344 r = data.readBlob(size, blob.blob);
345 if (r != NO_ERROR) {
346 ALOGE("injectEvent:service, cannot read blob");
347 return r;
348 }
349 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
350 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
351 if (!v->ParseFromArray(blob.blob->data(), size)) {
352 ALOGE("injectEvent:service, cannot parse data");
353 return BAD_VALUE;
354 }
355 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
356 if (r != NO_ERROR) {
357 ALOGE("injectEvent:service, cannot convert data");
358 return BAD_VALUE;
359 }
360 r = injectEvent(value.value);
361 BinderUtil::fillNoResultReply(reply);
362 return r;
363 } break;
364 case START_MOCKING: {
365 CHECK_INTERFACE(IVehicleNetwork, data, reply);
366 sp<IVehicleNetworkHalMock> mock =
367 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
368 r = startMocking(mock);
369 BinderUtil::fillNoResultReply(reply);
370 return r;
371 } break;
372 case STOP_MOCKING: {
373 CHECK_INTERFACE(IVehicleNetwork, data, reply);
374 sp<IVehicleNetworkHalMock> mock =
375 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
376 stopMocking(mock);
377 BinderUtil::fillNoResultReply(reply);
378 return NO_ERROR;
379 } break;
Keun-young Park28dd4702015-11-19 18:06:04 -0800380 case INJECT_HAL_ERROR: {
381 CHECK_INTERFACE(IVehicleNetwork, data, reply);
382 int32_t errorCode = data.readInt32();
383 int32_t property = data.readInt32();
384 int32_t operation = data.readInt32();
385 r = injectHalError(errorCode, property, operation);
386 BinderUtil::fillNoResultReply(reply);
387 return r;
388 } break;
389 case START_ERROR_LISTENING: {
390 CHECK_INTERFACE(IVehicleNetwork, data, reply);
391 sp<IVehicleNetworkListener> listener =
392 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
393 r = startErrorListening(listener);
394 BinderUtil::fillNoResultReply(reply);
395 return r;
396 } break;
397 case STOP_ERROR_LISTENING: {
398 CHECK_INTERFACE(IVehicleNetwork, data, reply);
399 sp<IVehicleNetworkListener> listener =
400 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
401 stopErrorListening(listener);
402 BinderUtil::fillNoResultReply(reply);
403 return NO_ERROR;
404 } break;
405 case START_HAL_RESTART_MONITORING: {
406 CHECK_INTERFACE(IVehicleNetwork, data, reply);
407 sp<IVehicleNetworkListener> listener =
408 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
409 r = startHalRestartMonitoring(listener);
410 BinderUtil::fillNoResultReply(reply);
411 return r;
412 } break;
413 case STOP_HAL_RESTART_MONITORING: {
414 CHECK_INTERFACE(IVehicleNetwork, data, reply);
415 sp<IVehicleNetworkListener> listener =
416 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
417 stopHalRestartMonitoring(listener);
418 BinderUtil::fillNoResultReply(reply);
419 return NO_ERROR;
420 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700421 default:
422 return BBinder::onTransact(code, data, reply, flags);
423 }
424}
425
426}; // namespace android