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