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