blob: 388715d5e401d25e0c7ea4fb2fef3e80bdda087c [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,
keunyounge18e25d2015-08-28 15:57:19 -070043};
44
45// ----------------------------------------------------------------------------
46
keunyoung15882e52015-09-16 16:57:58 -070047const char IVehicleNetwork::SERVICE_NAME[] = "com.android.car.vehiclenetwork.IVehicleNetwork";
keunyounge18e25d2015-08-28 15:57:19 -070048
49// ----------------------------------------------------------------------------
50
51class BpVehicleNetwork : public BpInterface<IVehicleNetwork> {
52public:
53 BpVehicleNetwork(const sp<IBinder> & impl)
54 : BpInterface<IVehicleNetwork>(impl) {
55 }
56
57 virtual sp<VehiclePropertiesHolder> listProperties(int32_t property) {
58 sp<VehiclePropertiesHolder> holder;
59 Parcel data, reply;
60 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
61 data.writeInt32(property);
62 status_t status = remote()->transact(LIST_PROPERTIES, data, &reply);
63 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -070064 reply.readExceptionCode(); // for compatibility with java
keunyounge18e25d2015-08-28 15:57:19 -070065 if (reply.readInt32() == 0) { // no result
66 return holder;
67 }
68 ReadableBlobHolder blob(new Parcel::ReadableBlob());
69 if (blob.blob == NULL) {
70 ALOGE("listProperties, no memory");
71 return holder;
72 }
73 int32_t size = reply.readInt32();
74 status = reply.readBlob(size, blob.blob);
75 if (status != NO_ERROR) {
76 ALOGE("listProperties, cannot read blob %d", status);
77 return holder;
78 }
79 //TODO make this more memory efficient
80 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
81 if (configs.get() == NULL) {
82 return holder;
83 }
84 if(!configs->ParseFromArray(blob.blob->data(), size)) {
85 ALOGE("listProperties, cannot parse reply");
86 return holder;
87 }
keunyoungd32f4e62015-09-21 11:33:06 -070088 holder = new VehiclePropertiesHolder();
89 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
90 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
91 holder->getList());
keunyounge18e25d2015-08-28 15:57:19 -070092 if (status != NO_ERROR) {
93 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
94 return holder;
95 }
keunyoungd32f4e62015-09-21 11:33:06 -070096
keunyounge18e25d2015-08-28 15:57:19 -070097 }
98 return holder;
99 }
100
101 virtual status_t setProperty(const vehicle_prop_value_t& value) {
102 Parcel data, reply;
103 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
104 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
105 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
106 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
107 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
108 int size = v->ByteSize();
109 WritableBlobHolder blob(new Parcel::WritableBlob());
110 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
111 data.writeInt32(size);
112 data.writeBlob(size, false, blob.blob);
113 v->SerializeToArray(blob.blob->data(), size);
114 status_t status = remote()->transact(SET_PROPERTY, data, &reply);
115 return status;
116 }
117
118 virtual status_t getProperty(vehicle_prop_value_t* value) {
119 Parcel data, reply;
120 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
121 // only needs to send property itself.
122 data.writeInt32(value->prop);
123 status_t status = remote()->transact(GET_PROPERTY, data, &reply);
124 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700125 reply.readExceptionCode(); // for compatibility with java
keunyounge18e25d2015-08-28 15:57:19 -0700126 if (reply.readInt32() == 0) { // no result
127 return BAD_VALUE;
128 }
129 ReadableBlobHolder blob(new Parcel::ReadableBlob());
130 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
131 int32_t size = reply.readInt32();
132 status = reply.readBlob(size, blob.blob);
133 if (status != NO_ERROR) {
134 ALOGE("getProperty, cannot read blob");
135 return status;
136 }
137 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
138 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
139 if (!v->ParseFromArray(blob.blob->data(), size)) {
140 ALOGE("getProperty, cannot parse reply");
141 return BAD_VALUE;
142 }
143 status = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), *value);
144 }
145 return status;
146 }
147
148 virtual status_t subscribe(const sp<IVehicleNetworkListener> &listener, int32_t property,
149 float sampleRate) {
150 Parcel data, reply;
151 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
152 data.writeStrongBinder(IInterface::asBinder(listener));
153 data.writeInt32(property);
154 data.writeFloat(sampleRate);
155 status_t status = remote()->transact(SUBSCRIBE, data, &reply);
156 return status;
157 }
158
159 virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property) {
160 Parcel data, reply;
161 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
162 data.writeStrongBinder(IInterface::asBinder(listener));
163 data.writeInt32(property);
164 status_t status = remote()->transact(UNSUBSCRIBE, data, &reply);
165 if (status != NO_ERROR) {
166 ALOGI("unsubscribing property %d failed %d", property, status);
167 }
168 }
keunyoung1ab8e182015-09-24 09:25:22 -0700169
170 virtual status_t injectEvent(const vehicle_prop_value_t& value) {
171 Parcel data, reply;
172 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
173 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
174 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
175 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
176 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
177 int size = v->ByteSize();
178 WritableBlobHolder blob(new Parcel::WritableBlob());
179 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
180 data.writeInt32(size);
181 data.writeBlob(size, false, blob.blob);
182 v->SerializeToArray(blob.blob->data(), size);
183 status_t status = remote()->transact(INJECT_EVENT, data, &reply);
184 return status;
185 }
186
187 virtual status_t startMocking(const sp<IVehicleNetworkHalMock>& mock) {
188 Parcel data, reply;
189 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
190 data.writeStrongBinder(IInterface::asBinder(mock));
191 status_t status = remote()->transact(START_MOCKING, data, &reply);
192 return status;
193 }
194
195 virtual void stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
196 Parcel data, reply;
197 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
198 data.writeStrongBinder(IInterface::asBinder(mock));
199 status_t status = remote()->transact(STOP_MOCKING, data, &reply);
200 if (status != NO_ERROR) {
201 ALOGI("stop mocking failed %d", status);
202 }
203 }
keunyounge18e25d2015-08-28 15:57:19 -0700204};
205
206IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);
207
208// ----------------------------------------------------------------------
209
210static bool isSystemUser() {
211 uid_t uid = IPCThreadState::self()->getCallingUid();
212 switch (uid) {
213 // This list will be expanded. Only those UIDs are allowed to access vehicle network
214 // for now. There can be per property based UID check built-in as well.
215 case AID_ROOT:
216 case AID_SYSTEM:
217 case AID_AUDIO: {
218 return true;
219 } break;
keunyoung15882e52015-09-16 16:57:58 -0700220 default: {
221 ALOGE("non-system user tried access, uid %d", uid);
222 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700223 }
224 return false;
225}
226
227status_t BnVehicleNetwork::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
228 uint32_t flags) {
229 if (!isSystemUser()) {
230 return PERMISSION_DENIED;
231 }
232 status_t r;
233 switch (code) {
234 case LIST_PROPERTIES: {
235 CHECK_INTERFACE(IVehicleNetwork, data, reply);
236 int32_t property = data.readInt32();
237 sp<VehiclePropertiesHolder> holder = listProperties(property);
238 if (holder.get() == NULL) { // given property not found
keunyoung15882e52015-09-16 16:57:58 -0700239 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
240 return NO_ERROR;
keunyounge18e25d2015-08-28 15:57:19 -0700241 }
242 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
243 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
keunyoungd32f4e62015-09-21 11:33:06 -0700244 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
keunyounge18e25d2015-08-28 15:57:19 -0700245 int size = configs->ByteSize();
246 WritableBlobHolder blob(new Parcel::WritableBlob());
247 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
keunyoung15882e52015-09-16 16:57:58 -0700248 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700249 reply->writeInt32(size);
250 reply->writeBlob(size, false, blob.blob);
251 configs->SerializeToArray(blob.blob->data(), size);
252 return NO_ERROR;
253 } break;
254 case SET_PROPERTY: {
255 CHECK_INTERFACE(IVehicleNetwork, data, reply);
256 if (data.readInt32() == 0) { // java side allows passing null with this.
257 return BAD_VALUE;
258 }
259 ScopedVehiclePropValue value;
260 ReadableBlobHolder blob(new Parcel::ReadableBlob());
261 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
262 int32_t size = data.readInt32();
263 r = data.readBlob(size, blob.blob);
264 if (r != NO_ERROR) {
265 ALOGE("setProperty:service, cannot read blob");
266 return r;
267 }
268 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
269 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
270 if (!v->ParseFromArray(blob.blob->data(), size)) {
271 ALOGE("setProperty:service, cannot parse data");
272 return BAD_VALUE;
273 }
274 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
275 if (r != NO_ERROR) {
276 ALOGE("setProperty:service, cannot convert data");
277 return BAD_VALUE;
278 }
279 r = setProperty(value.value);
keunyoung15882e52015-09-16 16:57:58 -0700280 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700281 return r;
282 } break;
283 case GET_PROPERTY: {
284 CHECK_INTERFACE(IVehicleNetwork, data, reply);
285 ScopedVehiclePropValue value;
286 value.value.prop = data.readInt32();
287 r = getProperty(&(value.value));
288 if (r == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700289 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700290 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
291 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
292 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
293 int size = v->ByteSize();
294 WritableBlobHolder blob(new Parcel::WritableBlob());
295 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
296 reply->writeInt32(size);
297 reply->writeBlob(size, false, blob.blob);
298 v->SerializeToArray(blob.blob->data(), size);
299 }
300 return r;
301 } break;
302 case SUBSCRIBE: {
303 CHECK_INTERFACE(IVehicleNetwork, data, reply);
304 sp<IVehicleNetworkListener> listener =
305 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
306 int32_t property = data.readInt32();
307 float sampleRate = data.readFloat();
308 r = subscribe(listener, property, sampleRate);
keunyoung15882e52015-09-16 16:57:58 -0700309 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700310 return r;
311 } break;
312 case UNSUBSCRIBE: {
313 CHECK_INTERFACE(IVehicleNetwork, data, reply);
314 sp<IVehicleNetworkListener> listener =
315 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
316 int32_t property = data.readInt32();
317 unsubscribe(listener, property);
keunyoung15882e52015-09-16 16:57:58 -0700318 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700319 return NO_ERROR;
320 } break;
keunyoung1ab8e182015-09-24 09:25:22 -0700321 case INJECT_EVENT: {
322 CHECK_INTERFACE(IVehicleNetwork, data, reply);
323 if (data.readInt32() == 0) { // java side allows passing null with this.
324 return BAD_VALUE;
325 }
326 ScopedVehiclePropValue value;
327 ReadableBlobHolder blob(new Parcel::ReadableBlob());
328 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
329 int32_t size = data.readInt32();
330 r = data.readBlob(size, blob.blob);
331 if (r != NO_ERROR) {
332 ALOGE("injectEvent:service, cannot read blob");
333 return r;
334 }
335 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
336 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
337 if (!v->ParseFromArray(blob.blob->data(), size)) {
338 ALOGE("injectEvent:service, cannot parse data");
339 return BAD_VALUE;
340 }
341 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
342 if (r != NO_ERROR) {
343 ALOGE("injectEvent:service, cannot convert data");
344 return BAD_VALUE;
345 }
346 r = injectEvent(value.value);
347 BinderUtil::fillNoResultReply(reply);
348 return r;
349 } break;
350 case START_MOCKING: {
351 CHECK_INTERFACE(IVehicleNetwork, data, reply);
352 sp<IVehicleNetworkHalMock> mock =
353 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
354 r = startMocking(mock);
355 BinderUtil::fillNoResultReply(reply);
356 return r;
357 } break;
358 case STOP_MOCKING: {
359 CHECK_INTERFACE(IVehicleNetwork, data, reply);
360 sp<IVehicleNetworkHalMock> mock =
361 interface_cast<IVehicleNetworkHalMock>(data.readStrongBinder());
362 stopMocking(mock);
363 BinderUtil::fillNoResultReply(reply);
364 return NO_ERROR;
365 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700366 default:
367 return BBinder::onTransact(code, data, reply, flags);
368 }
369}
370
371}; // namespace android