blob: 09da0eebd8f6a20ffdf68106874d90ca34406b8a [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>
Keun-young Park71b2f5c2016-03-10 18:44:40 -080020#include <string.h>
keunyounge18e25d2015-08-28 15:57:19 -070021
22#include <binder/IPCThreadState.h>
keunyounge18e25d2015-08-28 15:57:19 -070023
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,
Keun-young Park0727f952015-12-21 14:30:07 -0800137 float sampleRate, int32_t zones) {
keunyounge18e25d2015-08-28 15:57:19 -0700138 Parcel data, reply;
139 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
140 data.writeStrongBinder(IInterface::asBinder(listener));
141 data.writeInt32(property);
142 data.writeFloat(sampleRate);
Keun-young Park0727f952015-12-21 14:30:07 -0800143 data.writeInt32(zones);
keunyounge18e25d2015-08-28 15:57:19 -0700144 status_t status = remote()->transact(SUBSCRIBE, data, &reply);
145 return status;
146 }
147
148 virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property) {
149 Parcel data, reply;
150 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
151 data.writeStrongBinder(IInterface::asBinder(listener));
152 data.writeInt32(property);
153 status_t status = remote()->transact(UNSUBSCRIBE, data, &reply);
154 if (status != NO_ERROR) {
155 ALOGI("unsubscribing property %d failed %d", property, status);
156 }
157 }
keunyoung1ab8e182015-09-24 09:25:22 -0700158
159 virtual status_t injectEvent(const vehicle_prop_value_t& value) {
160 Parcel data, reply;
161 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
162 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
163 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
164 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
165 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
166 int size = v->ByteSize();
167 WritableBlobHolder blob(new Parcel::WritableBlob());
168 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
169 data.writeInt32(size);
170 data.writeBlob(size, false, blob.blob);
171 v->SerializeToArray(blob.blob->data(), size);
172 status_t status = remote()->transact(INJECT_EVENT, data, &reply);
173 return status;
174 }
175
176 virtual status_t startMocking(const sp<IVehicleNetworkHalMock>& mock) {
177 Parcel data, reply;
178 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
179 data.writeStrongBinder(IInterface::asBinder(mock));
180 status_t status = remote()->transact(START_MOCKING, data, &reply);
181 return status;
182 }
183
184 virtual void stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
185 Parcel data, reply;
186 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
187 data.writeStrongBinder(IInterface::asBinder(mock));
188 status_t status = remote()->transact(STOP_MOCKING, data, &reply);
189 if (status != NO_ERROR) {
190 ALOGI("stop mocking failed %d", status);
191 }
192 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800193
194 status_t injectHalError(int32_t errorCode, int32_t property, int32_t operation) {
195 Parcel data, reply;
196 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
197 data.writeInt32(errorCode);
198 data.writeInt32(property);
199 data.writeInt32(operation);
200 status_t status = remote()->transact(INJECT_HAL_ERROR, data, &reply);
201 return status;
202 }
203
204 virtual status_t startErrorListening(const sp<IVehicleNetworkListener> &listener) {
205 Parcel data, reply;
206 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
207 data.writeStrongBinder(IInterface::asBinder(listener));
208 status_t status = remote()->transact(START_ERROR_LISTENING, data, &reply);
209 return status;
210 }
211
212 virtual void stopErrorListening(const sp<IVehicleNetworkListener> &listener) {
213 Parcel data, reply;
214 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
215 data.writeStrongBinder(IInterface::asBinder(listener));
216 status_t status = remote()->transact(STOP_ERROR_LISTENING, data, &reply);
217 if (status != NO_ERROR) {
218 ALOGI("stopErrorListening %d", status);
219 }
220 }
221
222 virtual status_t startHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
223 Parcel data, reply;
224 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
225 data.writeStrongBinder(IInterface::asBinder(listener));
226 status_t status = remote()->transact(START_HAL_RESTART_MONITORING, data, &reply);
227 return status;
228 }
229
230 virtual void stopHalRestartMonitoring(const sp<IVehicleNetworkListener> &listener) {
231 Parcel data, reply;
232 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
233 data.writeStrongBinder(IInterface::asBinder(listener));
234 status_t status = remote()->transact(STOP_HAL_RESTART_MONITORING, data, &reply);
235 if (status != NO_ERROR) {
236 ALOGI("stopHalRestartMonitoring %d", status);
237 }
238 }
keunyounge18e25d2015-08-28 15:57:19 -0700239};
240
241IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);
242
243// ----------------------------------------------------------------------
244
keunyounge18e25d2015-08-28 15:57:19 -0700245status_t BnVehicleNetwork::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
246 uint32_t flags) {
keunyounge18e25d2015-08-28 15:57:19 -0700247 status_t r;
248 switch (code) {
249 case LIST_PROPERTIES: {
250 CHECK_INTERFACE(IVehicleNetwork, data, reply);
Keun-young Park737cdfb2016-02-12 15:11:39 -0800251 if (!isOperationAllowed(0, false)) {
252 return PERMISSION_DENIED;
253 }
keunyounge18e25d2015-08-28 15:57:19 -0700254 int32_t property = data.readInt32();
255 sp<VehiclePropertiesHolder> holder = listProperties(property);
256 if (holder.get() == NULL) { // given property not found
keunyoung15882e52015-09-16 16:57:58 -0700257 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
258 return NO_ERROR;
keunyounge18e25d2015-08-28 15:57:19 -0700259 }
260 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
261 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
keunyoungd32f4e62015-09-21 11:33:06 -0700262 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
keunyounge18e25d2015-08-28 15:57:19 -0700263 int size = configs->ByteSize();
264 WritableBlobHolder blob(new Parcel::WritableBlob());
265 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
keunyoung15882e52015-09-16 16:57:58 -0700266 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700267 reply->writeInt32(size);
268 reply->writeBlob(size, false, blob.blob);
269 configs->SerializeToArray(blob.blob->data(), size);
270 return NO_ERROR;
271 } break;
272 case SET_PROPERTY: {
273 CHECK_INTERFACE(IVehicleNetwork, data, reply);
keunyounge18e25d2015-08-28 15:57:19 -0700274 ScopedVehiclePropValue value;
keunyoung7d74e6d2015-10-14 15:43:10 -0700275 r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
276 false /* deleteMembers */);
keunyounge18e25d2015-08-28 15:57:19 -0700277 if (r != NO_ERROR) {
keunyounge18e25d2015-08-28 15:57:19 -0700278 return r;
279 }
Keun-young Park737cdfb2016-02-12 15:11:39 -0800280 if (!isOperationAllowed(value.value.prop, true)) {
281 return PERMISSION_DENIED;
282 }
keunyounge18e25d2015-08-28 15:57:19 -0700283 r = setProperty(value.value);
keunyoung15882e52015-09-16 16:57:58 -0700284 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700285 return r;
286 } break;
287 case GET_PROPERTY: {
288 CHECK_INTERFACE(IVehicleNetwork, data, reply);
Keun-young Park71b2f5c2016-03-10 18:44:40 -0800289 vehicle_prop_value_t value;
290 memset(&value, 0, sizeof(value));
291 r = VehiclePropValueBinderUtil::readFromParcel(data, &value,
keunyoung7d74e6d2015-10-14 15:43:10 -0700292 false /* deleteMembers */, true /*canIgnoreNoData*/);
293 if (r != NO_ERROR) {
294 ALOGE("getProperty cannot read %d", r);
295 return r;
296 }
Keun-young Park71b2f5c2016-03-10 18:44:40 -0800297 if (!isOperationAllowed(value.prop, false)) {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800298 return PERMISSION_DENIED;
299 }
Keun-young Park71b2f5c2016-03-10 18:44:40 -0800300 r = getProperty(&value);
keunyounge18e25d2015-08-28 15:57:19 -0700301 if (r == NO_ERROR) {
keunyoung7d74e6d2015-10-14 15:43:10 -0700302 reply->writeNoException();
Keun-young Park71b2f5c2016-03-10 18:44:40 -0800303 r = VehiclePropValueBinderUtil::writeToParcel(*reply, value);
304 releaseMemoryFromGet(&value);
keunyounge18e25d2015-08-28 15:57:19 -0700305 }
306 return r;
307 } break;
308 case SUBSCRIBE: {
309 CHECK_INTERFACE(IVehicleNetwork, data, reply);
310 sp<IVehicleNetworkListener> listener =
311 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
312 int32_t property = data.readInt32();
Keun-young Park737cdfb2016-02-12 15:11:39 -0800313 if (!isOperationAllowed(property, false)) {
314 return PERMISSION_DENIED;
315 }
keunyounge18e25d2015-08-28 15:57:19 -0700316 float sampleRate = data.readFloat();
Keun-young Park0727f952015-12-21 14:30:07 -0800317 int32_t zones = data.readInt32();
318 r = subscribe(listener, property, sampleRate, zones);
keunyoung15882e52015-09-16 16:57:58 -0700319 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700320 return r;
321 } break;
322 case UNSUBSCRIBE: {
323 CHECK_INTERFACE(IVehicleNetwork, data, reply);
324 sp<IVehicleNetworkListener> listener =
325 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
326 int32_t property = data.readInt32();
Keun-young Park737cdfb2016-02-12 15:11:39 -0800327 if (!isOperationAllowed(property, false)) {
328 return PERMISSION_DENIED;
329 }
keunyounge18e25d2015-08-28 15:57:19 -0700330 unsubscribe(listener, property);
keunyoung15882e52015-09-16 16:57:58 -0700331 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700332 return NO_ERROR;
333 } break;
keunyoung1ab8e182015-09-24 09:25:22 -0700334 case INJECT_EVENT: {
335 CHECK_INTERFACE(IVehicleNetwork, data, reply);
336 if (data.readInt32() == 0) { // java side allows passing null with this.
337 return BAD_VALUE;
338 }
Keun-young Park737cdfb2016-02-12 15:11:39 -0800339 if (!isOperationAllowed(0, true)) {
340 return PERMISSION_DENIED;
341 }
keunyoung1ab8e182015-09-24 09:25:22 -0700342 ScopedVehiclePropValue value;
343 ReadableBlobHolder blob(new Parcel::ReadableBlob());
344 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
345 int32_t size = data.readInt32();
346 r = data.readBlob(size, blob.blob);
347 if (r != NO_ERROR) {
348 ALOGE("injectEvent:service, cannot read blob");
349 return r;
350 }
351 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
352 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
353 if (!v->ParseFromArray(blob.blob->data(), size)) {
354 ALOGE("injectEvent:service, cannot parse data");
355 return BAD_VALUE;
356 }
357 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
358 if (r != NO_ERROR) {
359 ALOGE("injectEvent:service, cannot convert data");
360 return BAD_VALUE;
361 }
362 r = injectEvent(value.value);
363 BinderUtil::fillNoResultReply(reply);
364 return r;
365 } break;
366 case START_MOCKING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800367 if (!isOperationAllowed(0, true)) {
368 return PERMISSION_DENIED;
369 }
keunyoung1ab8e182015-09-24 09:25:22 -0700370 CHECK_INTERFACE(IVehicleNetwork, data, reply);
371 sp<IVehicleNetworkHalMock> mock =
372 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
373 r = startMocking(mock);
374 BinderUtil::fillNoResultReply(reply);
375 return r;
376 } break;
377 case STOP_MOCKING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800378 if (!isOperationAllowed(0, true)) {
379 return PERMISSION_DENIED;
380 }
keunyoung1ab8e182015-09-24 09:25:22 -0700381 CHECK_INTERFACE(IVehicleNetwork, data, reply);
382 sp<IVehicleNetworkHalMock> mock =
383 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
384 stopMocking(mock);
385 BinderUtil::fillNoResultReply(reply);
386 return NO_ERROR;
387 } break;
Keun-young Park28dd4702015-11-19 18:06:04 -0800388 case INJECT_HAL_ERROR: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800389 if (!isOperationAllowed(0, true)) {
390 return PERMISSION_DENIED;
391 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800392 CHECK_INTERFACE(IVehicleNetwork, data, reply);
393 int32_t errorCode = data.readInt32();
394 int32_t property = data.readInt32();
395 int32_t operation = data.readInt32();
396 r = injectHalError(errorCode, property, operation);
397 BinderUtil::fillNoResultReply(reply);
398 return r;
399 } break;
400 case START_ERROR_LISTENING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800401 if (!isOperationAllowed(0, false)) {
402 return PERMISSION_DENIED;
403 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800404 CHECK_INTERFACE(IVehicleNetwork, data, reply);
405 sp<IVehicleNetworkListener> listener =
406 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
407 r = startErrorListening(listener);
408 BinderUtil::fillNoResultReply(reply);
409 return r;
410 } break;
411 case STOP_ERROR_LISTENING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800412 if (!isOperationAllowed(0, false)) {
413 return PERMISSION_DENIED;
414 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800415 CHECK_INTERFACE(IVehicleNetwork, data, reply);
416 sp<IVehicleNetworkListener> listener =
417 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
418 stopErrorListening(listener);
419 BinderUtil::fillNoResultReply(reply);
420 return NO_ERROR;
421 } break;
422 case START_HAL_RESTART_MONITORING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800423 if (!isOperationAllowed(0, false)) {
424 return PERMISSION_DENIED;
425 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800426 CHECK_INTERFACE(IVehicleNetwork, data, reply);
427 sp<IVehicleNetworkListener> listener =
428 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
429 r = startHalRestartMonitoring(listener);
430 BinderUtil::fillNoResultReply(reply);
431 return r;
432 } break;
433 case STOP_HAL_RESTART_MONITORING: {
Keun-young Park737cdfb2016-02-12 15:11:39 -0800434 if (!isOperationAllowed(0, false)) {
435 return PERMISSION_DENIED;
436 }
Keun-young Park28dd4702015-11-19 18:06:04 -0800437 CHECK_INTERFACE(IVehicleNetwork, data, reply);
438 sp<IVehicleNetworkListener> listener =
439 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
440 stopHalRestartMonitoring(listener);
441 BinderUtil::fillNoResultReply(reply);
442 return NO_ERROR;
443 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700444 default:
445 return BBinder::onTransact(code, data, reply, flags);
446 }
447}
448
449}; // namespace android