blob: 8652f17f03bf78d6f3f815dd4101f53c1a1b7880 [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();
72 status = reply.readBlob(size, blob.blob);
73 if (status != NO_ERROR) {
74 ALOGE("listProperties, cannot read blob %d", status);
75 return holder;
76 }
77 //TODO make this more memory efficient
78 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
79 if (configs.get() == NULL) {
80 return holder;
81 }
82 if(!configs->ParseFromArray(blob.blob->data(), size)) {
83 ALOGE("listProperties, cannot parse reply");
84 return holder;
85 }
86 holder = new VehiclePropertiesHolder();
87 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
88 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
89 holder->getList());
90 if (status != NO_ERROR) {
91 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
92 return holder;
93 }
94
95 }
96 return holder;
97 }
98
99 virtual status_t onPropertySet(const vehicle_prop_value_t& value) {
100 Parcel data, reply;
101 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
102 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
103 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
104 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
105 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
106 int size = v->ByteSize();
107 WritableBlobHolder blob(new Parcel::WritableBlob());
108 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
109 data.writeInt32(size);
110 data.writeBlob(size, false, blob.blob);
111 v->SerializeToArray(blob.blob->data(), size);
112 status_t status = remote()->transact(ON_PROPERTY_SET, data, &reply);
113 return status;
114 }
115
116 virtual status_t onPropertyGet(vehicle_prop_value_t* value) {
117 Parcel data, reply;
118 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
119 // only needs to send property itself.
120 data.writeInt32(value->prop);
121 status_t status = remote()->transact(ON_PROPERTY_GET, data, &reply);
122 if (status == NO_ERROR) {
123 reply.readExceptionCode(); // for compatibility with java
124 if (reply.readInt32() == 0) { // no result
125 return BAD_VALUE;
126 }
127 ReadableBlobHolder blob(new Parcel::ReadableBlob());
128 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
129 int32_t size = reply.readInt32();
130 status = reply.readBlob(size, blob.blob);
131 if (status != NO_ERROR) {
132 ALOGE("getProperty, cannot read blob");
133 return status;
134 }
135 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
136 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
137 if (!v->ParseFromArray(blob.blob->data(), size)) {
138 ALOGE("getProperty, cannot parse reply");
139 return BAD_VALUE;
140 }
141 status = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), *value);
142 }
143 return status;
144 }
145
146 virtual status_t onPropertySubscribe(int32_t property, float sampleRate) {
147 Parcel data, reply;
148 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
149 data.writeInt32(property);
150 data.writeFloat(sampleRate);
151 status_t status = remote()->transact(ON_SUBSCRIBE, data, &reply);
152 return status;
153 }
154
155 virtual void onPropertyUnsubscribe(int32_t property) {
156 Parcel data, reply;
157 data.writeInterfaceToken(IVehicleNetworkHalMock::getInterfaceDescriptor());
158 data.writeInt32(property);
159 status_t status = remote()->transact(ON_UNSUBSCRIBE, data, &reply);
160 if (status != NO_ERROR) {
161 ALOGI("onPropertyUnsubscribe property %d failed %d", property, status);
162 }
163 }
164};
165
166IMPLEMENT_META_INTERFACE(VehicleNetworkHalMock, IVehicleNetworkHalMock::SERVICE_NAME);
167
168// ----------------------------------------------------------------------
169
170static bool isSystemUser() {
171 uid_t uid = IPCThreadState::self()->getCallingUid();
172 switch (uid) {
173 // This list will be expanded. Only those UIDs are allowed to access vehicle network
174 // for now. There can be per property based UID check built-in as well.
175 case AID_ROOT:
176 case AID_SYSTEM:
177 case AID_AUDIO: {
178 return true;
179 } break;
180 default: {
181 ALOGE("non-system user tried access, uid %d", uid);
182 } break;
183 }
184 return false;
185}
186
187status_t BnVehicleNetworkHalMock::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
188 uint32_t flags) {
189 if (!isSystemUser()) {
190 return PERMISSION_DENIED;
191 }
192 status_t r;
193 switch (code) {
194 case ON_LIST_PROPERTIES: {
195 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
196 sp<VehiclePropertiesHolder> holder = onListProperties();
197 if (holder.get() == NULL) { // given property not found
198 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
199 return NO_ERROR;
200 }
201 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
202 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
203 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
204 int size = configs->ByteSize();
205 WritableBlobHolder blob(new Parcel::WritableBlob());
206 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
207 BinderUtil::fillObjectResultReply(reply, true);
208 reply->writeInt32(size);
209 reply->writeBlob(size, false, blob.blob);
210 configs->SerializeToArray(blob.blob->data(), size);
211 return NO_ERROR;
212 } break;
213 case ON_PROPERTY_SET: {
214 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
215 if (data.readInt32() == 0) { // java side allows passing null with this.
216 return BAD_VALUE;
217 }
218 ScopedVehiclePropValue value;
219 ReadableBlobHolder blob(new Parcel::ReadableBlob());
220 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
221 int32_t size = data.readInt32();
222 r = data.readBlob(size, blob.blob);
223 if (r != NO_ERROR) {
224 ALOGE("setProperty:service, cannot read blob");
225 return r;
226 }
227 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
228 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
229 if (!v->ParseFromArray(blob.blob->data(), size)) {
230 ALOGE("setProperty:service, cannot parse data");
231 return BAD_VALUE;
232 }
233 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
234 if (r != NO_ERROR) {
235 ALOGE("setProperty:service, cannot convert data");
236 return BAD_VALUE;
237 }
238 r = onPropertySet(value.value);
239 BinderUtil::fillNoResultReply(reply);
240 return r;
241 } break;
242 case ON_PROPERTY_GET: {
243 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
244 ScopedVehiclePropValue value;
245 value.value.prop = data.readInt32();
246 r = onPropertyGet(&(value.value));
247 if (r == NO_ERROR) {
248 BinderUtil::fillObjectResultReply(reply, true);
249 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
250 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
251 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
252 int size = v->ByteSize();
253 WritableBlobHolder blob(new Parcel::WritableBlob());
254 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
255 reply->writeInt32(size);
256 reply->writeBlob(size, false, blob.blob);
257 v->SerializeToArray(blob.blob->data(), size);
258 }
259 return r;
260 } break;
261 case ON_SUBSCRIBE: {
262 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
263 int32_t property = data.readInt32();
264 float sampleRate = data.readFloat();
265 r = onPropertySubscribe(property, sampleRate);
266 BinderUtil::fillNoResultReply(reply);
267 return r;
268 } break;
269 case ON_UNSUBSCRIBE: {
270 CHECK_INTERFACE(IVehicleNetworkHalMock, data, reply);
271 int32_t property = data.readInt32();
272 onPropertyUnsubscribe(property);
273 BinderUtil::fillNoResultReply(reply);
274 return NO_ERROR;
275 } break;
276 default:
277 return BBinder::onTransact(code, data, reply, flags);
278 }
279}
280
281}; // namespace android