/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.car.hardware; import android.annotation.SystemApi; import android.car.Car; import android.car.CarManagerBase; import android.car.hardware.property.CarPropertyManager; import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback; import android.car.hardware.property.ICarProperty; import android.os.IBinder; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * API to access custom vehicle properties defined by OEMs. *

* System permission {@link Car#PERMISSION_VENDOR_EXTENSION} is required to get this manager. *

* @hide * @deprecated consider using {@link CarPropertyManager} instead. */ @Deprecated @SystemApi public final class CarVendorExtensionManager extends CarManagerBase { private static final boolean DBG = false; private static final String TAG = CarVendorExtensionManager.class.getSimpleName(); private final CarPropertyManager mPropertyManager; @GuardedBy("mLock") private final ArraySet mCallbacks = new ArraySet<>(); private final Object mLock = new Object(); @GuardedBy("mLock") private CarPropertyEventListenerToBase mListenerToBase = null; private void handleOnChangeEvent(CarPropertyValue value) { Collection callbacks; synchronized (mLock) { callbacks = new ArrayList<>(mCallbacks); } for (CarVendorExtensionCallback l: callbacks) { l.onChangeEvent(value); } } private void handleOnErrorEvent(int propertyId, int zone) { Collection listeners; synchronized (mLock) { listeners = new ArrayList<>(mCallbacks); } for (CarVendorExtensionCallback l: listeners) { l.onErrorEvent(propertyId, zone); } } /** * Creates an instance of the {@link CarVendorExtensionManager}. * *

Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead. * @hide */ public CarVendorExtensionManager(Car car, IBinder service) { super(car); ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service); mPropertyManager = new CarPropertyManager(car, mCarPropertyService); } /** * Contains callback functions that will be called when some event happens with vehicle * property. */ public interface CarVendorExtensionCallback { /** Called when a property is updated */ void onChangeEvent(CarPropertyValue value); /** Called when an error is detected with a property */ void onErrorEvent(int propertyId, int zone); } /** * Registers listener. The methods of the listener will be called when new events arrived in * the main thread. */ public void registerCallback(CarVendorExtensionCallback callback) { synchronized (mLock) { if (mCallbacks.isEmpty()) { mListenerToBase = new CarPropertyEventListenerToBase(this); } List configs = mPropertyManager.getPropertyList(); for (CarPropertyConfig c : configs) { // Register each individual propertyId mPropertyManager.registerCallback(mListenerToBase, c.getPropertyId(), 0); } mCallbacks.add(callback); } } /** Unregisters listener that was previously registered. */ public void unregisterCallback(CarVendorExtensionCallback callback) { synchronized (mLock) { mCallbacks.remove(callback); List configs = mPropertyManager.getPropertyList(); for (CarPropertyConfig c : configs) { // Register each individual propertyId mPropertyManager.unregisterCallback(mListenerToBase, c.getPropertyId()); } if (mCallbacks.isEmpty()) { mListenerToBase = null; } } } /** Get list of properties represented by CarVendorExtensionManager for this car. */ public List getProperties() { return mPropertyManager.getPropertyList(); } /** * Check whether a given property is available or disabled based on the cars current state. * @return true if the property is AVAILABLE, false otherwise */ public boolean isPropertyAvailable(int propertyId, int area) { return mPropertyManager.isPropertyAvailable(propertyId, area); } /** * Returns property value. Use this function for global vehicle properties. * * @param propertyClass - data type of the given property, for example property that was * defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using * {@code Integer.class}. * @param propId - property id which is matched with the one defined in vehicle HAL */ public E getGlobalProperty(Class propertyClass, int propId) { return getProperty(propertyClass, propId, 0 /* area */); } /** * Returns property value. Use this function for "zoned" vehicle properties. * * @param propertyClass - data type of the given property, for example property that was * defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using * {@code Integer.class}. * @param propId - property id which is matched with the one defined in vehicle HAL * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT} * or {@code VEHICLE_MIRROR_DRIVER_LEFT} */ public E getProperty(Class propertyClass, int propId, int area) { return mPropertyManager.getProperty(propertyClass, propId, area).getValue(); } /** * Call this function to set a value to global vehicle property. * * @param propertyClass - data type of the given property, for example property that was * defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using * {@code Integer.class}. * @param propId - property id which is matched with the one defined in vehicle HAL * @param value - new value, this object should match a class provided in {@code propertyClass} * argument. */ public void setGlobalProperty(Class propertyClass, int propId, E value) { mPropertyManager.setProperty(propertyClass, propId, 0 /* area */, value); } /** * Call this function to set a value to "zoned" vehicle property. * * @param propertyClass - data type of the given property, for example property that was * defined as {@code VEHICLE_VALUE_TYPE_INT32} in vehicle HAL could be accessed using * {@code Integer.class}. * @param propId - property id which is matched with the one defined in vehicle HAL * @param area - vehicle area (e.g. {@code VehicleAreaSeat.ROW_1_LEFT} * or {@code VEHICLE_MIRROR_DRIVER_LEFT} * @param value - new value, this object should match a class provided in {@code propertyClass} * argument. */ public void setProperty(Class propertyClass, int propId, int area, E value) { mPropertyManager.setProperty(propertyClass, propId, area, value); } /** @hide */ @Override public void onCarDisconnected() { synchronized (mLock) { mCallbacks.clear(); } mPropertyManager.onCarDisconnected(); } private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback { private final WeakReference mManager; CarPropertyEventListenerToBase(CarVendorExtensionManager manager) { mManager = new WeakReference<>(manager); } @Override public void onChangeEvent(CarPropertyValue value) { CarVendorExtensionManager manager = mManager.get(); if (manager != null) { manager.handleOnChangeEvent(value); } } @Override public void onErrorEvent(int propertyId, int zone) { CarVendorExtensionManager manager = mManager.get(); if (manager != null) { manager.handleOnErrorEvent(propertyId, zone); } } } }