PropertyHalServiceBase.java revision 79d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7b
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 */
16package com.android.car.hal;
17
18import static com.android.car.hal.CarPropertyUtils.toCarPropertyValue;
19import static com.android.car.hal.CarPropertyUtils.toVehiclePropValue;
20import static java.lang.Integer.toHexString;
21
22import android.annotation.Nullable;
23import android.car.hardware.CarPropertyConfig;
24import android.car.hardware.CarPropertyValue;
25import android.car.hardware.property.CarPropertyEvent;
26import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
27import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
28import android.util.Log;
29
30import com.android.car.CarLog;
31import com.android.internal.annotations.GuardedBy;
32
33import java.io.PrintWriter;
34import java.util.ArrayList;
35import java.util.Collection;
36import java.util.LinkedList;
37import java.util.List;
38import java.util.concurrent.ConcurrentHashMap;
39
40/**
41 * Common interface for HAL services that send Vehicle Properties back and forth via ICarProperty.
42 * Services that communicate by passing vehicle properties back and forth via ICarProperty should
43 * extend this class.
44 */
45public abstract class PropertyHalServiceBase extends HalServiceBase {
46    private final boolean mDbg;
47    private final ConcurrentHashMap<Integer, CarPropertyConfig<?>> mProps =
48            new ConcurrentHashMap<>();
49    private final String mTag;
50    private final VehicleHal mVehicleHal;
51
52    @GuardedBy("mLock")
53    private PropertyHalListener mListener;
54    private final Object mLock = new Object();
55
56    public interface PropertyHalListener {
57        void onPropertyChange(CarPropertyEvent event);
58        void onPropertySetError(int property, int area);
59    }
60
61    protected PropertyHalServiceBase(VehicleHal vehicleHal, String tag, boolean dbg) {
62        mVehicleHal = vehicleHal;
63        mTag = "PropertyHalServiceBase." + tag;
64        mDbg = dbg;
65
66        if (mDbg) {
67            Log.d(mTag, "started PropertyHalServiceBase!");
68        }
69    }
70
71    public void setListener(PropertyHalListener listener) {
72        synchronized (mLock) {
73            mListener = listener;
74        }
75    }
76
77    public List<CarPropertyConfig> getPropertyList() {
78        return new ArrayList<>(mProps.values());
79    }
80
81    /**
82     * Returns property or null if property is not ready yet.
83     */
84    @Nullable
85    public CarPropertyValue getProperty(int mgrPropId, int areaId) {
86        int halPropId = managerToHalPropId(mgrPropId);
87        if (halPropId == NOT_SUPPORTED_PROPERTY) {
88            throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
89        }
90
91        VehiclePropValue value = null;
92        try {
93            value = mVehicleHal.get(halPropId, areaId);
94        } catch (PropertyTimeoutException e) {
95            Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
96        }
97
98        return value == null ? null : toCarPropertyValue(value, mgrPropId);
99    }
100
101    public void setProperty(CarPropertyValue prop) {
102        int halPropId = managerToHalPropId(prop.getPropertyId());
103        if (halPropId == NOT_SUPPORTED_PROPERTY) {
104            throw new IllegalArgumentException("Invalid property Id : 0x"
105                    + toHexString(prop.getPropertyId()));
106        }
107        VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
108        try {
109            mVehicleHal.set(halProp);
110        } catch (PropertyTimeoutException e) {
111            Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
112            throw new RuntimeException(e);
113        }
114    }
115
116    @Override
117    public void init() {
118        if (mDbg) {
119            Log.d(mTag, "init()");
120        }
121        // Subscribe to each of the properties
122        for (Integer prop : mProps.keySet()) {
123            mVehicleHal.subscribeProperty(this, prop);
124        }
125    }
126
127    @Override
128    public void release() {
129        if (mDbg) {
130            Log.d(mTag, "release()");
131        }
132
133        for (Integer prop : mProps.keySet()) {
134            mVehicleHal.unsubscribeProperty(this, prop);
135        }
136
137        // Clear the property list
138        mProps.clear();
139
140        synchronized (mLock) {
141            mListener = null;
142        }
143    }
144
145    @Override
146    public Collection<VehiclePropConfig> takeSupportedProperties(
147            Collection<VehiclePropConfig> allProperties) {
148        List<VehiclePropConfig> taken = new LinkedList<>();
149
150        for (VehiclePropConfig p : allProperties) {
151            int mgrPropId = halToManagerPropId(p.prop);
152
153            if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
154                continue;  // The property is not handled by this HAL.
155            }
156
157            CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, mgrPropId);
158
159            taken.add(p);
160            mProps.put(p.prop, config);
161
162            if (mDbg) {
163                Log.d(mTag, "takeSupportedProperties: " + toHexString(p.prop));
164            }
165        }
166        return taken;
167    }
168
169    @Override
170    public void handleHalEvents(List<VehiclePropValue> values) {
171        PropertyHalListener listener;
172        synchronized (mLock) {
173            listener = mListener;
174        }
175        if (listener != null) {
176            for (VehiclePropValue v : values) {
177                int prop = v.prop;
178                int mgrPropId = halToManagerPropId(prop);
179
180                if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
181                    Log.e(mTag, "Property is not supported: 0x" + toHexString(prop));
182                    continue;
183                }
184
185                CarPropertyEvent event;
186                CarPropertyValue<?> propVal = toCarPropertyValue(v, mgrPropId);
187                event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE,
188                        propVal);
189
190                listener.onPropertyChange(event);
191                if (mDbg) {
192                    Log.d(mTag, "handleHalEvents event: " + event);
193                }
194            }
195        }
196    }
197
198    @Override
199    public void handlePropertySetError(int property, int area) {
200        PropertyHalListener listener;
201        synchronized (mLock) {
202            listener = mListener;
203        }
204        if (listener != null) {
205            listener.onPropertySetError(property, area);
206        }
207    }
208
209    @Override
210    public void dump(PrintWriter writer) {
211        writer.println(mTag);
212        writer.println("  Properties available:");
213        for (CarPropertyConfig prop : mProps.values()) {
214            writer.println("    " + prop.toString());
215        }
216    }
217
218    /**
219     * Converts manager property ID to Vehicle HAL property ID.
220     * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
221     */
222    abstract protected int managerToHalPropId(int managerPropId);
223
224    /**
225     * Converts Vehicle HAL property ID to manager property ID.
226     * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
227     */
228    abstract protected int halToManagerPropId(int halPropId);
229}
230