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; 18 19 import android.annotation.Nullable; 20 import android.car.builtin.os.BuildHelper; 21 import android.car.builtin.util.Slogf; 22 import android.car.hardware.CarPropertyValue; 23 import android.hardware.automotive.vehicle.RawPropValues; 24 import android.hardware.automotive.vehicle.SubscribeOptions; 25 import android.os.IBinder.DeathRecipient; 26 import android.os.RemoteException; 27 import android.os.ServiceSpecificException; 28 29 import com.android.car.hal.HalAreaConfig; 30 import com.android.car.hal.HalPropConfig; 31 import com.android.car.hal.HalPropValue; 32 import com.android.car.hal.HalPropValueBuilder; 33 import com.android.car.hal.VehicleHalCallback; 34 import com.android.car.hal.fakevhal.FakeVehicleStub; 35 import com.android.car.internal.property.CarPropertyErrorCodes; 36 import com.android.car.internal.property.CarPropertyErrorCodes.CarPropMgrErrorCode; 37 import com.android.car.internal.property.PropIdAreaId; 38 39 import java.io.FileDescriptor; 40 import java.util.List; 41 42 /** 43 * VehicleStub represents an IVehicle service interface in either AIDL or legacy HIDL version. It 44 * exposes common interface so that the client does not need to care about which version the 45 * underlying IVehicle service is in. 46 */ 47 public abstract class VehicleStub { 48 49 /** 50 * SubscriptionClient represents a client that could subscribe/unsubscribe to properties. 51 */ 52 public interface SubscriptionClient { 53 /** 54 * Subscribes to a property. 55 * 56 * @param options The list of subscribe options. 57 * @throws RemoteException if the remote operation fails. 58 * @throws ServiceSpecificException if VHAL returns service specific error. 59 */ subscribe(SubscribeOptions[] options)60 void subscribe(SubscribeOptions[] options) throws RemoteException, ServiceSpecificException; 61 62 /** 63 * Unsubscribes from a property. 64 * 65 * @param prop The ID for the property to unsubscribe. 66 * @throws RemoteException if the remote operation fails. 67 * @throws ServiceSpecificException if VHAL returns service specific error. 68 */ unsubscribe(int prop)69 void unsubscribe(int prop) throws RemoteException, ServiceSpecificException; 70 71 /** 72 * Registers the callback to be called when the min/max supported value or supportd values 73 * list change for the [propId, areaId]s. 74 * 75 * @throws ServiceSpecificException If VHAL returns error or VHAL connection fails. 76 */ registerSupportedValuesChange(List<PropIdAreaId> propIdAreaIds)77 void registerSupportedValuesChange(List<PropIdAreaId> propIdAreaIds); 78 79 /** 80 * Unregisters the [propId, areaId]s previously registered with 81 * registerSupportedValuesChange. 82 * 83 * Do nothing if the [propId, areaId]s were not previously registered. 84 * 85 * This operation is always assumed succeeded. 86 */ unregisterSupportedValuesChange(List<PropIdAreaId> propIdAreaIds)87 void unregisterSupportedValuesChange(List<PropIdAreaId> propIdAreaIds); 88 } 89 90 /** 91 * A request for {@link VehicleStub#getAsync} or {@link VehicleStub#setAsync}. 92 */ 93 public static class AsyncGetSetRequest { 94 private final int mServiceRequestId; 95 private final HalPropValue mHalPropValue; 96 private final long mTimeoutUptimeMs; 97 getServiceRequestId()98 public int getServiceRequestId() { 99 return mServiceRequestId; 100 } 101 getHalPropValue()102 public HalPropValue getHalPropValue() { 103 return mHalPropValue; 104 } 105 getTimeoutUptimeMs()106 public long getTimeoutUptimeMs() { 107 return mTimeoutUptimeMs; 108 } 109 110 /** 111 * Get an instance for AsyncGetSetRequest. 112 */ AsyncGetSetRequest(int serviceRequestId, HalPropValue halPropValue, long timeoutUptimeMs)113 public AsyncGetSetRequest(int serviceRequestId, HalPropValue halPropValue, 114 long timeoutUptimeMs) { 115 mServiceRequestId = serviceRequestId; 116 mHalPropValue = halPropValue; 117 mTimeoutUptimeMs = timeoutUptimeMs; 118 } 119 } 120 121 /** 122 * A result for {@link VehicleStub#getAsync}. 123 */ 124 public static final class GetVehicleStubAsyncResult { 125 private final int mServiceRequestId; 126 @Nullable 127 private final HalPropValue mHalPropValue; 128 private final CarPropertyErrorCodes mCarPropertyErrorCodes; 129 getServiceRequestId()130 public int getServiceRequestId() { 131 return mServiceRequestId; 132 } 133 134 @Nullable getHalPropValue()135 public HalPropValue getHalPropValue() { 136 return mHalPropValue; 137 } 138 getCarPropertyErrorCodes()139 public CarPropertyErrorCodes getCarPropertyErrorCodes() { 140 return mCarPropertyErrorCodes; 141 } 142 143 /** 144 * Constructs an instance for GetVehicleStubAsyncResult when result returned successfully. 145 */ GetVehicleStubAsyncResult(int serviceRequestId, HalPropValue halPropValue)146 public GetVehicleStubAsyncResult(int serviceRequestId, HalPropValue halPropValue) { 147 mServiceRequestId = serviceRequestId; 148 mHalPropValue = halPropValue; 149 mCarPropertyErrorCodes = CarPropertyErrorCodes.STATUS_OK_NO_ERROR; 150 } 151 152 /** 153 * Constructs an instance for GetVehicleStubAsyncResult when errors. 154 */ GetVehicleStubAsyncResult(int serviceRequestId, CarPropertyErrorCodes errorCodes)155 public GetVehicleStubAsyncResult(int serviceRequestId, CarPropertyErrorCodes errorCodes) { 156 mServiceRequestId = serviceRequestId; 157 mHalPropValue = null; 158 mCarPropertyErrorCodes = errorCodes; 159 } 160 } 161 162 /** 163 * A result for {@link VehicleStub#setAsync}. 164 */ 165 public static final class SetVehicleStubAsyncResult { 166 private final int mServiceRequestId; 167 @CarPropMgrErrorCode 168 private final CarPropertyErrorCodes mCarPropertyErrorCodes; 169 getServiceRequestId()170 public int getServiceRequestId() { 171 return mServiceRequestId; 172 } 173 getCarPropertyErrorCodes()174 public CarPropertyErrorCodes getCarPropertyErrorCodes() { 175 return mCarPropertyErrorCodes; 176 } 177 178 /** 179 * Constructs an success result. 180 */ SetVehicleStubAsyncResult(int serviceRequestId)181 public SetVehicleStubAsyncResult(int serviceRequestId) { 182 mServiceRequestId = serviceRequestId; 183 mCarPropertyErrorCodes = CarPropertyErrorCodes.STATUS_OK_NO_ERROR; 184 } 185 186 /** 187 * Constructs an instance for SetVehicleStubAsyncResult when errors. 188 */ SetVehicleStubAsyncResult(int serviceRequestId, CarPropertyErrorCodes errorCodes)189 public SetVehicleStubAsyncResult(int serviceRequestId, CarPropertyErrorCodes errorCodes) { 190 mServiceRequestId = serviceRequestId; 191 mCarPropertyErrorCodes = errorCodes; 192 } 193 } 194 195 /** 196 * A callback for asynchronous operations. 197 */ 198 public abstract static class VehicleStubCallbackInterface { 199 /** 200 * Method called when {@link getAsync} returns results. 201 */ onGetAsyncResults( List<GetVehicleStubAsyncResult> getVehicleStubAsyncResults)202 public abstract void onGetAsyncResults( 203 List<GetVehicleStubAsyncResult> getVehicleStubAsyncResults); 204 205 /** 206 * Method called when {@link setAsync} returns results. 207 */ onSetAsyncResults( List<SetVehicleStubAsyncResult> setVehicleStubAsyncResults)208 public abstract void onSetAsyncResults( 209 List<SetVehicleStubAsyncResult> setVehicleStubAsyncResults); 210 211 /** 212 * Register a callback that will be called when the callback binder died. 213 */ linkToDeath(DeathRecipient recipient)214 public abstract void linkToDeath(DeathRecipient recipient) throws RemoteException; 215 216 /** 217 * Method called when async requests timed-out. 218 * 219 * If the callback's binder is already dead, this function will not be called. 220 */ onRequestsTimeout(List<Integer> serviceRequestIds)221 public abstract void onRequestsTimeout(List<Integer> serviceRequestIds); 222 } 223 224 /** 225 * Gets a property asynchronously. 226 */ getAsync(List<AsyncGetSetRequest> getVehicleStubAsyncRequests, VehicleStubCallbackInterface getVehicleStubAsyncCallback)227 public abstract void getAsync(List<AsyncGetSetRequest> getVehicleStubAsyncRequests, 228 VehicleStubCallbackInterface getVehicleStubAsyncCallback); 229 230 /** 231 * Sets a property asynchronously. 232 */ setAsync(List<AsyncGetSetRequest> setVehicleStubAsyncRequests, VehicleStubCallbackInterface setVehicleStubAsyncCallback)233 public abstract void setAsync(List<AsyncGetSetRequest> setVehicleStubAsyncRequests, 234 VehicleStubCallbackInterface setVehicleStubAsyncCallback); 235 236 /** 237 * Checks whether we are connected to AIDL VHAL: {@code true} or HIDL VHAL: {@code false}. 238 */ isAidlVhal()239 public abstract boolean isAidlVhal(); 240 241 /** 242 * Creates a new VehicleStub to connect to Vehicle HAL. 243 * 244 * Create a new VehicleStub to connect to Vehicle HAL according to which backend (AIDL or HIDL) 245 * is available. This function will throw {@link IllegalStateException} if no vehicle HAL is 246 * available. 247 * 248 * @return a vehicle stub to connect to Vehicle HAL. 249 */ newVehicleStub()250 public static VehicleStub newVehicleStub() throws IllegalStateException { 251 VehicleStub stub = new AidlVehicleStub(); 252 if (stub.isValid()) { 253 if ((BuildHelper.isUserDebugBuild() || BuildHelper.isEngBuild()) 254 && FakeVehicleStub.doesEnableFileExist()) { 255 try { 256 return new FakeVehicleStub(stub); 257 } catch (Exception e) { 258 Slogf.e(CarLog.TAG_SERVICE, e, "Failed to create FakeVehicleStub. " 259 + "Fallback to using real VehicleStub."); 260 } 261 } 262 return stub; 263 } 264 265 Slogf.i(CarLog.TAG_SERVICE, "No AIDL vehicle HAL found, fall back to HIDL version"); 266 267 stub = new HidlVehicleStub(); 268 269 if (!stub.isValid()) { 270 throw new IllegalStateException("Vehicle HAL service is not available."); 271 } 272 273 return stub; 274 } 275 276 /** 277 * Gets a HalPropValueBuilder that could be used to build a HalPropValue. 278 * 279 * @return a builder to build HalPropValue. 280 */ getHalPropValueBuilder()281 public abstract HalPropValueBuilder getHalPropValueBuilder(); 282 283 /** 284 * Returns whether this vehicle stub is connecting to a valid vehicle HAL. 285 * 286 * @return Whether this vehicle stub is connecting to a valid vehicle HAL. 287 */ isValid()288 public abstract boolean isValid(); 289 290 /** 291 * Gets the interface descriptor for the connecting vehicle HAL. 292 * 293 * @return the interface descriptor. 294 * @throws IllegalStateException If unable to get the descriptor. 295 */ getInterfaceDescriptor()296 public abstract String getInterfaceDescriptor() throws IllegalStateException; 297 298 /** 299 * Registers a death recipient that would be called when vehicle HAL died. 300 * 301 * @param recipient A death recipient. 302 * @throws IllegalStateException If unable to register the death recipient. 303 */ linkToDeath(IVehicleDeathRecipient recipient)304 public abstract void linkToDeath(IVehicleDeathRecipient recipient) throws IllegalStateException; 305 306 /** 307 * Unlinks a previously linked death recipient. 308 * 309 * @param recipient A previously linked death recipient. 310 */ unlinkToDeath(IVehicleDeathRecipient recipient)311 public abstract void unlinkToDeath(IVehicleDeathRecipient recipient); 312 313 /** 314 * Gets all property configs. 315 * 316 * @return All the property configs. 317 * @throws RemoteException if the remote operation fails. 318 * @throws ServiceSpecificException if VHAL returns service specific error. 319 */ getAllPropConfigs()320 public abstract HalPropConfig[] getAllPropConfigs() 321 throws RemoteException, ServiceSpecificException; 322 323 /** 324 * Gets a new {@code SubscriptionClient} that could be used to subscribe/unsubscribe. 325 * 326 * Caller MUST unsubscribe all subscribed properties before discarding the client to prevent 327 * resource leak. 328 * 329 * @param callback A callback that could be used to receive events. 330 * @return a {@code SubscriptionClient} that could be used to subscribe/unsubscribe. 331 */ newSubscriptionClient(VehicleHalCallback callback)332 public abstract SubscriptionClient newSubscriptionClient(VehicleHalCallback callback); 333 334 /** 335 * Gets a property. 336 * 337 * @param requestedPropValue The property to get. 338 * @return The vehicle property value. 339 * @throws RemoteException if the remote operation fails. 340 * @throws ServiceSpecificException if VHAL returns service specific error. 341 */ 342 @Nullable get(HalPropValue requestedPropValue)343 public abstract HalPropValue get(HalPropValue requestedPropValue) 344 throws RemoteException, ServiceSpecificException; 345 346 /** 347 * Sets a property. 348 * 349 * @param propValue The property to set. 350 * @throws RemoteException if the remote operation fails. 351 * @throws ServiceSpecificException if VHAL returns service specific error. 352 */ set(HalPropValue propValue)353 public abstract void set(HalPropValue propValue) 354 throws RemoteException, ServiceSpecificException; 355 356 /** 357 * Dumps VHAL debug information. 358 * 359 * Additional arguments could also be provided through {@link args} to debug VHAL. 360 * 361 * @param fd The file descriptor to print output. 362 * @param args Optional additional arguments for the debug command. Can be empty. 363 * @throws RemoteException if the remote operation fails. 364 * @throws ServiceSpecificException if VHAL returns service specific error. 365 */ dump(FileDescriptor fd, List<String> args)366 public abstract void dump(FileDescriptor fd, List<String> args) 367 throws RemoteException, ServiceSpecificException; 368 369 /** 370 * Checks if fake VHAL is enabled. 371 * 372 * @return {@code true} if a FakeVehicleStub instance is created. 373 */ isFakeModeEnabled()374 public boolean isFakeModeEnabled() { 375 return false; 376 } 377 378 /** 379 * Checks if simulated mode is enabled 380 */ isSimulatedModeEnabled()381 public boolean isSimulatedModeEnabled() { 382 return false; 383 } 384 385 /** 386 * Cancels all the on-going async requests with the given request IDs. 387 * 388 * @param requestIds a list of async get/set request IDs. 389 */ cancelRequests(List<Integer> requestIds)390 public void cancelRequests(List<Integer> requestIds) {} 391 392 /** 393 * Whether the area config supports dynamic supported values API. 394 * 395 * This is only supported if area config has non-null 396 * {@code hasSupportedValuesInfo}. 397 */ isSupportedValuesImplemented(HalAreaConfig halAreaConfig)398 public boolean isSupportedValuesImplemented(HalAreaConfig halAreaConfig) { 399 return false; 400 } 401 MinMaxSupportedRawPropValues( @ullable RawPropValues minValue, @Nullable RawPropValues maxValue)402 public record MinMaxSupportedRawPropValues( 403 @Nullable RawPropValues minValue, @Nullable RawPropValues maxValue) {}; 404 405 /** 406 * Gets the min/max supported value. 407 * 408 * Caller should only call this if {@link #isSupportedValuesImplemented} is {@code true}. 409 * 410 * If no min/max supported value is specified, return an empty structure. 411 * 412 * @throws ServiceSpecificException if the operation fails. 413 */ getMinMaxSupportedValue(int propertyId, int areaId)414 public MinMaxSupportedRawPropValues getMinMaxSupportedValue(int propertyId, int areaId) 415 throws ServiceSpecificException { 416 throw new UnsupportedOperationException(); 417 } 418 419 /** 420 * Gets the supported values list. 421 * 422 * Caller should only call this if {@link #isSupportedValuesImplemented} is {@code true}. 423 * 424 * The returned list is not sorted. 425 * 426 * If no supported values list is specified, return {@code null}. 427 * 428 * @throws ServiceSpecificException if the operation fails. 429 */ getSupportedValuesList(int propertyId, int areaId)430 public @Nullable List<RawPropValues> getSupportedValuesList(int propertyId, int areaId) 431 throws ServiceSpecificException { 432 throw new UnsupportedOperationException(); 433 } 434 435 /** 436 * Returns the real vehicle stub if the vehicle stub is fake. 437 * 438 * @return The real vehicle stub other wise this. 439 */ getRealVehicleStub()440 public VehicleStub getRealVehicleStub() { 441 return this; 442 } 443 444 /** 445 * Returns the start time of the simulation in nanos. 446 */ getSimulationStartTimestampNanos()447 public long getSimulationStartTimestampNanos() { 448 throw new UnsupportedOperationException("Not in simulated mode"); 449 } 450 451 /** 452 * Injects the CarPropertyValues. 453 * @param carPropertyValues The carPropertyValues to inject. 454 */ injectVehicleProperties(List<CarPropertyValue> carPropertyValues)455 public void injectVehicleProperties(List<CarPropertyValue> carPropertyValues) { 456 throw new UnsupportedOperationException("Not in simulated mode"); 457 } 458 459 /** 460 * Gets the last injected vehicle property for the propertyId. 461 * 462 * @param propertyId The propertyId that was last injected. 463 * @return The {@link CarPropertyValue} that was last injected. 464 */ getLastInjectedVehicleProperty(int propertyId)465 public CarPropertyValue getLastInjectedVehicleProperty(int propertyId) { 466 throw new UnsupportedOperationException("Not in simulated mode"); 467 } 468 } 469