• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 android.car.hardware;
18 
19 import static android.car.feature.Flags.FLAG_CAR_PROPERTY_VALUE_PROPERTY_STATUS;
20 
21 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE;
22 import static com.android.car.internal.util.DebugUtils.constantToString;
23 import static com.android.car.internal.util.DebugUtils.toAreaIdString;
24 
25 import static java.lang.Integer.toHexString;
26 
27 import android.annotation.FlaggedApi;
28 import android.annotation.IntDef;
29 import android.annotation.NonNull;
30 import android.annotation.SystemApi;
31 import android.car.VehiclePropertyIds;
32 import android.car.builtin.os.BuildHelper;
33 import android.car.feature.Flags;
34 import android.os.Parcel;
35 import android.os.Parcelable;
36 
37 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
38 import com.android.car.internal.property.RawPropertyValue;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.util.Arrays;
43 import java.util.Objects;
44 
45 /**
46  * Stores a value for a vehicle property ID and area ID combination.
47  *
48  * Client should use {@code android.car.*} types when dealing with property ID, area ID or property
49  * value and MUST NOT use {@code android.hardware.automotive.vehicle.*} types directly.
50  *
51  * @param <T> refer to {@link Parcel#writeValue(java.lang.Object)} to get a list of all supported
52  *            types. The class should be visible to framework as default class loader is being used
53  *            here.
54  */
55 public final class CarPropertyValue<T> implements Parcelable {
56 
57     private final int mPropertyId;
58     private final int mAreaId;
59     private final int mStatus;
60     private final long mTimestampNanos;
61     private final RawPropertyValue<T> mValue;
62     private final boolean mIsSimulationPropId;
63 
64     /** @removed accidentally exposed previously */
65     @IntDef({
66         STATUS_AVAILABLE,
67         STATUS_UNAVAILABLE,
68         STATUS_ERROR
69     })
70     @Retention(RetentionPolicy.SOURCE)
71     public @interface PropertyStatus {}
72 
73     /**
74      * {@code CarPropertyValue} is available.
75      */
76     public static final int STATUS_AVAILABLE = 0;
77 
78     /**
79      * {@code CarPropertyValue} is unavailable.
80      */
81     public static final int STATUS_UNAVAILABLE = 1;
82 
83     /**
84      * {@code CarPropertyValue} has an error.
85      */
86     public static final int STATUS_ERROR = 2;
87 
88     /**
89      * Creates an instance of {@code CarPropertyValue}.
90      *
91      * @param propertyId The property identifier, see constants in
92      *                   {@link android.car.VehiclePropertyIds} for system defined property IDs.
93      * @param areaId     The area identifier. Must be {@code 0} if property is
94      *                   {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}. Otherwise, it
95      *                   must be one or more OR'd together constants of this property's
96      *                   {@link android.car.VehicleAreaType}:
97      *                     <ul>
98      *                       <li>{@code VehicleAreaWindow}</li>
99      *                       <li>{@code VehicleAreaDoor}</li>
100      *                       <li>{@link android.car.VehicleAreaSeat}</li>
101      *                       <li>{@code VehicleAreaMirror}</li>
102      *                       <li>{@link android.car.VehicleAreaWheel}</li>
103      *                     </ul>
104      * @param value Value of Property
105      * @hide
106      */
CarPropertyValue(int propertyId, int areaId, T value)107     public CarPropertyValue(int propertyId, int areaId, T value) {
108         this(propertyId, areaId, /* timestampNanos= */ 0, value);
109     }
110 
111     /**
112      * Creates an instance of {@code CarPropertyValue}. The {@code timestampNanos} is the time in
113      * nanoseconds at which the event happened. For a given car property, each new {@code
114      * CarPropertyValue} should be monotonically increasing using the same time base as
115      * {@link android.os.SystemClock#elapsedRealtimeNanos()}.
116      *
117      *
118      * @param propertyId The property identifier, see constants in
119      *                   {@link android.car.VehiclePropertyIds} for system defined property IDs.
120      * @param areaId     The area identifier. Must be {@code 0} if property is
121      *                   {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}. Otherwise, it
122      *                   must be one or more OR'd together constants of this property's
123      *                   {@link android.car.VehicleAreaType}:
124      *                     <ul>
125      *                       <li>{@code VehicleAreaWindow}</li>
126      *                       <li>{@code VehicleAreaDoor}</li>
127      *                       <li>{@link android.car.VehicleAreaSeat}</li>
128      *                       <li>{@code VehicleAreaMirror}</li>
129      *                       <li>{@link android.car.VehicleAreaWheel}</li>
130      *                     </ul>
131      * @param timestampNanos  Elapsed time in nanoseconds since boot
132      * @param value      Value of Property
133      * @hide
134      */
CarPropertyValue(int propertyId, int areaId, long timestampNanos, T value)135     public CarPropertyValue(int propertyId, int areaId, long timestampNanos, T value) {
136         this(propertyId, areaId, CarPropertyValue.STATUS_AVAILABLE, timestampNanos, value);
137     }
138 
139     /**
140      * Creates an instance of {@code CarPropertyValue}. The {@code timestampNanos} is the time in
141      * nanoseconds at which the event happened. For a given car property, each new {@code
142      * CarPropertyValue} should be monotonically increasing using the same time base as
143      * {@link android.os.SystemClock#elapsedRealtimeNanos()}.
144      *
145      * @param propertyId The property identifier, see constants in
146      *                   {@link android.car.VehiclePropertyIds} for system defined property IDs.
147      * @param areaId     The area identifier. Must be {@code 0} if property is
148      *                   {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}. Otherwise, it
149      *                   must be one or more OR'd together constants of this property's
150      *                   {@link android.car.VehicleAreaType}:
151      *                     <ul>
152      *                       <li>{@code VehicleAreaWindow}</li>
153      *                       <li>{@code VehicleAreaDoor}</li>
154      *                       <li>{@link android.car.VehicleAreaSeat}</li>
155      *                       <li>{@code VehicleAreaMirror}</li>
156      *                       <li>{@link android.car.VehicleAreaWheel}</li>
157      *                     </ul>
158      * @param status           The status of the property.
159      * @param timestampNanos   Elapsed time in nanoseconds since boot
160      * @param rawPropertyValue Value of the property.
161      *
162      * @hide
163      */
CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos, RawPropertyValue<T> rawPropertyValue)164     public CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos,
165             RawPropertyValue<T> rawPropertyValue) {
166         this(propertyId, areaId, status, timestampNanos, rawPropertyValue,
167                 /* isSimulationPropId= */ false);
168     }
169 
170     /**
171      * Creates an instance of {@code CarPropertyValue}. The {@code timestampNanos} is the time in
172      * nanoseconds at which the event happened. For a given car property, each new {@code
173      * CarPropertyValue} should be monotonically increasing using the same time base as
174      * {@link android.os.SystemClock#elapsedRealtimeNanos()}.
175      *
176      * @param propertyId The property identifier, see constants in
177      *                   {@link android.car.VehiclePropertyIds} for system defined property IDs.
178      * @param areaId     The area identifier. Must be {@code 0} if property is
179      *                   {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}. Otherwise, it
180      *                   must be one or more OR'd together constants of this property's
181      *                   {@link android.car.VehicleAreaType}:
182      *                     <ul>
183      *                       <li>{@code VehicleAreaWindow}</li>
184      *                       <li>{@code VehicleAreaDoor}</li>
185      *                       <li>{@link android.car.VehicleAreaSeat}</li>
186      *                       <li>{@code VehicleAreaMirror}</li>
187      *                       <li>{@link android.car.VehicleAreaWheel}</li>
188      *                     </ul>
189      * @param status           The status of the property.
190      * @param timestampNanos   Elapsed time in nanoseconds since boot
191      * @param rawPropertyValue Value of the property.
192      * @param isSimulationPropId     If the property is a Simulation property.
193      *
194      * @hide
195      */
CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos, RawPropertyValue<T> rawPropertyValue, boolean isSimulationPropId)196     public CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos,
197             RawPropertyValue<T> rawPropertyValue, boolean isSimulationPropId) {
198         mPropertyId = propertyId;
199         mAreaId = areaId;
200         mStatus = status;
201         mTimestampNanos = timestampNanos;
202         mValue = rawPropertyValue;
203         mIsSimulationPropId = isSimulationPropId;
204     }
205 
206 
207     /**
208      * @hide
209      *
210      * @deprecated use {@link CarPropertyValue#CarPropertyValue(int, int, long, T)} instead
211      */
212     @Deprecated
CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos, T value)213     public CarPropertyValue(int propertyId, int areaId, int status, long timestampNanos, T value) {
214 
215         this(propertyId, areaId, status, timestampNanos, new RawPropertyValue(
216                 Objects.requireNonNull(value, "value for propertyId: "
217                         + VehiclePropertyIds.toString(propertyId) + ", areaId: "
218                         + toAreaIdString(propertyId, areaId) + ", status: " + status
219                         + " must not be null")
220         ));
221     }
222 
223     /**
224      * Creates an instance of {@code CarPropertyValue}.
225      *
226      * @param in Parcel to read
227      * @hide
228      */
229     @SuppressWarnings("unchecked")
CarPropertyValue(Parcel in)230     public CarPropertyValue(Parcel in) {
231         mPropertyId = in.readInt();
232         mAreaId = in.readInt();
233         mStatus = in.readInt();
234         mTimestampNanos = in.readLong();
235         mValue = (RawPropertyValue<T>) in.readParcelable(RawPropertyValue.class.getClassLoader(),
236                 RawPropertyValue.class);
237         mIsSimulationPropId = in.readBoolean();
238     }
239 
240     public static final Creator<CarPropertyValue> CREATOR = new Creator<CarPropertyValue>() {
241         @Override
242         public CarPropertyValue createFromParcel(Parcel in) {
243             return new CarPropertyValue(in);
244         }
245 
246         @Override
247         public CarPropertyValue[] newArray(int size) {
248             return new CarPropertyValue[size];
249         }
250     };
251 
252     @Override
253     @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE)
describeContents()254     public int describeContents() {
255         return 0;
256     }
257 
258     @Override
writeToParcel(Parcel dest, int flags)259     public void writeToParcel(Parcel dest, int flags) {
260         dest.writeInt(mPropertyId);
261         dest.writeInt(mAreaId);
262         dest.writeInt(mStatus);
263         dest.writeLong(mTimestampNanos);
264         dest.writeParcelable(mValue, /* parcelableFlags= */ 0);
265         dest.writeBoolean(mIsSimulationPropId);
266     }
267 
268     /**
269      * Returns the property identifier.
270      *
271      * @return The property identifier of {@code CarPropertyValue}. See constants in
272      *         {@link android.car.VehiclePropertyIds} for some system defined possible values.
273      */
getPropertyId()274     public int getPropertyId() {
275         return mPropertyId;
276     }
277 
278     /**
279      * Returns the area identifier.
280      *
281      * @return The area identifier of {@code CarPropertyValue}, If property is
282      *         {@link android.car.VehicleAreaType#VEHICLE_AREA_TYPE_GLOBAL}, it will be {@code 0}.
283      *         Otherwise, it will be on or more OR'd together constants of this property's
284      *         {@link android.car.VehicleAreaType}:
285      *           <ul>
286      *             <li>{@code VehicleAreaWindow}</li>
287      *             <li>{@code VehicleAreaDoor}</li>
288      *             <li>{@link android.car.VehicleAreaSeat}</li>
289      *             <li>{@code VehicleAreaMirror}</li>
290      *             <li>{@link android.car.VehicleAreaWheel}</li>
291      *           </ul>
292      */
getAreaId()293     public int getAreaId() {
294         return mAreaId;
295     }
296 
297     /**
298      * @return The property status of {@code CarPropertyValue}
299      */
300     @FlaggedApi(FLAG_CAR_PROPERTY_VALUE_PROPERTY_STATUS)
301     @PropertyStatus
getPropertyStatus()302     public int getPropertyStatus() {
303         return mStatus;
304     }
305 
306     /**
307      * @return Status of {@code CarPropertyValue}
308      * @deprecated Use {@link #getPropertyStatus} instead.
309      */
310     @Deprecated
311     @PropertyStatus
getStatus()312     public int getStatus() {
313         return mStatus;
314     }
315 
316     /**
317      * Returns the timestamp in nanoseconds at which the {@code CarPropertyValue} happened. For a
318      * given car property, each new {@code CarPropertyValue} should be monotonically increasing
319      * using the same time base as {@link android.os.SystemClock#elapsedRealtimeNanos()}.
320      *
321      * <p>NOTE: Timestamp should be synchronized with other signals from the platform (e.g.
322      * {@link android.location.Location} and {@link android.hardware.SensorEvent} instances).
323      * Ideally, timestamp synchronization error should be below 1 millisecond.
324      */
getTimestamp()325     public long getTimestamp() {
326         return mTimestampNanos;
327     }
328 
329     /**
330      * Returns the value for {@code CarPropertyValue}.
331      *
332      * <p>
333      * <b>Note:</b>Caller must check the value of {@link #getPropertyStatus()}. Only use
334      * {@link #getValue()} when {@link #getPropertyStatus()} is {@link #STATUS_AVAILABLE}. If not,
335      * {@link #getValue()} is meaningless.
336      */
337     @NonNull
getValue()338     public T getValue() {
339         return mValue.getTypedValue();
340     }
341 
342     /**
343      * Gets the internal raw property value.
344      *
345      * @hide
346      */
getRawPropertyValue()347     public RawPropertyValue getRawPropertyValue() {
348         return mValue;
349     }
350 
351     /**
352      * Returns weather the propertyId is Simulation Property Id.
353      *
354      * <p>Simulation property is a property which is used by car service and vehicle hardware but
355      * is not defined in {@link android.car.VehiclePropertyIds}
356      *
357      * @return This will only be {@code true} if returned from
358      * {@link android.car.hardware.property.CarPropertySimulationManager}.
359      *
360      * @hide
361      */
362     @SystemApi
363     @FlaggedApi(Flags.FLAG_CAR_PROPERTY_SIMULATION)
isPropertyIdSimulationPropId()364     public boolean isPropertyIdSimulationPropId() {
365         if (!BuildHelper.isDebuggableBuild()) {
366             throw new IllegalStateException("Build is not eng or user-debug");
367         }
368         return mIsSimulationPropId;
369     }
370 
371     /** @hide */
372     @Override
toString()373     public String toString() {
374         String propertyIdToString = VehiclePropertyIds.toString(mPropertyId);
375         if (Flags.carPropertySimulation()) {
376             if (isPropertyIdSimulationPropId()) {
377                 propertyIdToString = Integer.toHexString(mPropertyId);
378             }
379         }
380         String propertyValueString = "CarPropertyValue{"
381                 + "mPropertyId=0x" + toHexString(mPropertyId)
382                 + ", propertyName=" + propertyIdToString
383                 + ", mAreaId=" + toAreaIdString(mPropertyId, mAreaId)
384                 + ", mStatus=" + constantToString(CarPropertyValue.class, "STATUS_", mStatus)
385                 + ", mTimestampNanos=" + mTimestampNanos
386                 + ", mValue=" + mValue;
387         if (Flags.carPropertySimulation()) {
388             if (isPropertyIdSimulationPropId()) {
389                 return propertyValueString
390                         + ", mIsSimulationPropId=" + mIsSimulationPropId
391                         + '}';
392             }
393         }
394         return propertyValueString + '}';
395     }
396 
397     /** Generates hash code for this instance. */
398     @Override
hashCode()399     public int hashCode() {
400         return Arrays.hashCode(new Object[]{
401                 mPropertyId, mAreaId, mStatus, mTimestampNanos, mValue});
402     }
403 
404     /** Checks equality with passed {@code object}. */
405     @Override
equals(Object object)406     public boolean equals(Object object) {
407         if (this == object) {
408             return true;
409         }
410         if (!(object instanceof CarPropertyValue<?>)) {
411             return false;
412         }
413         CarPropertyValue<?> carPropertyValue = (CarPropertyValue<?>) object;
414         return mPropertyId == carPropertyValue.mPropertyId && mAreaId == carPropertyValue.mAreaId
415                 && mStatus == carPropertyValue.mStatus
416                 && mTimestampNanos == carPropertyValue.mTimestampNanos
417                 && Objects.equals(mValue, carPropertyValue.mValue);
418     }
419 }
420