• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 com.android.car.hal;
18 
19 import static android.car.evs.CarEvsManager.SERVICE_TYPE_REARVIEW;
20 import static android.car.evs.CarEvsManager.SERVICE_TYPE_SURROUNDVIEW;
21 import static android.hardware.automotive.vehicle.VehicleProperty.EVS_SERVICE_REQUEST;
22 
23 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
24 
25 import android.car.builtin.util.Slogf;
26 import android.car.evs.CarEvsManager.CarEvsServiceType;
27 import android.hardware.automotive.vehicle.EvsServiceRequestIndex;
28 import android.hardware.automotive.vehicle.EvsServiceState;
29 import android.hardware.automotive.vehicle.EvsServiceType;
30 import android.util.Log;
31 import android.util.SparseArray;
32 
33 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
34 import com.android.internal.annotations.GuardedBy;
35 
36 import java.io.PrintWriter;
37 import java.util.Collection;
38 import java.util.List;
39 
40 /*
41  * Translates HAL events, CarEvsService is interested in, into the higher-level semantic
42  * information.
43  */
44 public class EvsHalService extends HalServiceBase {
45 
46     private static final String TAG = EvsHalService.class.getSimpleName();
47     private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG);
48 
49     private static final int[] SUPPORTED_PROPERTIES = new int[] {
50         EVS_SERVICE_REQUEST,
51     };
52 
53     private final Object mLock = new Object();
54 
55     @GuardedBy("mLock")
56     private final SparseArray<HalPropConfig> mProperties = new SparseArray();
57 
58     private final VehicleHal mHal;
59 
60     @GuardedBy("mLock")
61     private EvsHalEventListener mListener;
62 
63     private @CarEvsServiceType int mLastServiceTypeRequested;
64 
65     private boolean mIsEvsServiceRequestSupported;
66 
EvsHalService(VehicleHal hal)67     public EvsHalService(VehicleHal hal) {
68         mHal = hal;
69     }
70 
71     /**
72      * Interface to be implemented by any client that wants to get notified upon a new EVS service
73      * request.
74      */
75     public interface EvsHalEventListener {
76         /** Called when a value of monitoring VHAL property gets changed */
onEvent(@arEvsServiceType int id, boolean on)77         void onEvent(@CarEvsServiceType int id, boolean on);
78     }
79 
80     /**
81      * Sets the event listener to receive Vehicle's EVS-related events.
82      *
83      * @param listener {@link EvsHalEventListener}
84      * @throws {@link IllegalStateException} if none of required VHAL properties are not supported
85      *         on this device.
86      */
setListener(EvsHalEventListener listener)87     public void setListener(EvsHalEventListener listener) {
88         if (!mIsEvsServiceRequestSupported) {
89             throw new IllegalStateException(
90                     "Any of required VHAL properties are not supported.");
91         }
92 
93         synchronized (mLock) {
94             mListener = listener;
95         }
96 
97         mHal.subscribeProperty(this, EVS_SERVICE_REQUEST);
98     }
99 
100     /** Returns whether {@code EVS_SERVICE_REQUEST} is supported */
isEvsServiceRequestSupported()101     public boolean isEvsServiceRequestSupported() {
102         return mIsEvsServiceRequestSupported;
103     }
104 
105     @Override
init()106     public void init() {
107         synchronized (mLock) {
108             for (int i = 0; i < mProperties.size(); i++) {
109                 HalPropConfig config = mProperties.valueAt(i);
110                 if (VehicleHal.isPropertySubscribable(config)) {
111                     mHal.subscribeProperty(this, config.getPropId());
112                 }
113             }
114         }
115     }
116 
117     @Override
release()118     public void release() {
119         synchronized (mLock) {
120             mListener = null;
121             mProperties.clear();
122         }
123     }
124 
125     @Override
getAllSupportedProperties()126     public int[] getAllSupportedProperties() {
127         return SUPPORTED_PROPERTIES;
128     }
129 
130     @Override
takeProperties(Collection<HalPropConfig> configs)131     public void takeProperties(Collection<HalPropConfig> configs) {
132         if (configs.isEmpty()) {
133             return;
134         }
135 
136         synchronized (mLock) {
137             for (HalPropConfig config : configs) {
138                 mProperties.put(config.getPropId(), config);
139             }
140 
141             mIsEvsServiceRequestSupported = mProperties.contains(EVS_SERVICE_REQUEST);
142         }
143     }
144 
145     @Override
onHalEvents(List<HalPropValue> values)146     public void onHalEvents(List<HalPropValue> values) {
147         EvsHalEventListener listener;
148         synchronized (mLock) {
149             listener = mListener;
150         }
151 
152         if (listener == null) {
153             Slogf.w(TAG, "EVS Hal event occurs while the listener is null.");
154             return;
155         }
156 
157         dispatchHalEvents(values, listener);
158     }
159 
dispatchHalEvents(List<HalPropValue> values, EvsHalEventListener listener)160     private void dispatchHalEvents(List<HalPropValue> values, EvsHalEventListener listener) {
161         for (int i = 0; i < values.size(); ++i) {
162             HalPropValue v = values.get(i);
163             boolean on = false;
164             @CarEvsServiceType int type;
165             switch (v.getPropId()) {
166                 case EVS_SERVICE_REQUEST:
167                     // Check
168                     // android.hardware.automotive.vehicle.VehicleProperty.EVS_SERVICE_REQUEST
169                     try {
170                         int rawServiceType = v.getInt32Value(EvsServiceRequestIndex.TYPE);
171                         type = rawServiceType == EvsServiceType.REARVIEW
172                                 ? SERVICE_TYPE_REARVIEW : SERVICE_TYPE_SURROUNDVIEW;
173                         on = v.getInt32Value(EvsServiceRequestIndex.STATE) == EvsServiceState.ON;
174                         if (DBG) {
175                             Slogf.d(TAG,
176                                     "Received EVS_SERVICE_REQUEST: type = " + type + " on = " + on);
177                         }
178                     } catch (IndexOutOfBoundsException e) {
179                         Slogf.e(TAG, "Received invalid EVS_SERVICE_REQUEST, missing type or state,"
180                                 + " int32Values: " + v.dumpInt32Values());
181                         break;
182                     }
183                     listener.onEvent(type, on);
184                     break;
185 
186                 default:
187                     if (DBG) {
188                         Slogf.d(TAG, "Received unknown property change: " + v);
189                     }
190                     break;
191             }
192         }
193     }
194 
195     @Override
196     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(PrintWriter writer)197     public void dump(PrintWriter writer) {
198         writer.println("*EVSHALSERVICE*");
199         writer.printf("Use EVS_SERVICE_REQUEST: %b\n", isEvsServiceRequestSupported());
200     }
201 }
202