blob: ce2831c6f08860942b0f4f3bc3a3a742a6c79886 [file] [log] [blame]
/*
* 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.CarNotConnectedException;
import android.car.hardware.property.CarPropertyManager;
import android.os.Handler;
import android.os.IBinder;
import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.List;
/**
* API to access custom vehicle properties defined by OEMs.
* <p>
* System permission {@link Car#PERMISSION_VENDOR_EXTENSION} is required to get this manager.
* </p>
* @hide
*/
@SystemApi
public final class CarVendorExtensionManager implements CarManagerBase {
private final static boolean DBG = false;
private final static String TAG = CarVendorExtensionManager.class.getSimpleName();
private final CarPropertyManager mPropertyManager;
private CarPropertyEventListenerToBase mListenerToBase = null;
@GuardedBy("mLock")
private final ArraySet<CarVendorExtensionCallback> mCallbacks = new ArraySet<>();
private final Object mLock = new Object();
private static class CarPropertyEventListenerToBase implements
CarPropertyManager.CarPropertyEventListener{
private final WeakReference<CarVendorExtensionManager> 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);
}
}
}
private void handleOnChangeEvent(CarPropertyValue value) {
Collection<CarVendorExtensionCallback> callbacks;
synchronized (this) {
callbacks = new ArraySet<>(mCallbacks);
}
for (CarVendorExtensionCallback l: callbacks) {
l.onChangeEvent(value);
}
}
private void handleOnErrorEvent(int propertyId, int zone) {
Collection<CarVendorExtensionCallback> listeners;
synchronized (this) {
listeners = new ArraySet<>(mCallbacks);
}
if (!listeners.isEmpty()) {
for (CarVendorExtensionCallback l: listeners) {
l.onErrorEvent(propertyId, zone);
}
}
}
/**
* Creates an instance of the {@link CarVendorExtensionManager}.
*
* <p>Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead.
* @hide
*/
public CarVendorExtensionManager(IBinder service, Handler handler) {
mPropertyManager = new CarPropertyManager(service, handler, DBG, TAG);
}
/**
* 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)
throws CarNotConnectedException {
synchronized (mLock) {
if (mCallbacks.isEmpty()) {
mListenerToBase = new CarPropertyEventListenerToBase(this);
}
List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
for (CarPropertyConfig c : configs) {
// Register each individual propertyId
mPropertyManager.registerListener(mListenerToBase, c.getPropertyId(), 0);
}
mCallbacks.add(callback);
}
}
/** Unregisters listener that was previously registered. */
public void unregisterCallback(CarVendorExtensionCallback callback)
throws CarNotConnectedException {
synchronized (mLock) {
mCallbacks.remove(callback);
List<CarPropertyConfig> configs = mPropertyManager.getPropertyList();
for (CarPropertyConfig c : configs) {
// Register each individual propertyId
mPropertyManager.unregisterListener(mListenerToBase, c.getPropertyId());
}
if (mCallbacks.isEmpty()) {
mListenerToBase = null;
}
}
}
/** Get list of properties represented by CarVendorExtensionManager for this car. */
public List<CarPropertyConfig> getProperties() throws CarNotConnectedException {
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)
throws CarNotConnectedException {
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
*
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public <E> E getGlobalProperty(Class<E> propertyClass, int propId)
throws CarNotConnectedException {
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}
*
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public <E> E getProperty(Class<E> propertyClass, int propId, int area)
throws CarNotConnectedException {
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.
*
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public <E> void setGlobalProperty(Class<E> propertyClass, int propId, E value)
throws CarNotConnectedException {
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.
*
* @throws CarNotConnectedException if the connection to the car service has been lost.
*/
public <E> void setProperty(Class<E> propertyClass, int propId, int area, E value)
throws CarNotConnectedException {
mPropertyManager.setProperty(propertyClass, propId, area, value);
}
/** @hide */
@Override
public void onCarDisconnected() {
mPropertyManager.onCarDisconnected();
}
}