blob: 6af722b6c27a804ba6e9787b336f9a4c174bd133 [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,
40};
41
42// ----------------------------------------------------------------------------
43
keunyoung15882e52015-09-16 16:57:58 -070044const char IVehicleNetwork::SERVICE_NAME[] = "com.android.car.vehiclenetwork.IVehicleNetwork";
keunyounge18e25d2015-08-28 15:57:19 -070045
46// ----------------------------------------------------------------------------
47
48class BpVehicleNetwork : public BpInterface<IVehicleNetwork> {
49public:
50 BpVehicleNetwork(const sp<IBinder> & impl)
51 : BpInterface<IVehicleNetwork>(impl) {
52 }
53
54 virtual sp<VehiclePropertiesHolder> listProperties(int32_t property) {
55 sp<VehiclePropertiesHolder> holder;
56 Parcel data, reply;
57 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
58 data.writeInt32(property);
59 status_t status = remote()->transact(LIST_PROPERTIES, data, &reply);
60 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -070061 reply.readExceptionCode(); // for compatibility with java
keunyounge18e25d2015-08-28 15:57:19 -070062 if (reply.readInt32() == 0) { // no result
63 return holder;
64 }
65 ReadableBlobHolder blob(new Parcel::ReadableBlob());
66 if (blob.blob == NULL) {
67 ALOGE("listProperties, no memory");
68 return holder;
69 }
70 int32_t size = reply.readInt32();
71 status = reply.readBlob(size, blob.blob);
72 if (status != NO_ERROR) {
73 ALOGE("listProperties, cannot read blob %d", status);
74 return holder;
75 }
76 //TODO make this more memory efficient
77 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
78 if (configs.get() == NULL) {
79 return holder;
80 }
81 if(!configs->ParseFromArray(blob.blob->data(), size)) {
82 ALOGE("listProperties, cannot parse reply");
83 return holder;
84 }
85 vehicle_prop_config_t* configArray = NULL;
86 int32_t numConfigs;
87 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(), &configArray,
88 &numConfigs);
89 if (status != NO_ERROR) {
90 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
91 return holder;
92 }
93 holder = new VehiclePropertiesHolder(configArray, numConfigs);
94 }
95 return holder;
96 }
97
98 virtual status_t setProperty(const vehicle_prop_value_t& value) {
99 Parcel data, reply;
100 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
101 data.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
102 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
103 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
104 VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
105 int size = v->ByteSize();
106 WritableBlobHolder blob(new Parcel::WritableBlob());
107 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
108 data.writeInt32(size);
109 data.writeBlob(size, false, blob.blob);
110 v->SerializeToArray(blob.blob->data(), size);
111 status_t status = remote()->transact(SET_PROPERTY, data, &reply);
112 return status;
113 }
114
115 virtual status_t getProperty(vehicle_prop_value_t* value) {
116 Parcel data, reply;
117 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
118 // only needs to send property itself.
119 data.writeInt32(value->prop);
120 status_t status = remote()->transact(GET_PROPERTY, data, &reply);
121 if (status == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700122 reply.readExceptionCode(); // for compatibility with java
keunyounge18e25d2015-08-28 15:57:19 -0700123 if (reply.readInt32() == 0) { // no result
124 return BAD_VALUE;
125 }
126 ReadableBlobHolder blob(new Parcel::ReadableBlob());
127 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
128 int32_t size = reply.readInt32();
129 status = reply.readBlob(size, blob.blob);
130 if (status != NO_ERROR) {
131 ALOGE("getProperty, cannot read blob");
132 return status;
133 }
134 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
135 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
136 if (!v->ParseFromArray(blob.blob->data(), size)) {
137 ALOGE("getProperty, cannot parse reply");
138 return BAD_VALUE;
139 }
140 status = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), *value);
141 }
142 return status;
143 }
144
145 virtual status_t subscribe(const sp<IVehicleNetworkListener> &listener, int32_t property,
146 float sampleRate) {
147 Parcel data, reply;
148 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
149 data.writeStrongBinder(IInterface::asBinder(listener));
150 data.writeInt32(property);
151 data.writeFloat(sampleRate);
152 status_t status = remote()->transact(SUBSCRIBE, data, &reply);
153 return status;
154 }
155
156 virtual void unsubscribe(const sp<IVehicleNetworkListener> &listener, int32_t property) {
157 Parcel data, reply;
158 data.writeInterfaceToken(IVehicleNetwork::getInterfaceDescriptor());
159 data.writeStrongBinder(IInterface::asBinder(listener));
160 data.writeInt32(property);
161 status_t status = remote()->transact(UNSUBSCRIBE, data, &reply);
162 if (status != NO_ERROR) {
163 ALOGI("unsubscribing property %d failed %d", property, status);
164 }
165 }
166};
167
168IMPLEMENT_META_INTERFACE(VehicleNetwork, IVehicleNetwork::SERVICE_NAME);
169
170// ----------------------------------------------------------------------
171
172static bool isSystemUser() {
173 uid_t uid = IPCThreadState::self()->getCallingUid();
174 switch (uid) {
175 // This list will be expanded. Only those UIDs are allowed to access vehicle network
176 // for now. There can be per property based UID check built-in as well.
177 case AID_ROOT:
178 case AID_SYSTEM:
179 case AID_AUDIO: {
180 return true;
181 } break;
keunyoung15882e52015-09-16 16:57:58 -0700182 default: {
183 ALOGE("non-system user tried access, uid %d", uid);
184 } break;
keunyounge18e25d2015-08-28 15:57:19 -0700185 }
186 return false;
187}
188
189status_t BnVehicleNetwork::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
190 uint32_t flags) {
191 if (!isSystemUser()) {
192 return PERMISSION_DENIED;
193 }
194 status_t r;
195 switch (code) {
196 case LIST_PROPERTIES: {
197 CHECK_INTERFACE(IVehicleNetwork, data, reply);
198 int32_t property = data.readInt32();
199 sp<VehiclePropertiesHolder> holder = listProperties(property);
200 if (holder.get() == NULL) { // given property not found
keunyoung15882e52015-09-16 16:57:58 -0700201 BinderUtil::fillObjectResultReply(reply, false /* isValid */);
202 return NO_ERROR;
keunyounge18e25d2015-08-28 15:57:19 -0700203 }
204 std::unique_ptr<VehiclePropConfigs> configs(new VehiclePropConfigs());
205 ASSERT_OR_HANDLE_NO_MEMORY(configs.get(), return NO_MEMORY);
206 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getData(),
207 holder->getNumConfigs(), *configs.get());
208 int size = configs->ByteSize();
209 WritableBlobHolder blob(new Parcel::WritableBlob());
210 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
keunyoung15882e52015-09-16 16:57:58 -0700211 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700212 reply->writeInt32(size);
213 reply->writeBlob(size, false, blob.blob);
214 configs->SerializeToArray(blob.blob->data(), size);
215 return NO_ERROR;
216 } break;
217 case SET_PROPERTY: {
218 CHECK_INTERFACE(IVehicleNetwork, data, reply);
219 if (data.readInt32() == 0) { // java side allows passing null with this.
220 return BAD_VALUE;
221 }
222 ScopedVehiclePropValue value;
223 ReadableBlobHolder blob(new Parcel::ReadableBlob());
224 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
225 int32_t size = data.readInt32();
226 r = data.readBlob(size, blob.blob);
227 if (r != NO_ERROR) {
228 ALOGE("setProperty:service, cannot read blob");
229 return r;
230 }
231 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
232 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
233 if (!v->ParseFromArray(blob.blob->data(), size)) {
234 ALOGE("setProperty:service, cannot parse data");
235 return BAD_VALUE;
236 }
237 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
238 if (r != NO_ERROR) {
239 ALOGE("setProperty:service, cannot convert data");
240 return BAD_VALUE;
241 }
242 r = setProperty(value.value);
keunyoung15882e52015-09-16 16:57:58 -0700243 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700244 return r;
245 } break;
246 case GET_PROPERTY: {
247 CHECK_INTERFACE(IVehicleNetwork, data, reply);
248 ScopedVehiclePropValue value;
249 value.value.prop = data.readInt32();
250 r = getProperty(&(value.value));
251 if (r == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700252 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700253 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
254 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
255 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
256 int size = v->ByteSize();
257 WritableBlobHolder blob(new Parcel::WritableBlob());
258 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
259 reply->writeInt32(size);
260 reply->writeBlob(size, false, blob.blob);
261 v->SerializeToArray(blob.blob->data(), size);
262 }
263 return r;
264 } break;
265 case SUBSCRIBE: {
266 CHECK_INTERFACE(IVehicleNetwork, data, reply);
267 sp<IVehicleNetworkListener> listener =
268 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
269 int32_t property = data.readInt32();
270 float sampleRate = data.readFloat();
271 r = subscribe(listener, property, sampleRate);
keunyoung15882e52015-09-16 16:57:58 -0700272 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700273 return r;
274 } break;
275 case UNSUBSCRIBE: {
276 CHECK_INTERFACE(IVehicleNetwork, data, reply);
277 sp<IVehicleNetworkListener> listener =
278 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
279 int32_t property = data.readInt32();
280 unsubscribe(listener, property);
keunyoung15882e52015-09-16 16:57:58 -0700281 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700282 return NO_ERROR;
283 } break;
284 default:
285 return BBinder::onTransact(code, data, reply, flags);
286 }
287}
288
289}; // namespace android