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