blob: a3b17a53314cd161ad16278f26021da610c06edc [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 }
keunyoungd32f4e62015-09-21 11:33:06 -070085 holder = new VehiclePropertiesHolder();
86 ASSERT_OR_HANDLE_NO_MEMORY(holder.get(), return);
87 status = VehicleNetworkProtoUtil::fromVehiclePropConfigs(*configs.get(),
88 holder->getList());
keunyounge18e25d2015-08-28 15:57:19 -070089 if (status != NO_ERROR) {
90 ALOGE("listProperties, cannot convert VehiclePropConfigs %d", status);
91 return holder;
92 }
keunyoungd32f4e62015-09-21 11:33:06 -070093
keunyounge18e25d2015-08-28 15:57:19 -070094 }
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);
keunyoungd32f4e62015-09-21 11:33:06 -0700206 VehicleNetworkProtoUtil::toVehiclePropConfigs(holder->getList(), *configs.get());
keunyounge18e25d2015-08-28 15:57:19 -0700207 int size = configs->ByteSize();
208 WritableBlobHolder blob(new Parcel::WritableBlob());
209 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
keunyoung15882e52015-09-16 16:57:58 -0700210 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700211 reply->writeInt32(size);
212 reply->writeBlob(size, false, blob.blob);
213 configs->SerializeToArray(blob.blob->data(), size);
214 return NO_ERROR;
215 } break;
216 case SET_PROPERTY: {
217 CHECK_INTERFACE(IVehicleNetwork, data, reply);
218 if (data.readInt32() == 0) { // java side allows passing null with this.
219 return BAD_VALUE;
220 }
221 ScopedVehiclePropValue value;
222 ReadableBlobHolder blob(new Parcel::ReadableBlob());
223 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
224 int32_t size = data.readInt32();
225 r = data.readBlob(size, blob.blob);
226 if (r != NO_ERROR) {
227 ALOGE("setProperty:service, cannot read blob");
228 return r;
229 }
230 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
231 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
232 if (!v->ParseFromArray(blob.blob->data(), size)) {
233 ALOGE("setProperty:service, cannot parse data");
234 return BAD_VALUE;
235 }
236 r = VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), value.value);
237 if (r != NO_ERROR) {
238 ALOGE("setProperty:service, cannot convert data");
239 return BAD_VALUE;
240 }
241 r = setProperty(value.value);
keunyoung15882e52015-09-16 16:57:58 -0700242 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700243 return r;
244 } break;
245 case GET_PROPERTY: {
246 CHECK_INTERFACE(IVehicleNetwork, data, reply);
247 ScopedVehiclePropValue value;
248 value.value.prop = data.readInt32();
249 r = getProperty(&(value.value));
250 if (r == NO_ERROR) {
keunyoung15882e52015-09-16 16:57:58 -0700251 BinderUtil::fillObjectResultReply(reply, true);
keunyounge18e25d2015-08-28 15:57:19 -0700252 std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
253 ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
254 VehicleNetworkProtoUtil::toVehiclePropValue(value.value, *v.get());
255 int size = v->ByteSize();
256 WritableBlobHolder blob(new Parcel::WritableBlob());
257 ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
258 reply->writeInt32(size);
259 reply->writeBlob(size, false, blob.blob);
260 v->SerializeToArray(blob.blob->data(), size);
261 }
262 return r;
263 } break;
264 case SUBSCRIBE: {
265 CHECK_INTERFACE(IVehicleNetwork, data, reply);
266 sp<IVehicleNetworkListener> listener =
267 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
268 int32_t property = data.readInt32();
269 float sampleRate = data.readFloat();
270 r = subscribe(listener, property, sampleRate);
keunyoung15882e52015-09-16 16:57:58 -0700271 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700272 return r;
273 } break;
274 case UNSUBSCRIBE: {
275 CHECK_INTERFACE(IVehicleNetwork, data, reply);
276 sp<IVehicleNetworkListener> listener =
277 interface_cast<IVehicleNetworkListener>(data.readStrongBinder());
278 int32_t property = data.readInt32();
279 unsubscribe(listener, property);
keunyoung15882e52015-09-16 16:57:58 -0700280 BinderUtil::fillNoResultReply(reply);
keunyounge18e25d2015-08-28 15:57:19 -0700281 return NO_ERROR;
282 } break;
283 default:
284 return BBinder::onTransact(code, data, reply, flags);
285 }
286}
287
288}; // namespace android