Home | History | Annotate | Download | only in hardware
      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 
     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 
     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      */
     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 */
     93         void onChangeEvent(CarPropertyValue value);
     94 
     95         /** Called when an error is detected with a property */
     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      */
    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. */
    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. */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    219     public void onCarDisconnected() {
    220         mPropertyManager.onCarDisconnected();
    221     }
    222     private static class CarPropertyEventListenerToBase implements
    223             CarPropertyManager.CarPropertyEventListener {
    224         private final WeakReference<CarVendorExtensionManager> mManager;
    225 
    226         CarPropertyEventListenerToBase(CarVendorExtensionManager manager) {
    227             mManager = new WeakReference<>(manager);
    228         }
    229 
    230         @Override
    231         public void onChangeEvent(CarPropertyValue value) {
    232             CarVendorExtensionManager manager = mManager.get();
    233             if (manager != null) {
    234                 manager.handleOnChangeEvent(value);
    235             }
    236         }
    237 
    238         @Override
    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