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