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