• 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 boolean mIsEvsServiceRequestSupported;
64 
EvsHalService(VehicleHal hal)65     public EvsHalService(VehicleHal hal) {
66         mHal = hal;
67     }
68 
69     /**
70      * Interface to be implemented by any client that wants to get notified upon a new EVS service
71      * request.
72      */
73     public interface EvsHalEventListener {
74         /** Called when a value of monitoring VHAL property gets changed */
onEvent(@arEvsServiceType int id, boolean on)75         void onEvent(@CarEvsServiceType int id, boolean on);
76     }
77 
78     /**
79      * Sets the event listener to receive Vehicle's EVS-related events.
80      *
81      * @param listener {@link EvsHalEventListener}
82      * @throws {@link IllegalStateException} if none of required VHAL properties are not supported
83      *         on this device.
84      */
setListener(EvsHalEventListener listener)85     public void setListener(EvsHalEventListener listener) {
86         if (!mIsEvsServiceRequestSupported) {
87             throw new IllegalStateException(
88                     "Any of required VHAL properties are not supported.");
89         }
90 
91         synchronized (mLock) {
92             mListener = listener;
93         }
94 
95         mHal.subscribeProperty(this, EVS_SERVICE_REQUEST);
96     }
97 
98     /** Returns whether {@code EVS_SERVICE_REQUEST} is supported */
isEvsServiceRequestSupported()99     public boolean isEvsServiceRequestSupported() {
100         return mIsEvsServiceRequestSupported;
101     }
102 
103     @Override
init()104     public void init() {
105         synchronized (mLock) {
106             for (int i = 0; i < mProperties.size(); i++) {
107                 HalPropConfig config = mProperties.valueAt(i);
108                 if (VehicleHal.isPropertySubscribable(config)) {
109                     mHal.subscribeProperty(this, config.getPropId());
110                 }
111             }
112         }
113     }
114 
115     @Override
release()116     public void release() {
117         synchronized (mLock) {
118             mListener = null;
119             mProperties.clear();
120         }
121     }
122 
123     @Override
getAllSupportedProperties()124     public int[] getAllSupportedProperties() {
125         return SUPPORTED_PROPERTIES;
126     }
127 
128     @Override
takeProperties(Collection<HalPropConfig> configs)129     public void takeProperties(Collection<HalPropConfig> configs) {
130         if (configs.isEmpty()) {
131             return;
132         }
133 
134         synchronized (mLock) {
135             for (HalPropConfig config : configs) {
136                 mProperties.put(config.getPropId(), config);
137             }
138 
139             mIsEvsServiceRequestSupported = mProperties.contains(EVS_SERVICE_REQUEST);
140         }
141     }
142 
143     @Override
onHalEvents(List<HalPropValue> values)144     public void onHalEvents(List<HalPropValue> values) {
145         EvsHalEventListener listener;
146         synchronized (mLock) {
147             listener = mListener;
148         }
149 
150         if (listener == null) {
151             Slogf.w(TAG, "EVS Hal event occurs while the listener is null.");
152             return;
153         }
154 
155         dispatchHalEvents(values, listener);
156     }
157 
dispatchHalEvents(List<HalPropValue> values, EvsHalEventListener listener)158     private void dispatchHalEvents(List<HalPropValue> values, EvsHalEventListener listener) {
159         for (int i = 0; i < values.size(); ++i) {
160             HalPropValue v = values.get(i);
161             boolean on = false;
162             @CarEvsServiceType int type;
163             switch (v.getPropId()) {
164                 case EVS_SERVICE_REQUEST:
165                     // Check
166                     // android.hardware.automotive.vehicle.VehicleProperty.EVS_SERVICE_REQUEST
167                     try {
168                         int rawServiceType = v.getInt32Value(EvsServiceRequestIndex.TYPE);
169                         type = rawServiceType == EvsServiceType.REARVIEW
170                                 ? SERVICE_TYPE_REARVIEW : SERVICE_TYPE_SURROUNDVIEW;
171                         on = v.getInt32Value(EvsServiceRequestIndex.STATE) == EvsServiceState.ON;
172                         if (DBG) {
173                             Slogf.d(TAG,
174                                     "Received EVS_SERVICE_REQUEST: type = " + type + " on = " + on);
175                         }
176                     } catch (IndexOutOfBoundsException e) {
177                         Slogf.e(TAG, "Received invalid EVS_SERVICE_REQUEST, missing type or state,"
178                                 + " int32Values: " + v.dumpInt32Values());
179                         break;
180                     }
181                     listener.onEvent(type, on);
182                     break;
183 
184                 default:
185                     if (DBG) {
186                         Slogf.d(TAG, "Received unknown property change: " + v);
187                     }
188                     break;
189             }
190         }
191     }
192 
193     @Override
194     @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
dump(PrintWriter writer)195     public void dump(PrintWriter writer) {
196         writer.println("*EVSHALSERVICE*");
197         writer.printf("Use EVS_SERVICE_REQUEST: %b\n", isEvsServiceRequestSupported());
198     }
199 }
200