• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package android.car.hardware;
18 
19 import android.annotation.SystemApi;
20 import android.car.Car;
21 import android.car.CarManagerBase;
22 import android.car.CarNotConnectedException;
23 import android.car.hardware.property.CarPropertyManager;
24 import android.os.Handler;
25 import android.os.IBinder;
26 import android.util.ArraySet;
27 
28 import com.android.internal.annotations.GuardedBy;
29 
30 import java.lang.ref.WeakReference;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.List;
34 
35 /**
36  * API to access custom vehicle properties defined by OEMs.
37  * <p>
38  * System permission {@link Car#PERMISSION_VENDOR_EXTENSION} is required to get this manager.
39  * </p>
40  * @hide
41  */
42 @SystemApi
43 public final class CarVendorExtensionManager implements CarManagerBase {
44 
45     private final static boolean DBG = false;
46     private final static String TAG = CarVendorExtensionManager.class.getSimpleName();
47     private final CarPropertyManager mPropertyManager;
48 
49     @GuardedBy("mLock")
50     private final ArraySet<CarVendorExtensionCallback> mCallbacks = new ArraySet<>();
51     private final Object mLock = new Object();
52 
53     @GuardedBy("mLock")
54     private CarPropertyEventListenerToBase mListenerToBase = null;
55 
handleOnChangeEvent(CarPropertyValue value)56     private void handleOnChangeEvent(CarPropertyValue value) {
57         Collection<CarVendorExtensionCallback> callbacks;
58         synchronized (mLock) {
59             callbacks = new ArrayList<>(mCallbacks);
60         }
61         for (CarVendorExtensionCallback l: callbacks) {
62             l.onChangeEvent(value);
63         }
64     }
65 
handleOnErrorEvent(int propertyId, int zone)66     private void handleOnErrorEvent(int propertyId, int zone) {
67         Collection<CarVendorExtensionCallback> listeners;
68         synchronized (mLock) {
69             listeners = new ArrayList<>(mCallbacks);
70         }
71         for (CarVendorExtensionCallback l: listeners) {
72             l.onErrorEvent(propertyId, zone);
73         }
74 
75     }
76 
77     /**
78      * Creates an instance of the {@link CarVendorExtensionManager}.
79      *
80      * <p>Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead.
81      * @hide
82      */
CarVendorExtensionManager(IBinder service, Handler handler)83     public CarVendorExtensionManager(IBinder service, Handler handler) {
84         mPropertyManager = new CarPropertyManager(service, handler, DBG, TAG);
85     }
86 
87     /**
88      * Contains callback functions that will be called when some event happens with vehicle
89      * property.
90      */
91     public interface CarVendorExtensionCallback {
92         /** Called when a property is updated */
onChangeEvent(CarPropertyValue value)93         void onChangeEvent(CarPropertyValue value);
94 
95         /** Called when an error is detected with a property */
onErrorEvent(int propertyId, int zone)96         void onErrorEvent(int propertyId, int zone);
97     }
98 
99     /**
100      * Registers listener. The methods of the listener will be called when new events arrived in
101      * the main thread.
102      */
registerCallback(CarVendorExtensionCallback callback)103     public void registerCallback(CarVendorExtensionCallback callback)
104             throws CarNotConnectedException {
105         synchronized (mLock) {
106             if (mCallbacks.isEmpty()) {
107                 mListenerToBase = new CarPropertyEventListenerToBase(this);
108             }
109 
110             List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
111             for (CarPropertyConfig c : configs) {
112                 // Register each individual propertyId
113                 mPropertyManager.registerListener(mListenerToBase, c.getPropertyId(), 0);
114             }
115             mCallbacks.add(callback);
116         }
117     }
118 
119     /** Unregisters listener that was previously registered. */
unregisterCallback(CarVendorExtensionCallback callback)120     public void unregisterCallback(CarVendorExtensionCallback callback)
121             throws CarNotConnectedException {
122         synchronized (mLock) {
123             mCallbacks.remove(callback);
124             List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
125             for (CarPropertyConfig c : configs) {
126                 // Register each individual propertyId
127                 mPropertyManager.unregisterListener(mListenerToBase, c.getPropertyId());
128             }
129             if (mCallbacks.isEmpty()) {
130                 mListenerToBase = null;
131             }
132         }
133     }
134 
135     /** Get list of properties represented by CarVendorExtensionManager for this car. */
getProperties()136     public List<CarPropertyConfig> getProperties() throws CarNotConnectedException {
137         return mPropertyManager.getPropertyList();
138     }
139 
140     /**
141      * Check whether a given property is available or disabled based on the cars current state.
142      * @return true if the property is AVAILABLE, false otherwise
143      */
isPropertyAvailable(int propertyId, int area)144     public boolean isPropertyAvailable(int propertyId, int area)
145             throws CarNotConnectedException {
146         return mPropertyManager.isPropertyAvailable(propertyId, area);
147     }
148 
149     /**
150      * Returns property value. Use this function for global vehicle properties.
151      *
152      * @param propertyClass - data type of the given property, for example property that was
153      *        defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
154      *        {@code Integer.class}.
155      * @param propId - property id which is matched with the one defined in vehicle HAL
156      *
157      * @throws CarNotConnectedException if the connection to the car service has been lost.
158      */
getGlobalProperty(Class<E> propertyClass, int propId)159     public <E> E getGlobalProperty(Class<E> propertyClass, int propId)
160             throws CarNotConnectedException {
161         return getProperty(propertyClass, propId, 0 /* area */);
162     }
163 
164     /**
165      * Returns property value. Use this function for "zoned" vehicle properties.
166      *
167      * @param propertyClass - data type of the given property, for example property that was
168      *        defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
169      *        {@code Integer.class}.
170      * @param propId - property id which is matched with the one defined in vehicle HAL
171      * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT}
172      *        or {@code VEHICLE_MIRROR_DRIVER_LEFT}
173      *
174      * @throws CarNotConnectedException if the connection to the car service has been lost.
175      */
getProperty(Class<E> propertyClass, int propId, int area)176     public <E> E getProperty(Class<E> propertyClass, int propId, int area)
177             throws CarNotConnectedException {
178         return mPropertyManager.getProperty(propertyClass, propId, area).getValue();
179     }
180 
181     /**
182      * Call this function to set a value to global vehicle property.
183      *
184      * @param propertyClass - data type of the given property, for example property that was
185      *        defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
186      *        {@code Integer.class}.
187      * @param propId - property id which is matched with the one defined in vehicle HAL
188      * @param value - new value, this object should match a class provided in {@code propertyClass}
189      *        argument.
190      *
191      * @throws CarNotConnectedException if the connection to the car service has been lost.
192      */
setGlobalProperty(Class<E> propertyClass, int propId, E value)193     public <E> void setGlobalProperty(Class<E> propertyClass, int propId, E value)
194             throws CarNotConnectedException {
195         mPropertyManager.setProperty(propertyClass, propId, 0 /* area */, value);
196     }
197 
198     /**
199      * Call this function to set a value to "zoned" vehicle property.
200      *
201      * @param propertyClass - data type of the given property, for example property that was
202      *        defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using
203      *        {@code Integer.class}.
204      * @param propId - property id which is matched with the one defined in vehicle HAL
205      * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT}
206      *        or {@code VEHICLE_MIRROR_DRIVER_LEFT}
207      * @param value - new value, this object should match a class provided in {@code propertyClass}
208      *        argument.
209      *
210      * @throws CarNotConnectedException if the connection to the car service has been lost.
211      */
setProperty(Class<E> propertyClass, int propId, int area, E value)212     public <E> void setProperty(Class<E> propertyClass, int propId, int area, E value)
213             throws CarNotConnectedException {
214         mPropertyManager.setProperty(propertyClass, propId, area, value);
215     }
216 
217     /** @hide */
218     @Override
onCarDisconnected()219     public void onCarDisconnected() {
220         mPropertyManager.onCarDisconnected();
221     }
222     private static class CarPropertyEventListenerToBase implements
223             CarPropertyManager.CarPropertyEventListener {
224         private final WeakReference<CarVendorExtensionManager> mManager;
225 
CarPropertyEventListenerToBase(CarVendorExtensionManager manager)226         CarPropertyEventListenerToBase(CarVendorExtensionManager manager) {
227             mManager = new WeakReference<>(manager);
228         }
229 
230         @Override
onChangeEvent(CarPropertyValue value)231         public void onChangeEvent(CarPropertyValue value) {
232             CarVendorExtensionManager manager = mManager.get();
233             if (manager != null) {
234                 manager.handleOnChangeEvent(value);
235             }
236         }
237 
238         @Override
onErrorEvent(int propertyId, int zone)239         public void onErrorEvent(int propertyId, int zone) {
240             CarVendorExtensionManager manager = mManager.get();
241             if (manager != null) {
242                 manager.handleOnErrorEvent(propertyId, zone);
243             }
244         }
245     }
246 }
247