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