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