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