1 /*
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 package com.android.car.vehiclenetwork;
17 
18 import static com.android.car.vehiclenetwork.VehiclePropValueUtil.getVectorLength;
19 import static com.android.car.vehiclenetwork.VehiclePropValueUtil.isCustomProperty;
20 import static com.android.car.vehiclenetwork.VehiclePropValueUtil.toFloatArray;
21 import static com.android.car.vehiclenetwork.VehiclePropValueUtil.toIntArray;
22 
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.Message;
26 import android.os.RemoteException;
27 import android.os.ServiceManager;
28 import android.os.ServiceSpecificException;
29 import android.util.Log;
30 
31 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
32 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
33 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
34 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
35 import com.android.internal.annotations.GuardedBy;
36 
37 import java.lang.ref.WeakReference;
38 
39 /**
40  * System API to access Vehicle network. This is only for system services and applications should
41  * not use this. All APIs will fail with security error if normal app tries this.
42  */
43 public class VehicleNetwork {
44     /**
45      * Listener for VNS events.
46      */
47     public interface VehicleNetworkListener {
48         /**
49          * Notify HAL events. This requires subscribing the property
50          */
onVehicleNetworkEvents(VehiclePropValues values)51         void onVehicleNetworkEvents(VehiclePropValues values);
onHalError(int errorCode, int property, int operation)52         void onHalError(int errorCode, int property, int operation);
onHalRestart(boolean inMocking)53         void onHalRestart(boolean inMocking);
54     }
55 
56     public interface VehicleNetworkHalMock {
onListProperties()57         VehiclePropConfigs onListProperties();
onPropertySet(VehiclePropValue value)58         void onPropertySet(VehiclePropValue value);
onPropertyGet(VehiclePropValue value)59         VehiclePropValue onPropertyGet(VehiclePropValue value);
onPropertySubscribe(int property, float sampleRate, int zones)60         void onPropertySubscribe(int property, float sampleRate, int zones);
onPropertyUnsubscribe(int property)61         void onPropertyUnsubscribe(int property);
62     }
63 
64     private static final String TAG = VehicleNetwork.class.getSimpleName();
65 
66     private final IVehicleNetwork mService;
67     private final VehicleNetworkListener mListener;
68     private final IVehicleNetworkListenerImpl mVehicleNetworkListener;
69     private final EventHandler mEventHandler;
70 
71     @GuardedBy("this")
72     private VehicleNetworkHalMock mHalMock;
73     private IVehicleNetworkHalMock mHalMockImpl;
74 
75     private static final int VNS_CONNECT_MAX_RETRY = 10;
76     private static final long VNS_RETRY_WAIT_TIME_MS = 1000;
77     private static final int NO_ZONE = -1;
78 
79     /**
80      * Factory method to create VehicleNetwork
81      *
82      * @param listener listener for listening events
83      * @param looper Looper to dispatch listener events
84      */
createVehicleNetwork(VehicleNetworkListener listener, Looper looper)85     public static VehicleNetwork createVehicleNetwork(VehicleNetworkListener listener,
86             Looper looper) {
87         int retryCount = 0;
88         IVehicleNetwork service = null;
89         while (service == null) {
90             service = IVehicleNetwork.Stub.asInterface(ServiceManager.getService(
91                     IVehicleNetwork.class.getCanonicalName()));
92             retryCount++;
93             if (retryCount > VNS_CONNECT_MAX_RETRY) {
94                 break;
95             }
96             try {
97                 Thread.sleep(VNS_RETRY_WAIT_TIME_MS);
98             } catch (InterruptedException e) {
99                 //ignore
100             }
101         }
102         if (service == null) {
103             throw new RuntimeException("Vehicle network service not available:" +
104                     IVehicleNetwork.class.getCanonicalName());
105         }
106         return new VehicleNetwork(service, listener, looper);
107     }
108 
VehicleNetwork(IVehicleNetwork service, VehicleNetworkListener listener, Looper looper)109     private VehicleNetwork(IVehicleNetwork service, VehicleNetworkListener listener,
110             Looper looper) {
111         mService = service;
112         mListener = listener;
113         mEventHandler = new EventHandler(looper);
114         mVehicleNetworkListener = new IVehicleNetworkListenerImpl(this);
115     }
116 
117     /**
118      * List all properties from vehicle HAL
119      *
120      * @return all properties
121      */
listProperties()122     public VehiclePropConfigs listProperties() {
123         return listProperties(0 /* all */);
124     }
125 
126     /**
127      * Return configuration information of single property
128      *
129      * @param property vehicle property number defined in {@link VehicleNetworkConsts}. 0 has has
130      * special meaning of list all properties.
131      * @return null if given property does not exist.
132      */
listProperties(int property)133     public VehiclePropConfigs listProperties(int property) {
134         try {
135             VehiclePropConfigsParcelable parcelable = mService.listProperties(property);
136             if (parcelable != null) {
137                 return parcelable.configs;
138             }
139         } catch (RemoteException e) {
140             handleRemoteException(e);
141         }
142         return null;
143     }
144 
145     /**
146      * Set property which will lead into writing the value to vehicle HAL.
147      *
148      * @throws IllegalArgumentException If value set has wrong value like wrong valueType, wrong
149      * data, and etc.
150      */
setProperty(VehiclePropValue value)151     public void setProperty(VehiclePropValue value) throws IllegalArgumentException {
152         VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
153         try {
154             mService.setProperty(parcelable);
155         } catch (RemoteException e) {
156             handleRemoteException(e);
157         }
158     }
159 
160     /**
161      * Set integer type property
162      *
163      * @throws IllegalArgumentException For type mismatch (=the property is not int type)
164      */
setIntProperty(int property, int value)165     public void setIntProperty(int property, int value) throws IllegalArgumentException {
166         VehiclePropValue v = VehiclePropValueUtil.createIntValue(property, value, 0);
167         setProperty(v);
168     }
169 
170     /**
171      * Set int vector type property. Length of passed values should match with vector length.
172      */
setIntVectorProperty(int property, int[] values)173     public void setIntVectorProperty(int property, int[] values) throws IllegalArgumentException {
174         VehiclePropValue v = VehiclePropValueUtil.createIntVectorValue(property, values, 0);
175         setProperty(v);
176     }
177 
178     /**
179      * Set long type property.
180      */
setLongProperty(int property, long value)181     public void setLongProperty(int property, long value) throws IllegalArgumentException {
182         VehiclePropValue v = VehiclePropValueUtil.createLongValue(property, value, 0);
183         setProperty(v);
184     }
185 
186     /**
187      * Set float type property.
188      */
setFloatProperty(int property, float value)189     public void setFloatProperty(int property, float value) throws IllegalArgumentException {
190         VehiclePropValue v = VehiclePropValueUtil.createFloatValue(property, value, 0);
191         setProperty(v);
192     }
193 
194     /**
195      * Set float vector type property. Length of values should match with vector length.
196      */
setFloatVectorProperty(int property, float[] values)197     public void setFloatVectorProperty(int property, float[] values)
198             throws IllegalArgumentException {
199         VehiclePropValue v = VehiclePropValueUtil.createFloatVectorValue(property, values, 0);
200         setProperty(v);
201     }
202 
203     /**
204      * Set zoned boolean type property
205      *
206      * @throws IllegalArgumentException For type mismatch (=the property is not boolean type)
207      */
setBooleanProperty(int property, boolean value)208     public void setBooleanProperty(int property, boolean value)
209             throws IllegalArgumentException {
210         VehiclePropValue v = VehiclePropValueUtil.createBooleanValue(property, value, 0);
211         setProperty(v);
212     }
213 
214     /**
215      * Set zoned boolean type property
216      *
217      * @throws IllegalArgumentException For type mismatch (=the property is not boolean type)
218      */
setZonedBooleanProperty(int property, int zone, boolean value)219     public void setZonedBooleanProperty(int property, int zone, boolean value)
220             throws IllegalArgumentException {
221         VehiclePropValue v = VehiclePropValueUtil.createZonedBooleanValue(property, zone, value, 0);
222         setProperty(v);
223     }
224 
225     /**
226      * Set zoned float type property
227      *
228      * @throws IllegalArgumentException For type mismatch (=the property is not float type)
229      */
setZonedFloatProperty(int property, int zone, float value)230     public void setZonedFloatProperty(int property, int zone, float value)
231             throws IllegalArgumentException {
232         VehiclePropValue v = VehiclePropValueUtil.createZonedFloatValue(property, zone, value, 0);
233         setProperty(v);
234     }
235 
236     /**
237      * Set zoned integer type property
238      *
239      * @throws IllegalArgumentException For type mismatch (=the property is not int type)
240      */
setZonedIntProperty(int property, int zone, int value)241     public void setZonedIntProperty(int property, int zone, int value)
242             throws IllegalArgumentException {
243         VehiclePropValue v = VehiclePropValueUtil.createZonedIntValue(property, zone, value, 0);
244         setProperty(v);
245     }
246 
247     /**
248      * Set zoned int vector type property. Length of passed values should match with vector length.
249      */
setZonedIntVectorProperty(int property, int zone, int[] values)250     public void setZonedIntVectorProperty(int property, int zone, int[] values)
251             throws IllegalArgumentException {
252         VehiclePropValue v = VehiclePropValueUtil
253                 .createZonedIntVectorValue(property, zone, values, 0);
254         setProperty(v);
255     }
256 
257     /**
258      * Set zoned float vector type property. Length of passed values should match with vector
259      * length.
260      */
setZonedFloatVectorProperty(int property, int zone, float[] values)261     public void setZonedFloatVectorProperty(int property, int zone, float[] values)
262             throws IllegalArgumentException {
263         VehiclePropValue v = VehiclePropValueUtil
264                 .createZonedFloatVectorValue(property, zone, values, 0);
265         setProperty(v);
266     }
267 
268     /**
269      * Get property. This can be used for a property which does not require any other data.
270      */
getProperty(int property)271     public VehiclePropValue getProperty(int property) throws IllegalArgumentException,
272             ServiceSpecificException {
273         int valueType = VehicleNetworkConsts.getVehicleValueType(property);
274         if (valueType == 0) {
275             throw new IllegalArgumentException("Data type is unknown for property: " + property);
276         }
277         VehiclePropValue value = VehiclePropValueUtil.createBuilder(property, valueType, 0).build();
278         return getProperty(value);
279     }
280 
281     /**
282      * Generic get method for any type of property. Some property may require setting data portion
283      * as get may return different result depending on the data set.
284      */
getProperty(VehiclePropValue value)285     public VehiclePropValue getProperty(VehiclePropValue value) throws IllegalArgumentException,
286             ServiceSpecificException {
287         VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
288         try {
289             VehiclePropValueParcelable resParcelable = mService.getProperty(parcelable);
290             if (resParcelable != null) {
291                 return resParcelable.value;
292             }
293         } catch (RemoteException e) {
294             handleRemoteException(e);
295         }
296         return null;
297     }
298 
299     /**
300      * Get int type property.
301      */
getIntProperty(int property)302     public int getIntProperty(int property) throws IllegalArgumentException,
303             ServiceSpecificException {
304         VehiclePropValue v = getProperty(
305                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT32);
306         if (v.getInt32ValuesCount() != 1) {
307             throw new IllegalStateException();
308         }
309         return v.getInt32Values(0);
310     }
311 
312     /**
313      * Get zoned int type property.
314      */
getZonedIntProperty(int property, int zone)315     public int getZonedIntProperty(int property, int zone) throws IllegalArgumentException,
316             ServiceSpecificException {
317         VehiclePropValue v = getProperty(
318                 property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
319         if (v.getInt32ValuesCount() != 1) {
320             throw new IllegalStateException();
321         }
322         return v.getInt32Values(0);
323     }
324 
325     /**
326      * Get int vector type property. Length of values should match vector length.
327      */
getIntVectorProperty(int property)328     public int[] getIntVectorProperty(int property) throws IllegalArgumentException,
329             ServiceSpecificException {
330         VehiclePropValue v = getProperty(
331                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT32);
332         assertVectorLength(v.getInt32ValuesCount(), property, v.getValueType());
333         return toIntArray(v.getInt32ValuesList());
334     }
335 
336     /**
337      * Get zoned int vector type property. Length of values should match vector length.
338      */
getZonedIntVectorProperty(int property, int zone)339     public int[] getZonedIntVectorProperty(int property, int zone)
340             throws IllegalArgumentException, ServiceSpecificException {
341         VehiclePropValue v = getProperty(
342                 property, zone, VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32);
343         assertVectorLength(v.getInt32ValuesCount(), property, v.getValueType());
344         return toIntArray(v.getInt32ValuesList());
345     }
346 
347     /**
348      * Get float type property.
349      */
getFloatProperty(int property)350     public float getFloatProperty(int property) throws IllegalArgumentException,
351             ServiceSpecificException {
352         VehiclePropValue v = getProperty(
353                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT);
354         if (v.getFloatValuesCount() != 1) {
355             throw new IllegalStateException();
356         }
357         return v.getFloatValues(0);
358     }
359 
360     /**
361      * Get float vector type property. Length of values should match vector's length.
362      */
getFloatVectorProperty(int property)363     public float[] getFloatVectorProperty(int property) throws IllegalArgumentException,
364             ServiceSpecificException {
365         VehiclePropValue v = getProperty(
366                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT);
367         assertVectorLength(v.getFloatValuesCount(), property, v.getValueType());
368         return toFloatArray(v.getFloatValuesList());
369     }
370 
371     /**
372      * Get zoned float vector type property. Length of values should match vector's length.
373      */
getZonedFloatVectorProperty(int property, int zone)374     public float[] getZonedFloatVectorProperty(int property, int zone)
375             throws IllegalArgumentException, ServiceSpecificException {
376         VehiclePropValue v = getProperty(property, zone,
377                 VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT);
378         assertVectorLength(v.getFloatValuesCount(), property, v.getValueType());
379         return toFloatArray(v.getFloatValuesList());
380     }
381 
382     /**
383      * Get long type property.
384      */
getLongProperty(int property)385     public long getLongProperty(int property) throws IllegalArgumentException,
386             ServiceSpecificException {
387         VehiclePropValue v = getProperty(
388                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_INT64);
389         return v.getInt64Value();
390     }
391 
392     /**
393      * Get string type property.
394      */
395     //TODO check UTF8 to java string conversion
getStringProperty(int property)396     public String getStringProperty(int property) throws IllegalArgumentException,
397             ServiceSpecificException {
398         VehiclePropValue v = getProperty(
399                 property, NO_ZONE, VehicleValueType.VEHICLE_VALUE_TYPE_STRING);
400         return v.getStringValue();
401     }
402 
403     /**
404      * Subscribe given property with given sample rate.
405      */
subscribe(int property, float sampleRate)406     public void subscribe(int property, float sampleRate) throws IllegalArgumentException {
407         subscribe(property, sampleRate, 0);
408     }
409 
410     /**
411      * Subscribe given property with given sample rate.
412      */
subscribe(int property, float sampleRate, int zones)413     public void subscribe(int property, float sampleRate, int zones)
414             throws IllegalArgumentException {
415         try {
416             mService.subscribe(mVehicleNetworkListener, property, sampleRate, zones);
417         } catch (RemoteException e) {
418             handleRemoteException(e);
419         }
420     }
421 
422     /**
423      * Stop subscribing the property.
424      */
unsubscribe(int property)425     public void unsubscribe(int property) {
426         try {
427             mService.unsubscribe(mVehicleNetworkListener, property);
428         } catch (RemoteException e) {
429             handleRemoteException(e);
430         }
431     }
432 
433     /**
434      * Inject given value to all clients subscribing the property. This is for testing.
435      */
injectEvent(VehiclePropValue value)436     public synchronized void injectEvent(VehiclePropValue value) {
437         try {
438             mService.injectEvent(new VehiclePropValueParcelable(value));
439         } catch (RemoteException e) {
440             handleRemoteException(e);
441         }
442     }
443 
444     /**
445      * Start mocking of vehicle HAL. For testing only.
446      */
startMocking(VehicleNetworkHalMock mock)447     public synchronized void startMocking(VehicleNetworkHalMock mock) {
448         mHalMock = mock;
449         mHalMockImpl = new IVehicleNetworkHalMockImpl(this);
450         try {
451             mService.startMocking(mHalMockImpl);
452         } catch (RemoteException e) {
453             handleRemoteException(e);
454         }
455     }
456 
457     /**
458      * Stop mocking of vehicle HAL. For testing only.
459      */
stopMocking()460     public synchronized void stopMocking() {
461         if (mHalMockImpl == null) {
462             return;
463         }
464         try {
465             mService.stopMocking(mHalMockImpl);
466         } catch (RemoteException e) {
467             handleRemoteException(e);
468         } finally {
469             mHalMock = null;
470             mHalMockImpl = null;
471         }
472     }
473 
474     /**
475      * Start mocking of vehicle HAL. For testing only.
476      */
startMocking(IVehicleNetworkHalMock mock)477     public synchronized void startMocking(IVehicleNetworkHalMock mock) {
478         mHalMock = null;
479         mHalMockImpl = mock;
480         try {
481             mService.startMocking(mHalMockImpl);
482         } catch (RemoteException e) {
483             handleRemoteException(e);
484         }
485     }
486 
487     /**
488      * Stop mocking of vehicle HAL. For testing only.
489      */
stopMocking(IVehicleNetworkHalMock mock)490     public synchronized void stopMocking(IVehicleNetworkHalMock mock) {
491         if (mock.asBinder() != mHalMockImpl.asBinder()) {
492             return;
493         }
494         try {
495             mService.stopMocking(mHalMockImpl);
496         } catch (RemoteException e) {
497             handleRemoteException(e);
498         } finally {
499             mHalMock = null;
500             mHalMockImpl = null;
501         }
502     }
503 
injectHalError(int errorCode, int property, int operation)504     public synchronized void injectHalError(int errorCode, int property, int operation) {
505         try {
506             mService.injectHalError(errorCode, property, operation);
507         } catch (RemoteException e) {
508             handleRemoteException(e);
509         }
510     }
511 
startErrorListening()512     public synchronized void startErrorListening() {
513         try {
514             mService.startErrorListening(mVehicleNetworkListener);
515         } catch (RemoteException e) {
516             handleRemoteException(e);
517         }
518     }
519 
stopErrorListening()520     public synchronized void stopErrorListening() {
521         try {
522             mService.stopErrorListening(mVehicleNetworkListener);
523         } catch (RemoteException e) {
524             handleRemoteException(e);
525         }
526     }
527 
startHalRestartMonitoring()528     public synchronized void startHalRestartMonitoring() {
529         try {
530             mService.startHalRestartMonitoring(mVehicleNetworkListener);
531         } catch (RemoteException e) {
532             handleRemoteException(e);
533         }
534     }
535 
stopHalRestartMonitoring()536     public synchronized void stopHalRestartMonitoring() {
537         try {
538             mService.stopHalRestartMonitoring(mVehicleNetworkListener);
539         } catch (RemoteException e) {
540             handleRemoteException(e);
541         }
542     }
543 
getHalMock()544     private synchronized VehicleNetworkHalMock getHalMock() {
545         return mHalMock;
546     }
547 
handleRemoteException(RemoteException e)548     private void handleRemoteException(RemoteException e) {
549         throw new RuntimeException("Vehicle network service not working ", e);
550     }
551 
handleVehicleNetworkEvents(VehiclePropValues values)552     private void handleVehicleNetworkEvents(VehiclePropValues values) {
553         mListener.onVehicleNetworkEvents(values);
554     }
555 
handleHalError(int errorCode, int property, int operation)556     private void handleHalError(int errorCode, int property, int operation) {
557         mListener.onHalError(errorCode, property, operation);
558     }
559 
handleHalRestart(boolean inMocking)560     private void handleHalRestart(boolean inMocking) {
561         mListener.onHalRestart(inMocking);
562     }
563 
564     private class EventHandler extends Handler {
565 
566         private static final int MSG_EVENTS = 0;
567         private static final int MSG_HAL_ERROR = 1;
568         private static final int MSG_HAL_RESTART = 2;
569 
EventHandler(Looper looper)570         private EventHandler(Looper looper) {
571             super(looper);
572         }
573 
notifyEvents(VehiclePropValues values)574         private void notifyEvents(VehiclePropValues values) {
575             Message msg = obtainMessage(MSG_EVENTS, values);
576             sendMessage(msg);
577         }
578 
notifyHalError(int errorCode, int property, int operation)579         private void notifyHalError(int errorCode, int property, int operation) {
580             Message msg = obtainMessage(MSG_HAL_ERROR, errorCode, property, operation);
581             sendMessage(msg);
582         }
583 
notifyHalRestart(boolean inMocking)584         private void notifyHalRestart(boolean inMocking) {
585             Message msg = obtainMessage(MSG_HAL_RESTART, inMocking ? 1 : 0, 0);
586             sendMessage(msg);
587         }
588 
589         @Override
handleMessage(Message msg)590         public void handleMessage(Message msg) {
591             switch (msg.what) {
592                 case MSG_EVENTS:
593                     handleVehicleNetworkEvents((VehiclePropValues) msg.obj);
594                     break;
595                 case MSG_HAL_ERROR:
596                     handleHalError(msg.arg1, msg.arg2, (Integer) msg.obj);
597                     break;
598                 case MSG_HAL_RESTART:
599                     handleHalRestart(msg.arg1 == 1);
600                     break;
601                 default:
602                     Log.w(TAG, "Unknown message:" + msg.what, new RuntimeException());
603                     break;
604             }
605         }
606     }
607 
608     private static class IVehicleNetworkListenerImpl extends IVehicleNetworkListener.Stub {
609 
610         private final WeakReference<VehicleNetwork> mVehicleNetwork;
611 
IVehicleNetworkListenerImpl(VehicleNetwork vehicleNewotk)612         private IVehicleNetworkListenerImpl(VehicleNetwork vehicleNewotk) {
613             mVehicleNetwork = new WeakReference<>(vehicleNewotk);
614         }
615 
616         @Override
onVehicleNetworkEvents(VehiclePropValuesParcelable values)617         public void onVehicleNetworkEvents(VehiclePropValuesParcelable values) {
618             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
619             if (vehicleNetwork != null) {
620                 vehicleNetwork.mEventHandler.notifyEvents(values.values);
621             }
622         }
623 
624         @Override
onHalError(int errorCode, int property, int operation)625         public void onHalError(int errorCode, int property, int operation) {
626             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
627             if (vehicleNetwork != null) {
628                 vehicleNetwork.mEventHandler.notifyHalError(errorCode, property, operation);
629             }
630         }
631 
632         @Override
onHalRestart(boolean inMocking)633         public void onHalRestart(boolean inMocking) {
634             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
635             if (vehicleNetwork != null) {
636                 vehicleNetwork.mEventHandler.notifyHalRestart(inMocking);
637             }
638         }
639     }
640 
641     private static class IVehicleNetworkHalMockImpl extends IVehicleNetworkHalMock.Stub {
642         private final WeakReference<VehicleNetwork> mVehicleNetwork;
643 
IVehicleNetworkHalMockImpl(VehicleNetwork vehicleNewotk)644         private IVehicleNetworkHalMockImpl(VehicleNetwork vehicleNewotk) {
645             mVehicleNetwork = new WeakReference<>(vehicleNewotk);
646         }
647 
648         @Override
onListProperties()649         public VehiclePropConfigsParcelable onListProperties() {
650             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
651             if (vehicleNetwork == null) {
652                 return null;
653             }
654             VehiclePropConfigs configs = vehicleNetwork.getHalMock().onListProperties();
655             return new VehiclePropConfigsParcelable(configs);
656         }
657 
658         @Override
onPropertySet(VehiclePropValueParcelable value)659         public void onPropertySet(VehiclePropValueParcelable value) {
660             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
661             if (vehicleNetwork == null) {
662                 return;
663             }
664             vehicleNetwork.getHalMock().onPropertySet(value.value);
665         }
666 
667         @Override
onPropertyGet(VehiclePropValueParcelable value)668         public VehiclePropValueParcelable onPropertyGet(VehiclePropValueParcelable value) {
669             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
670             if (vehicleNetwork == null) {
671                 return null;
672             }
673             VehiclePropValue resValue = vehicleNetwork.getHalMock().onPropertyGet(value.value);
674             return new VehiclePropValueParcelable(resValue);
675         }
676 
677         @Override
onPropertySubscribe(int property, float sampleRate, int zones)678         public void onPropertySubscribe(int property, float sampleRate, int zones) {
679             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
680             if (vehicleNetwork == null) {
681                 return;
682             }
683             vehicleNetwork.getHalMock().onPropertySubscribe(property, sampleRate, zones);
684         }
685 
686         @Override
onPropertyUnsubscribe(int property)687         public void onPropertyUnsubscribe(int property) {
688             VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
689             if (vehicleNetwork == null) {
690                 return;
691             }
692             vehicleNetwork.getHalMock().onPropertyUnsubscribe(property);
693         }
694     }
695 
getProperty(int property, int zone, int customPropetyDataType)696     private VehiclePropValue getProperty(int property, int zone, int customPropetyDataType) {
697         boolean isCustom = isCustomProperty(property);
698         int valueType = isCustom
699                 ? customPropetyDataType
700                 : VehicleNetworkConsts.getVehicleValueType(property);
701 
702         VehiclePropValue.Builder valuePrototypeBuilder =
703                 VehiclePropValueUtil.createBuilder(property, valueType, 0);
704 
705         if (zone != NO_ZONE) {
706             valuePrototypeBuilder.setZone(zone);
707         }
708 
709         VehiclePropValue v = getProperty(valuePrototypeBuilder.build());
710         if (v == null) {
711             // if property is invalid, IllegalArgumentException should have been thrown
712             // from getProperty.
713             throw new IllegalStateException();
714         }
715 
716         if (!isCustom && v.getValueType() != valueType) {
717             throw new IllegalArgumentException(
718                     "Unexpected type for property 0x" + Integer.toHexString(property) +
719                     " got:0x" + Integer.toHexString(v.getValueType())
720                     + ", expecting:0x" + Integer.toHexString(valueType));
721         }
722         return v;
723     }
724 
assertVectorLength(int actual, int property, int valueType)725     private void assertVectorLength(int actual, int property, int valueType) {
726         int expectedLen = getVectorLength(valueType);
727         if (expectedLen != actual) {
728             throw new IllegalStateException("Invalid array size for property: " + property
729                     + ". Expected: " + expectedLen
730                     + ", actual: " + actual);
731         }
732     }
733 }
734