• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.cts;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.junit.Assert.assertThrows;
23 import static org.junit.Assume.assumeFalse;
24 import static org.junit.Assume.assumeTrue;
25 
26 import android.car.Car;
27 import android.car.VehicleAreaType;
28 import android.car.VehiclePropertyIds;
29 import android.car.VehiclePropertyType;
30 import android.car.cts.utils.BuildUtils;
31 import android.car.cts.utils.ShellPermissionUtils;
32 import android.car.feature.Flags;
33 import android.car.hardware.CarPropertyConfig;
34 import android.car.hardware.property.AreaIdConfig;
35 import android.car.hardware.property.CarPropertyManager;
36 import android.platform.test.annotations.AppModeFull;
37 import android.platform.test.annotations.RequiresDevice;
38 import android.platform.test.annotations.RequiresFlagsDisabled;
39 import android.platform.test.annotations.RequiresFlagsEnabled;
40 import android.platform.test.flag.junit.CheckFlagsRule;
41 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
42 
43 import androidx.test.filters.SmallTest;
44 import androidx.test.runner.AndroidJUnit4;
45 
46 import org.junit.Assert;
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.Test.None;
51 import org.junit.runner.RunWith;
52 
53 import java.util.Arrays;
54 import java.util.List;
55 
56 @SmallTest
57 @RequiresDevice
58 @RunWith(AndroidJUnit4.class)
59 @AppModeFull(reason = "Instant apps cannot get car related permissions.")
60 public final class CarPropertyConfigTest extends AbstractCarTestCase {
61 
62     private static final String TAG = CarPropertyConfigTest.class.getSimpleName();
63     private static final float EPSILON = 0.00001f;
64 
65     private List<CarPropertyConfig> mConfigs;
66 
67     @Rule
68     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
69 
70     @Before
setUp()71     public void setUp() throws Exception {
72         CarPropertyManager carPropertyManager = (CarPropertyManager) getCar().getCarManager(
73                 Car.PROPERTY_SERVICE);
74         ShellPermissionUtils.runWithShellPermissionIdentity(
75                 () -> mConfigs = carPropertyManager.getPropertyList());
76         assertThat(mConfigs.size()).isAtLeast(4);
77     }
78 
79     @Test
testGetPropertyId()80     public void testGetPropertyId() {
81         List<Integer> expectedPropertyTypes = Arrays.asList(
82                 VehiclePropertyType.STRING,
83                 VehiclePropertyType.BOOLEAN,
84                 VehiclePropertyType.INT32,
85                 VehiclePropertyType.INT32_VEC,
86                 VehiclePropertyType.INT64,
87                 VehiclePropertyType.INT64_VEC,
88                 VehiclePropertyType.FLOAT,
89                 VehiclePropertyType.FLOAT_VEC,
90                 VehiclePropertyType.BYTES,
91                 VehiclePropertyType.MIXED);
92 
93         for (CarPropertyConfig cfg : mConfigs) {
94             int propId = cfg.getPropertyId();
95 
96             boolean verifyGroup =
97                 (propId & VehiclePropertyGroup.MASK) == VehiclePropertyGroup.VENDOR ||
98                    (propId & VehiclePropertyGroup.MASK) == VehiclePropertyGroup.SYSTEM;
99             Assert.assertTrue(verifyGroup);
100 
101             int propertyType = propId & VehiclePropertyType.MASK;
102             assertThat(expectedPropertyTypes).contains(propertyType);
103         }
104     }
105 
106     @Test
107     @RequiresFlagsDisabled(Flags.FLAG_AREA_ID_CONFIG_ACCESS)
testGetAccess_AreaIdConfigAccessDisabled()108     public void testGetAccess_AreaIdConfigAccessDisabled() {
109         List<Integer> expectedAccessCodes = Arrays.asList(
110                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_NONE,
111                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
112                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
113                 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE);
114         for (CarPropertyConfig cfg : mConfigs) {
115             int result = cfg.getAccess();
116             assertThat(expectedAccessCodes).contains(result);
117         }
118     }
119 
120     @Test
121     @RequiresFlagsEnabled(Flags.FLAG_AREA_ID_CONFIG_ACCESS)
testGetAccess_AreaIdConfigAccessEnabled()122     public void testGetAccess_AreaIdConfigAccessEnabled() {
123         for (CarPropertyConfig<?> cfg : mConfigs) {
124             boolean readOnlyPresent = false;
125             boolean writeOnlyPresent = false;
126             boolean readWritePresent = false;
127             for (AreaIdConfig<?> areaIdConfig : cfg.getAreaIdConfigs()) {
128                 int areaIdAccess = areaIdConfig.getAccess();
129                 if (areaIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ) {
130                     readOnlyPresent = true;
131                 } else if (areaIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE) {
132                     writeOnlyPresent = true;
133                 } else if (areaIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
134                     readWritePresent = true;
135                 } else {
136                     throw new AssertionError("AreaIdConfig must have an access level of one of the"
137                             + " following: {READ, WRITE, READ_WRITE}");
138                 }
139             }
140             assertThat(readOnlyPresent || writeOnlyPresent || readWritePresent).isTrue();
141 
142             int propertyIdAccess = cfg.getAccess();
143             if (propertyIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ) {
144                 assertThat(readOnlyPresent && !writeOnlyPresent).isTrue();
145             } else if (propertyIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE) {
146                 assertThat(!readOnlyPresent && writeOnlyPresent && !readWritePresent).isTrue();
147             } else if (propertyIdAccess == CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
148                 assertThat(!readOnlyPresent && !writeOnlyPresent && readWritePresent).isTrue();
149             } else {
150                 throw new AssertionError("CarPropertyConfig must have an access level of one of the"
151                         + " following: {READ, WRITE, READ_WRITE}");
152             }
153         }
154     }
155 
156     @Test
testGetAreaType()157     public void testGetAreaType() {
158         List<Integer> expectedAreaTypes = Arrays.asList(
159                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
160                 VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW,
161                 VehicleAreaType.VEHICLE_AREA_TYPE_SEAT,
162                 VehicleAreaType.VEHICLE_AREA_TYPE_DOOR,
163                 VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR,
164                 VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL,
165                 VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR);
166         for (CarPropertyConfig cfg : mConfigs) {
167             int result = 0;
168             try {
169                 result = cfg.getAreaType();
170             } catch (RuntimeException e) {
171                 Assert.fail(
172                         "Unexpected Runtime Exception for property: "
173                                 + VehiclePropertyIds.toString(cfg.getPropertyId()));
174             }
175 
176             assertThat(expectedAreaTypes).contains(result);
177             int propertyArea = cfg.getPropertyId() & VehicleArea.MASK;
178             if (result == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) {
179                 Assert.assertEquals(VehicleArea.GLOBAL, propertyArea);
180             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW) {
181                 Assert.assertEquals(VehicleArea.WINDOW, propertyArea);
182             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_SEAT) {
183                 Assert.assertEquals(VehicleArea.SEAT, propertyArea);
184             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR) {
185                 Assert.assertEquals(VehicleArea.MIRROR, propertyArea);
186             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_DOOR) {
187                 Assert.assertEquals(VehicleArea.DOOR, propertyArea);
188             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL) {
189                 Assert.assertEquals(VehicleArea.WHEEL, propertyArea);
190             } else if (result == VehicleAreaType.VEHICLE_AREA_TYPE_VENDOR) {
191                 Assert.assertEquals(VehicleArea.VENDOR, propertyArea);
192             } else {
193                 Assert.fail("Failed for property: "
194                         + VehiclePropertyIds.toString(cfg.getPropertyId()));
195             }
196         }
197     }
198 
199     @Test
testGetChangeMode()200     public void testGetChangeMode() {
201         List<Integer> expectedChangeModes = Arrays.asList(
202                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC,
203                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE,
204                 CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS);
205         for (CarPropertyConfig cfg : mConfigs) {
206             int result = cfg.getChangeMode();
207             assertThat(expectedChangeModes).contains(result);
208         }
209     }
210 
211     @Test
testGetConfigArrayAndPropertyId()212     public void testGetConfigArrayAndPropertyId() {
213         for (CarPropertyConfig cfg : mConfigs) {
214             cfg.getPropertyId();
215             Assert.assertNotNull(cfg.getConfigArray());
216         }
217     }
218 
219     @Test
testSampleRate()220     public void testSampleRate() {
221         for (CarPropertyConfig cfg : mConfigs) {
222             float maxSampleRate = cfg.getMaxSampleRate();
223             float minSampleRate = cfg.getMinSampleRate();
224             // Only continuous properties have min/max sample rate.
225             if (Math.abs(maxSampleRate - 0.0f) > EPSILON
226                     || Math.abs(minSampleRate - 0.0f) > EPSILON) {
227                 Assert.assertEquals(
228                     CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS, cfg.getChangeMode());
229             }
230         }
231     }
232 
233     @Test
testGlobalProperty()234     public void testGlobalProperty() {
235         for (CarPropertyConfig cfg : mConfigs) {
236             Assert.assertEquals(
237                 cfg.getAreaType() == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL,
238                 cfg.isGlobalProperty());
239         }
240     }
241 
242     @Test
testGetAreaIds()243     public void testGetAreaIds() {
244         for (CarPropertyConfig<?> cfg : mConfigs) {
245             int[] areaIds = cfg.getAreaIds();
246             Assert.assertNotNull(areaIds);
247             assertThat(areaIds).isNotEmpty();
248             Assert.assertTrue(areaIdCheck(areaIds));
249             assertThat(areaIds.length).isEqualTo(cfg.getAreaIdConfigs().size());
250             for (int areaId : areaIds) {
251                 boolean found = false;
252                 for (AreaIdConfig<?> areaIdConfig : cfg.getAreaIdConfigs()) {
253                     if (areaIdConfig.getAreaId() == areaId) {
254                         found = true;
255                         break;
256                     }
257                 }
258                 assertWithMessage("Property ID: " + VehiclePropertyIds.toString(cfg.getPropertyId())
259                         + " area ID: 0x" + Integer.toHexString(areaId)
260                         + " must be found in AreaIdConfigs list").that(found).isTrue();
261             }
262         }
263     }
264 
265     @Test
testGetAreaIdConfigs()266     public void testGetAreaIdConfigs() {
267         for (CarPropertyConfig<?> cfg : mConfigs) {
268             List<? extends AreaIdConfig<?>> areaIdConfigs = cfg.getAreaIdConfigs();
269             assertThat(areaIdConfigs).isNotNull();
270             assertThat(areaIdConfigs).isNotEmpty();
271             for (AreaIdConfig<?> areaIdConfig : areaIdConfigs) {
272                 boolean minMaxCorrectlyDefined =
273                         (areaIdConfig.getMinValue() != null && areaIdConfig.getMaxValue() != null)
274                                 || (areaIdConfig.getMinValue() == null
275                                 && areaIdConfig.getMaxValue() == null);
276                 assertWithMessage("Property ID: " + VehiclePropertyIds.toString(cfg.getPropertyId())
277                         + " area ID: 0x" + Integer.toHexString(areaIdConfig.getAreaId())
278                         + " min/max must be both defined or both null").that(
279                         minMaxCorrectlyDefined).isTrue();
280                 if (cfg.getPropertyType().equals(Integer.class)) {
281                     if (areaIdConfig.getMinValue() != null) {
282                         assertThat((Integer) areaIdConfig.getMaxValue()).isAtLeast(
283                                 (Integer) areaIdConfig.getMinValue());
284                         if (((Integer) areaIdConfig.getMinValue()).equals(0)) {
285                             assertThat((Integer) areaIdConfig.getMaxValue()).isNotEqualTo(0);
286                         }
287                     }
288                 } else if (cfg.getPropertyType().equals(Long.class)) {
289                     if (areaIdConfig.getMinValue() != null) {
290                         assertThat((Long) areaIdConfig.getMaxValue()).isAtLeast(
291                                 (Long) areaIdConfig.getMinValue());
292                         if (((Long) areaIdConfig.getMinValue()).equals(0L)) {
293                             assertThat((Long) areaIdConfig.getMaxValue()).isNotEqualTo(0L);
294                         }
295                     }
296                 } else if (cfg.getPropertyType().equals(Float.class)) {
297                     if (areaIdConfig.getMinValue() != null) {
298                         assertThat((Float) areaIdConfig.getMaxValue()).isAtLeast(
299                                 (Float) areaIdConfig.getMinValue());
300                         if (((Float) areaIdConfig.getMinValue()).equals(0F)) {
301                             assertThat((Float) areaIdConfig.getMaxValue()).isNotEqualTo(0F);
302                         }
303                     }
304                 } else {
305                     assertThat(areaIdConfig.getMinValue()).isNull();
306                     assertThat(areaIdConfig.getMaxValue()).isNull();
307                 }
308                 assertThat(areaIdConfig.getSupportedEnumValues()).isNotNull();
309                 assertThat(areaIdConfig.getSupportedEnumValues()).containsNoDuplicates();
310                 if (Flags.areaIdConfigAccess()) {
311                     assertThat(areaIdConfig.getAccess()).isIn(Arrays.asList(
312                             CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ,
313                             CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_WRITE,
314                             CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE
315                     ));
316                 }
317             }
318         }
319     }
320 
321     @Test
testGetAreaIdConfig()322     public void testGetAreaIdConfig() {
323         for (CarPropertyConfig<?> cfg : mConfigs) {
324             for (int areaId : cfg.getAreaIds()) {
325                 AreaIdConfig<?> areaIdConfig = cfg.getAreaIdConfig(areaId);
326                 assertThat(areaIdConfig).isNotNull();
327                 assertThat(areaIdConfig.getAreaId()).isEqualTo(areaId);
328                 assertThat(areaIdConfig).isIn(cfg.getAreaIdConfigs());
329             }
330         }
331     }
332 
333     @Test(expected = None.class /* no exception expected*/)
testGetMinAndMaxValue()334     public void testGetMinAndMaxValue() {
335         for (CarPropertyConfig cfg: mConfigs) {
336             cfg.getMinValue();
337             cfg.getMaxValue();
338             for (int areaId : cfg.getAreaIds()) {
339                 cfg.getMaxValue(areaId);
340                 cfg.getMinValue(areaId);
341             }
342         }
343     }
344 
345     @Test
346     @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION)
testIsPropertyIdSimulationPropId()347     public void testIsPropertyIdSimulationPropId() {
348         assumeFalse(BuildUtils.isUserBuild());
349         for (CarPropertyConfig<?> cfg : mConfigs) {
350             assertThat(cfg.isPropertyIdSimulationPropId()).isFalse();
351         }
352     }
353 
354     @Test
355     @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION)
testIsPropertyIdSimulationPropId_userBuild()356     public void testIsPropertyIdSimulationPropId_userBuild() {
357         assumeTrue(BuildUtils.isUserBuild());
358         for (CarPropertyConfig<?> cfg : mConfigs) {
359             IllegalStateException thrown =
360                     assertThrows(
361                             IllegalStateException.class, () -> cfg.isPropertyIdSimulationPropId());
362             assertThat(thrown).hasMessageThat().contains("Build is not eng or user-debug");
363         }
364     }
365 
366     /**
367      * The property value must be independently controllable in any two different AreaIDs
368      * in the array. An area must only appear once in the array of AreaIDs. That is, an
369      * area must only be part of a single AreaID in the array.
370      * @param areaIds
371      * @return
372      */
areaIdCheck(int[] areaIds)373     private boolean areaIdCheck(int[] areaIds) {
374         for (int i = 0; i < areaIds.length - 1; i++) {
375             for (int j = i + 1; j < areaIds.length; j++) {
376                 if ((areaIds[i] & areaIds[j]) != 0) {
377                     return false;
378                 }
379             }
380         }
381         return true;
382     }
383 
384     private final class VehiclePropertyGroup {
385         private static final int SYSTEM = 0x10000000;
386         private static final int VENDOR = 0x20000000;
387 
388         private static final int MASK   = 0xf0000000;
389     }
390 
391     private final class VehicleArea {
392         private static final int GLOBAL = 0x01000000;
393         private static final int WINDOW = 0x03000000;
394         private static final int MIRROR = 0x04000000;
395         private static final int SEAT   = 0x05000000;
396         private static final int DOOR   = 0x06000000;
397         private static final int WHEEL  = 0x07000000;
398         private static final int VENDOR  = 0x08000000;
399 
400         private static final int MASK   = 0x0f000000;
401 
402     }
403 }
404