blob: 09453dd3c40149028ba1ec1ebfe77187979d08fc [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 */
16package com.android.car.vehiclenetwork;
17
18import android.annotation.Nullable;
19import android.os.Handler;
20import android.os.Looper;
21import android.os.Message;
22import android.os.RemoteException;
23import android.os.ServiceManager;
24import android.util.Log;
25
keunyoungd32f4e62015-09-21 11:33:06 -070026import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
keunyounge18e25d2015-08-28 15:57:19 -070027import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
28import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
29import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
keunyoung1ab8e182015-09-24 09:25:22 -070030import com.android.internal.annotations.GuardedBy;
keunyounge18e25d2015-08-28 15:57:19 -070031
32import java.lang.ref.WeakReference;
33
34/**
35 * System API to access Vehicle network. This is only for system services and applications should
keunyoung15882e52015-09-16 16:57:58 -070036 * not use this. All APIs will fail with security error if normal app tries this.
keunyounge18e25d2015-08-28 15:57:19 -070037 */
38public class VehicleNetwork {
keunyoung1ab8e182015-09-24 09:25:22 -070039 /**
40 * Listener for VNS events.
41 */
keunyounge18e25d2015-08-28 15:57:19 -070042 public interface VehicleNetworkListener {
keunyoung1ab8e182015-09-24 09:25:22 -070043 /**
44 * Notify HAL events. This requires subscribing the property
45 */
keunyounge18e25d2015-08-28 15:57:19 -070046 void onVehicleNetworkEvents(VehiclePropValues values);
47 }
48
keunyoung1ab8e182015-09-24 09:25:22 -070049 public interface VehicleNetworkHalMock {
50 VehiclePropConfigs onListProperties();
51 void onPropertySet(VehiclePropValue value);
keunyoung7d74e6d2015-10-14 15:43:10 -070052 VehiclePropValue onPropertyGet(VehiclePropValue property);
keunyoung1ab8e182015-09-24 09:25:22 -070053 void onPropertySubscribe(int property, int sampleRate);
54 void onPropertyUnsubscribe(int property);
55 }
56
keunyounge18e25d2015-08-28 15:57:19 -070057 private static final String TAG = VehicleNetwork.class.getSimpleName();
58
59 private final IVehicleNetwork mService;
60 private final VehicleNetworkListener mListener;
61 private final IVehicleNetworkListenerImpl mVehicleNetworkListener;
62 private final EventHandler mEventHandler;
63
keunyoung1ab8e182015-09-24 09:25:22 -070064 @GuardedBy("this")
65 private VehicleNetworkHalMock mHalMock;
66 private IVehicleNetworkHalMock mHalMockImpl;
67
keunyoung15882e52015-09-16 16:57:58 -070068 public static VehicleNetwork createVehicleNetwork(VehicleNetworkListener listener,
69 Looper looper) {
keunyounge18e25d2015-08-28 15:57:19 -070070 IVehicleNetwork service = IVehicleNetwork.Stub.asInterface(ServiceManager.getService(
71 IVehicleNetwork.class.getCanonicalName()));
72 if (service == null) {
keunyoung15882e52015-09-16 16:57:58 -070073 throw new RuntimeException("Vehicle network service not available:" +
74 IVehicleNetwork.class.getCanonicalName());
keunyounge18e25d2015-08-28 15:57:19 -070075 }
76 return new VehicleNetwork(service, listener, looper);
77 }
78
79 private VehicleNetwork(IVehicleNetwork service, VehicleNetworkListener listener,
80 Looper looper) {
81 mService = service;
82 mListener = listener;
83 mEventHandler = new EventHandler(looper);
84 mVehicleNetworkListener = new IVehicleNetworkListenerImpl(this);
85 }
86
keunyoung15882e52015-09-16 16:57:58 -070087 public VehiclePropConfigs listProperties() {
88 return listProperties(0 /* all */);
89 }
90
keunyounge18e25d2015-08-28 15:57:19 -070091 public VehiclePropConfigs listProperties(int property) {
92 try {
93 VehiclePropConfigsParcelable parcelable = mService.listProperties(property);
94 if (parcelable != null) {
95 return parcelable.configs;
96 }
97 } catch (RemoteException e) {
98 handleRemoteException(e);
99 }
100 return null;
101 }
102
keunyoung15882e52015-09-16 16:57:58 -0700103 public void setProperty(VehiclePropValue value) {
keunyounge18e25d2015-08-28 15:57:19 -0700104 VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
105 try {
keunyoung15882e52015-09-16 16:57:58 -0700106 mService.setProperty(parcelable);
keunyounge18e25d2015-08-28 15:57:19 -0700107 } catch (RemoteException e) {
108 handleRemoteException(e);
109 }
keunyounge18e25d2015-08-28 15:57:19 -0700110 }
111
keunyoungfe30ba02015-09-17 17:56:35 -0700112 public void setIntProperty(int property, int value) {
keunyoung1ab8e182015-09-24 09:25:22 -0700113 VehiclePropValue v = VehiclePropValueUtil.createIntValue(property, value, 0);
keunyoungfe30ba02015-09-17 17:56:35 -0700114 setProperty(v);
115 }
116
keunyoungd32f4e62015-09-21 11:33:06 -0700117 public void setIntVectorProperty(int property, int[] values) {
keunyoung1ab8e182015-09-24 09:25:22 -0700118 VehiclePropValue v = VehiclePropValueUtil.createIntVectorValue(property, values, 0);
119 setProperty(v);
keunyoungd32f4e62015-09-21 11:33:06 -0700120 }
121
keunyoungfe30ba02015-09-17 17:56:35 -0700122 public void setLongProperty(int property, long value) {
keunyoung1ab8e182015-09-24 09:25:22 -0700123 VehiclePropValue v = VehiclePropValueUtil.createLongValue(property, value, 0);
keunyoungfe30ba02015-09-17 17:56:35 -0700124 setProperty(v);
125 }
126
keunyoungd32f4e62015-09-21 11:33:06 -0700127 public void setFloatProperty(int property, float value) {
keunyoung1ab8e182015-09-24 09:25:22 -0700128 VehiclePropValue v = VehiclePropValueUtil.createFloatValue(property, value, 0);
keunyoungfe30ba02015-09-17 17:56:35 -0700129 setProperty(v);
130 }
131
keunyoungd32f4e62015-09-21 11:33:06 -0700132 public void setFloatVectorProperty(int property, float[] values) {
keunyoung1ab8e182015-09-24 09:25:22 -0700133 VehiclePropValue v = VehiclePropValueUtil.createFloatVectorValue(property, values, 0);
134 setProperty(v);
keunyoungd32f4e62015-09-21 11:33:06 -0700135 }
136
keunyounge18e25d2015-08-28 15:57:19 -0700137 public VehiclePropValue getProperty(int property) {
keunyoung7d74e6d2015-10-14 15:43:10 -0700138 int valueType = VehicleNetworkConsts.getVehicleValueType(property);
139 VehiclePropValue value = VehiclePropValueUtil.createBuilder(property, valueType, 0).build();
140 return getProperty(value);
141 }
142
143 public VehiclePropValue getProperty(VehiclePropValue value) {
144 VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
keunyounge18e25d2015-08-28 15:57:19 -0700145 try {
keunyoung7d74e6d2015-10-14 15:43:10 -0700146 VehiclePropValueParcelable resParcelable = mService.getProperty(parcelable);
147 if (resParcelable != null) {
148 return resParcelable.value;
keunyounge18e25d2015-08-28 15:57:19 -0700149 }
150 } catch (RemoteException e) {
151 handleRemoteException(e);
152 }
153 return null;
154 }
155
keunyoungfe30ba02015-09-17 17:56:35 -0700156 public int getIntProperty(int property) {
157 VehiclePropValue v = getProperty(property);
158 if (v == null) {
keunyoungd32f4e62015-09-21 11:33:06 -0700159 // if property is invalid, IllegalArgumentException should have been thrown
160 // from getProperty.
keunyoungfe30ba02015-09-17 17:56:35 -0700161 throw new IllegalStateException();
162 }
keunyoungd32f4e62015-09-21 11:33:06 -0700163 if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_INT32) {
keunyoungfe30ba02015-09-17 17:56:35 -0700164 throw new IllegalArgumentException();
165 }
keunyoungd32f4e62015-09-21 11:33:06 -0700166 if (v.getInt32ValuesCount() != 1) {
167 throw new IllegalStateException();
168 }
169 return v.getInt32Values(0);
170 }
171
172 public void getIntVectorProperty(int property, int[] values) {
173 VehiclePropValue v = getProperty(property);
174 if (v == null) {
175 // if property is invalid, IllegalArgumentException should have been thrown
176 // from getProperty.
177 throw new IllegalStateException();
178 }
179 switch (v.getValueType()) {
180 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2:
181 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3:
182 case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4:
183 if (values.length !=
184 (v.getValueType() - VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2 + 2)) {
185 throw new IllegalArgumentException("wrong array length");
186 }
187 break;
188 default:
189 throw new IllegalArgumentException();
190 }
191 if (v.getInt32ValuesCount() != values.length) {
192 throw new IllegalStateException();
193 }
194 for (int i = 0; i < values.length; i++) {
195 values[i] = v.getInt32Values(i);
196 }
keunyoungfe30ba02015-09-17 17:56:35 -0700197 }
198
199 public float getFloatProperty(int property) {
200 VehiclePropValue v = getProperty(property);
201 if (v == null) {
202 throw new IllegalStateException();
203 }
keunyoungd32f4e62015-09-21 11:33:06 -0700204 if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT) {
keunyoungfe30ba02015-09-17 17:56:35 -0700205 throw new IllegalArgumentException();
206 }
keunyoungd32f4e62015-09-21 11:33:06 -0700207 if (v.getFloatValuesCount() != 1) {
208 throw new IllegalStateException();
209 }
210 return v.getFloatValues(0);
211 }
212
213 public void getFloatVectorProperty(int property, float[] values) {
214 VehiclePropValue v = getProperty(property);
215 if (v == null) {
216 // if property is invalid, IllegalArgumentException should have been thrown
217 // from getProperty.
218 throw new IllegalStateException();
219 }
220 switch (v.getValueType()) {
221 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2:
222 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3:
223 case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4:
224 if (values.length !=
225 (v.getValueType() - VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2 + 2)) {
226 throw new IllegalArgumentException("wrong array length");
227 }
228 break;
229 default:
230 throw new IllegalArgumentException();
231 }
232 if (v.getFloatValuesCount() != values.length) {
233 throw new IllegalStateException();
234 }
235 for (int i = 0; i < values.length; i++) {
236 values[i] = v.getFloatValues(i);
237 }
keunyoungfe30ba02015-09-17 17:56:35 -0700238 }
239
240 public long getLongProperty(int property) {
241 VehiclePropValue v = getProperty(property);
242 if (v == null) {
243 throw new IllegalStateException();
244 }
keunyoungd32f4e62015-09-21 11:33:06 -0700245 if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_INT64) {
keunyoungfe30ba02015-09-17 17:56:35 -0700246 throw new IllegalArgumentException();
247 }
248 return v.getInt64Value();
249 }
250
251 //TODO check UTF8 to java string conversion
252 public String getStringProperty(int property) {
253 VehiclePropValue v = getProperty(property);
254 if (v == null) {
255 throw new IllegalStateException();
256 }
keunyoungd32f4e62015-09-21 11:33:06 -0700257 if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_STRING) {
keunyoungfe30ba02015-09-17 17:56:35 -0700258 throw new IllegalArgumentException();
259 }
260 return v.getStringValue();
261 }
262
keunyoung15882e52015-09-16 16:57:58 -0700263 public void subscribe(int property, float sampleRate) {
keunyounge18e25d2015-08-28 15:57:19 -0700264 try {
keunyoung15882e52015-09-16 16:57:58 -0700265 mService.subscribe(mVehicleNetworkListener, property, sampleRate);
keunyounge18e25d2015-08-28 15:57:19 -0700266 } catch (RemoteException e) {
267 handleRemoteException(e);
268 }
keunyounge18e25d2015-08-28 15:57:19 -0700269 }
270
271 public void unsubscribe(int property) {
272 try {
273 mService.unsubscribe(mVehicleNetworkListener, property);
274 } catch (RemoteException e) {
275 handleRemoteException(e);
276 }
277 }
278
keunyoung1ab8e182015-09-24 09:25:22 -0700279 public synchronized void injectEvent(VehiclePropValue value) {
280 try {
281 mService.injectEvent(new VehiclePropValueParcelable(value));
282 } catch (RemoteException e) {
283 handleRemoteException(e);
284 }
285 }
286
287 public synchronized void startMocking(VehicleNetworkHalMock mock) {
288 mHalMock = mock;
289 mHalMockImpl = new IVehicleNetworkHalMockImpl(this);
290 try {
291 mService.startMocking(mHalMockImpl);
292 } catch (RemoteException e) {
293 handleRemoteException(e);
294 }
295 }
296
297 public synchronized void stopMocking() {
298 try {
299 mService.stopMocking(mHalMockImpl);
300 } catch (RemoteException e) {
301 handleRemoteException(e);
302 } finally {
303 mHalMock = null;
304 mHalMockImpl = null;
305 }
306 }
307
308 public synchronized void startMocking(IVehicleNetworkHalMock mock) {
309 mHalMock = null;
310 mHalMockImpl = mock;
311 try {
312 mService.startMocking(mHalMockImpl);
313 } catch (RemoteException e) {
314 handleRemoteException(e);
315 }
316 }
317
318 public synchronized void stopMocking(IVehicleNetworkHalMock mock) {
319 if (mock.asBinder() != mHalMockImpl.asBinder()) {
320 return;
321 }
322 try {
323 mService.stopMocking(mHalMockImpl);
324 } catch (RemoteException e) {
325 handleRemoteException(e);
326 } finally {
327 mHalMock = null;
328 mHalMockImpl = null;
329 }
330 }
331
332 private synchronized VehicleNetworkHalMock getHalMock() {
333 return mHalMock;
334 }
335
keunyounge18e25d2015-08-28 15:57:19 -0700336 private void handleRemoteException(RemoteException e) {
337 throw new RuntimeException("Vehicle network service not working ", e);
338 }
339
340 private void handleVehicleNetworkEvents(VehiclePropValues values) {
341 mEventHandler.notifyEvents(values);
342 }
343
344 private void doHandleVehicleNetworkEvents(VehiclePropValues values) {
345 mListener.onVehicleNetworkEvents(values);
346 }
347
348 private class EventHandler extends Handler {
349 private static final int MSG_EVENTS = 0;
350
351 private EventHandler(Looper looper) {
352 super(looper);
353 }
354
355 private void notifyEvents(VehiclePropValues values) {
356 Message msg = obtainMessage(MSG_EVENTS, values);
357 sendMessage(msg);
358 }
359
360 @Override
361 public void handleMessage(Message msg) {
362 switch (msg.what) {
363 case MSG_EVENTS:
364 doHandleVehicleNetworkEvents((VehiclePropValues)msg.obj);
365 break;
366 default:
367 Log.w(TAG, "unown message:" + msg.what, new RuntimeException());
368 break;
369 }
370 }
371 }
372
373 private static class IVehicleNetworkListenerImpl extends IVehicleNetworkListener.Stub {
374 private final WeakReference<VehicleNetwork> mVehicleNetwork;
375
376 private IVehicleNetworkListenerImpl(VehicleNetwork vehicleNewotk) {
377 mVehicleNetwork = new WeakReference<VehicleNetwork>(vehicleNewotk);
378 }
379
380 @Override
381 public void onVehicleNetworkEvents(VehiclePropValuesParcelable values) {
382 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
383 if (vehicleNetwork != null) {
384 vehicleNetwork.handleVehicleNetworkEvents(values.values);
385 }
386 }
387 }
keunyoung1ab8e182015-09-24 09:25:22 -0700388
389 private static class IVehicleNetworkHalMockImpl extends IVehicleNetworkHalMock.Stub {
390 private final WeakReference<VehicleNetwork> mVehicleNetwork;
391
392 private IVehicleNetworkHalMockImpl(VehicleNetwork vehicleNewotk) {
393 mVehicleNetwork = new WeakReference<VehicleNetwork>(vehicleNewotk);
394 }
395
396 @Override
397 public VehiclePropConfigsParcelable onListProperties() {
398 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
399 if (vehicleNetwork == null) {
400 return null;
401 }
402 VehiclePropConfigs configs = vehicleNetwork.getHalMock().onListProperties();
403 return new VehiclePropConfigsParcelable(configs);
404 }
405
406 @Override
407 public void onPropertySet(VehiclePropValueParcelable value) {
408 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
409 if (vehicleNetwork == null) {
410 return;
411 }
412 vehicleNetwork.getHalMock().onPropertySet(value.value);
413 }
414
415 @Override
keunyoung7d74e6d2015-10-14 15:43:10 -0700416 public VehiclePropValueParcelable onPropertyGet(VehiclePropValueParcelable value) {
keunyoung1ab8e182015-09-24 09:25:22 -0700417 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
418 if (vehicleNetwork == null) {
419 return null;
420 }
keunyoung7d74e6d2015-10-14 15:43:10 -0700421 VehiclePropValue resValue = vehicleNetwork.getHalMock().onPropertyGet(value.value);
422 return new VehiclePropValueParcelable(resValue);
keunyoung1ab8e182015-09-24 09:25:22 -0700423 }
424
425 @Override
426 public void onPropertySubscribe(int property, int sampleRate) {
427 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
428 if (vehicleNetwork == null) {
429 return;
430 }
431 vehicleNetwork.getHalMock().onPropertySubscribe(property, sampleRate);
432 }
433
434 @Override
435 public void onPropertyUnsubscribe(int property) {
436 VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
437 if (vehicleNetwork == null) {
438 return;
439 }
440 vehicleNetwork.getHalMock().onPropertyUnsubscribe(property);
441 }
442 }
keunyounge18e25d2015-08-28 15:57:19 -0700443}