blob: 91e00b23e7b74abcfedc1fad7858d730589c8d56 [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 }
81 //TODO make this more memory efficient
82 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
83 if (configs.get() == NULL) {
84 return holder;
85 }
86 if(!configs->ParseFromArray(blob.blob->data(), size)) {
87 ALOGE("listProperties, cannot parse reply");
88 return holder;
89 }
90 holder = new VehiclePropertiesHolder();
91 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
92 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
93 holder->getList());
94 if (status != NO_ERROR) {
95 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
96 return holder;
97 }
98
99 }
100 return holder;
101 }
102
103 virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
104 Parcel data, reply;
105 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700106 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, value);
107 if (status != NO_ERROR) {
108 return status;
109 }
110 status = remote()->transact(ON_PROPERTY_SET, data, &reply);
keunyoung1ab8e182015-09-24 09:25:22 -0700111 return status;
112 }
113
114 virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
keunyoung7d74e6d2015-10-14 15:43:10 -0700115 if (value == NULL) {
116 return BAD_VALUE;
117 }
keunyoung1ab8e182015-09-24 09:25:22 -0700118 Parcel data, reply;
119 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
keunyoung7d74e6d2015-10-14 15:43:10 -0700120 status_t status = VehiclePropValueBinderUtil::writeToParcel(data, *value);
121 if (status != NO_ERROR) {
122 return status;
123 }
124 status = remote()->transact(ON_PROPERTY_GET, data, &reply);
keunyoung1ab8e182015-09-24 09:25:22 -0700125 if (status == NO_ERROR) {
126 reply.readExceptionCode(); // for compatibility with java
keunyoung7d74e6d2015-10-14 15:43:10 -0700127 status = VehiclePropValueBinderUtil::readFromParcel(reply, value);
keunyoung1ab8e182015-09-24 09:25:22 -0700128 }
129 return status;
130 }
131
Keun-young Park0727f952015-12-21 14:30:07 -0800132 virtual status_t onPropertySubscribe(int32_t property, float sampleRate, int32_t zones) {
keunyoung1ab8e182015-09-24 09:25:22 -0700133 Parcel data, reply;
134 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
135 data.writeInt32(property);
136 data.writeFloat(sampleRate);
Keun-young Park0727f952015-12-21 14:30:07 -0800137 data.writeInt32(zones);
keunyoung1ab8e182015-09-24 09:25:22 -0700138 status_t status = remote()->transact(ON_SUBSCRIBE, data, &reply);
139 return status;
140 }
141
142 virtual void onPropertyUnsubscribe(int32_t property) {
143 Parcel data, reply;
144 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
145 data.writeInt32(property);
146 status_t status = remote()->transact(ON_UNSUBSCRIBE, data, &reply);
147 if (status != NO_ERROR) {
148 ALOGI("onPropertyUnsubscribe property %d failed %d", property, status);
149 }
150 }
151};
152
153IMPLEMENT_META_INTERFACE(VehicleNetworkHalMock, IVehicleNetworkHalMock::SERVICE_NAME);
154
155// ----------------------------------------------------------------------
156
157static bool isSystemUser() {
158 uid_t uid = IPCThreadState::self()->getCallingUid();
159 switch (uid) {
160 // This list will be expanded. Only those UIDs are allowed to access vehicle network
161 // for now. There can be per property based UID check built-in as well.
162 case AID_ROOT:
163 case AID_SYSTEM:
164 case AID_AUDIO: {
165 return true;
166 } break;
167 default: {
168 ALOGE("non-system user tried access, uid %d", uid);
169 } break;
170 }
171 return false;
172}
173
174status_t BnVehicleNetworkHalMock::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
175 uint32_t flags) {
176 if (!isSystemUser()) {
177 return PERMISSION_DENIED;
178 }
179 status_t r;
180 switch (code) {
181 case ON_LIST_PROPERTIES: {
182 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
183 sp<VehiclePropertiesHolder> holder = onListProperties();
184 if (holder.get() == NULL) { // given property not found
185 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
186 return NO_ERROR;
187 }
188 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
189 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
190 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
191 int size = configs->ByteSize();
192 WritableBlobHolder blob(new Parcel::WritableBlob());
193 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
194 BinderUtil::fillObjectResultReply(reply, true);
195 reply->writeInt32(size);
196 reply->writeBlob(size, false, blob.blob);
197 configs->SerializeToArray(blob.blob->data(), size);
198 return NO_ERROR;
199 } break;
200 case ON_PROPERTY_SET: {
201 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
202 if (data.readInt32() == 0) { // java side allows passing null with this.
203 return BAD_VALUE;
204 }
205 ScopedVehiclePropValue value;
206 ReadableBlobHolder blob(new Parcel::ReadableBlob());
207 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
208 int32_t size = data.readInt32();
Keun-young Park20539ba2016-10-10 17:57:34 -0700209 if (size < 0) {
210 ALOGE("setProperty:service, bad blob size %d", size);
211 return BAD_VALUE;
212 }
keunyoung1ab8e182015-09-24 09:25:22 -0700213 r = data.readBlob(size, blob.blob);
214 if (r != NO_ERROR) {
215 ALOGE("setProperty:service, cannot read blob");
216 return r;
217 }
218 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
219 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
220 if (!v->ParseFromArray(blob.blob->data(), size)) {
221 ALOGE("setProperty:service, cannot parse data");
222 return BAD_VALUE;
223 }
224 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
225 if (r != NO_ERROR) {
226 ALOGE("setProperty:service, cannot convert data");
227 return BAD_VALUE;
228 }
229 r = onPropertySet(value.value);
230 BinderUtil::fillNoResultReply(reply);
231 return r;
232 } break;
233 case ON_PROPERTY_GET: {
234 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
235 ScopedVehiclePropValue value;
Keun-young Parkaaeffaf2015-11-25 17:24:10 -0800236 r = VehiclePropValueBinderUtil::readFromParcel(data, &value.value,
237 false /* deleteMembers */, true /*canIgnoreNoData*/);
238 if (r != NO_ERROR) {
239 ALOGE("onPropertyGet cannot read %d", r);
240 return r;
241 }
keunyoung1ab8e182015-09-24 09:25:22 -0700242 r = onPropertyGet(&(value.value));
243 if (r == NO_ERROR) {
244 BinderUtil::fillObjectResultReply(reply, true);
245 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
246 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
247 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
248 int size = v->ByteSize();
249 WritableBlobHolder blob(new Parcel::WritableBlob());
250 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
251 reply->writeInt32(size);
252 reply->writeBlob(size, false, blob.blob);
253 v->SerializeToArray(blob.blob->data(), size);
254 }
255 return r;
256 } break;
257 case ON_SUBSCRIBE: {
258 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
259 int32_t property = data.readInt32();
260 float sampleRate = data.readFloat();
Keun-young Park0727f952015-12-21 14:30:07 -0800261 int32_t zones = data.readInt32();
262 r = onPropertySubscribe(property, sampleRate, zones);
keunyoung1ab8e182015-09-24 09:25:22 -0700263 BinderUtil::fillNoResultReply(reply);
264 return r;
265 } break;
266 case ON_UNSUBSCRIBE: {
267 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
268 int32_t property = data.readInt32();
269 onPropertyUnsubscribe(property);
270 BinderUtil::fillNoResultReply(reply);
271 return NO_ERROR;
272 } break;
273 default:
274 return BBinder::onTransact(code, data, reply, flags);
275 }
276}
277
278}; // namespace android