1 /* 2 * Copyright (C) 2024 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.hal.property; 18 19 import static com.android.car.CarServiceUtils.toIntArray; 20 21 import static com.google.common.truth.Truth.assertThat; 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import static org.junit.Assert.assertThrows; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.when; 27 28 import android.car.Car; 29 import android.car.VehiclePropertyIds; 30 import android.car.feature.FakeFeatureFlagsImpl; 31 import android.car.feature.Flags; 32 import android.car.hardware.CarHvacFanDirection; 33 import android.car.test.AbstractExpectableTestCase; 34 import android.content.Context; 35 import android.content.pm.PackageManager; 36 import android.hardware.automotive.vehicle.VehicleGear; 37 import android.hardware.automotive.vehicle.VehicleProperty; 38 import android.hardware.automotive.vehicle.VehicleUnit; 39 import android.hardware.automotive.vehicle.VehicleVendorPermission; 40 import android.os.SystemClock; 41 import android.platform.test.ravenwood.RavenwoodRule; 42 import android.util.ArraySet; 43 import android.util.SparseArray; 44 45 import com.android.car.hal.HalPropValue; 46 import com.android.car.hal.HalPropValueBuilder; 47 import com.android.car.hal.property.PropertyHalServiceConfigs.CarSvcPropertyConfig; 48 import com.android.car.hal.property.PropertyPermissionInfo.AllOfPermissions; 49 import com.android.car.hal.property.PropertyPermissionInfo.AnyOfPermissions; 50 import com.android.car.hal.property.PropertyPermissionInfo.PermissionCondition; 51 import com.android.car.hal.property.PropertyPermissionInfo.PropertyPermissions; 52 import com.android.car.hal.property.PropertyPermissionInfo.SinglePermission; 53 54 import org.junit.Before; 55 import org.junit.Rule; 56 import org.junit.Test; 57 import org.mockito.Mock; 58 import org.mockito.MockitoAnnotations; 59 import org.mockito.junit.MockitoJUnit; 60 import org.mockito.junit.MockitoRule; 61 62 import java.io.ByteArrayInputStream; 63 import java.io.IOException; 64 import java.io.InputStream; 65 import java.nio.charset.StandardCharsets; 66 import java.util.ArrayList; 67 import java.util.List; 68 import java.util.Set; 69 70 public final class PropertyHalServiceConfigsUnitTest extends AbstractExpectableTestCase { 71 private static final int VENDOR_PROPERTY_1 = 0x21e01111; 72 private static final int VENDOR_PROPERTY_2 = 0x21e01112; 73 private static final int VENDOR_PROPERTY_3 = 0x21e01113; 74 private static final int VENDOR_PROPERTY_4 = 0x21e01114; 75 private static final int[] VENDOR_PROPERTY_IDS = { 76 VENDOR_PROPERTY_1, VENDOR_PROPERTY_2, VENDOR_PROPERTY_3, VENDOR_PROPERTY_4}; 77 private static final int[] SYSTEM_PROPERTY_IDS = {VehiclePropertyIds.ENGINE_OIL_LEVEL, 78 VehiclePropertyIds.CURRENT_GEAR, VehiclePropertyIds.NIGHT_MODE, 79 VehiclePropertyIds.HVAC_FAN_SPEED, VehiclePropertyIds.DOOR_LOCK}; 80 private static final int BACKPORTED_PROPERTY = 0x31e01111; 81 82 @Rule 83 public MockitoRule mMockitoRule = MockitoJUnit.rule(); 84 85 @Rule 86 public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build(); 87 88 @Mock 89 private Context mContext; 90 91 private PropertyHalServiceConfigs mPropertyHalServiceConfigs; 92 private static final HalPropValueBuilder PROP_VALUE_BUILDER = 93 new HalPropValueBuilder(/*isAidl=*/true); 94 //payload test 95 private static final HalPropValue GEAR_WITH_VALID_VALUE = 96 PROP_VALUE_BUILDER.build(VehicleProperty.GEAR_SELECTION, /*areaId=*/0, 97 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 98 VehicleGear.GEAR_DRIVE); 99 private static final HalPropValue GEAR_WITH_EXTRA_VALUE = 100 PROP_VALUE_BUILDER.build(VehicleProperty.GEAR_SELECTION, /*areaId=*/0, 101 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 102 new int[]{VehicleGear.GEAR_DRIVE, VehicleGear.GEAR_1}); 103 private static final HalPropValue GEAR_WITH_INVALID_VALUE = 104 PROP_VALUE_BUILDER.build(VehicleProperty.GEAR_SELECTION, /*areaId=*/0, 105 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 106 VehicleUnit.KILOPASCAL); 107 private static final HalPropValue GEAR_WITH_INVALID_TYPE_VALUE = 108 PROP_VALUE_BUILDER.build(VehicleProperty.GEAR_SELECTION, /*areaId=*/0, 109 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 110 1.0f); 111 private static final HalPropValue HVAC_FAN_DIRECTIONS_VALID = 112 PROP_VALUE_BUILDER.build(VehicleProperty.HVAC_FAN_DIRECTION, /*areaId=*/0, 113 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 114 CarHvacFanDirection.FACE | CarHvacFanDirection.FLOOR); 115 private static final HalPropValue HVAC_FAN_DIRECTIONS_INVALID = 116 PROP_VALUE_BUILDER.build(VehicleProperty.HVAC_FAN_DIRECTION, /*areaId=*/0, 117 /*timestamp=*/SystemClock.elapsedRealtimeNanos(), /*status=*/0, 118 CarHvacFanDirection.FACE | 0x100); 119 private static final HalPropValue ULTRASONCIS_SENSOR_MEASURED_DISTANCE_WITH_ERROR_VALID = 120 PROP_VALUE_BUILDER.build( 121 /*prop=*/ VehiclePropertyIds.ULTRASONICS_SENSOR_MEASURED_DISTANCE, 122 /*areaId=*/ 1, 123 /*timestamp=*/ SystemClock.elapsedRealtimeNanos(), 124 /*status=*/ 0, 125 /*values=*/ new int[]{300, 10}); 126 private static final HalPropValue ULTRASONCIS_SENSOR_MEASURED_DISTANCE_EMPTY_ARRAY_VALID = 127 PROP_VALUE_BUILDER.build( 128 /*prop=*/ VehiclePropertyIds.ULTRASONICS_SENSOR_MEASURED_DISTANCE, 129 /*areaId=*/ 1, 130 /*timestamp=*/ SystemClock.elapsedRealtimeNanos(), 131 /*status=*/ 0, 132 /*values=*/ new int[]{}); 133 134 private FakeFeatureFlagsImpl mFakeFeatureFlags; 135 136 @Before setUp()137 public void setUp() { 138 MockitoAnnotations.initMocks(this); 139 140 mFakeFeatureFlags = new FakeFeatureFlagsImpl(); 141 mFakeFeatureFlags.setFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES, true); 142 143 mPropertyHalServiceConfigs = new PropertyHalServiceConfigs(mFakeFeatureFlags); 144 145 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CAR_ENGINE_DETAILED)) 146 .thenReturn(PackageManager.PERMISSION_GRANTED); 147 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE)) 148 .thenReturn(PackageManager.PERMISSION_GRANTED); 149 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_READ_WINDSHIELD_WIPERS)) 150 .thenReturn(PackageManager.PERMISSION_DENIED); 151 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_WINDSHIELD_WIPERS)) 152 .thenReturn(PackageManager.PERMISSION_GRANTED); 153 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_ADAS_STATES)) 154 .thenReturn(PackageManager.PERMISSION_DENIED); 155 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_READ_DISPLAY_UNITS)) 156 .thenReturn(PackageManager.PERMISSION_DENIED); 157 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_DISPLAY_UNITS)) 158 .thenReturn(PackageManager.PERMISSION_GRANTED); 159 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_VENDOR_EXTENSION)) 160 .thenReturn(PackageManager.PERMISSION_GRANTED); 161 } 162 163 /** 164 * Test {@link PropertyHalServiceConfigs#checkPayload(HalPropValue)} 165 */ 166 @Test testCheckPayload()167 public void testCheckPayload() { 168 assertThat(mPropertyHalServiceConfigs.checkPayload(GEAR_WITH_VALID_VALUE)).isTrue(); 169 assertThat(mPropertyHalServiceConfigs.checkPayload(GEAR_WITH_EXTRA_VALUE)).isFalse(); 170 assertThat(mPropertyHalServiceConfigs.checkPayload(GEAR_WITH_INVALID_VALUE)).isFalse(); 171 assertThat(mPropertyHalServiceConfigs.checkPayload(GEAR_WITH_INVALID_TYPE_VALUE)).isFalse(); 172 assertThat(mPropertyHalServiceConfigs.checkPayload(HVAC_FAN_DIRECTIONS_VALID)).isTrue(); 173 assertThat(mPropertyHalServiceConfigs.checkPayload(HVAC_FAN_DIRECTIONS_INVALID)).isFalse(); 174 assertThat(mPropertyHalServiceConfigs 175 .checkPayload(ULTRASONCIS_SENSOR_MEASURED_DISTANCE_WITH_ERROR_VALID)) 176 .isTrue(); 177 assertThat(mPropertyHalServiceConfigs 178 .checkPayload(ULTRASONCIS_SENSOR_MEASURED_DISTANCE_EMPTY_ARRAY_VALID)) 179 .isTrue(); 180 } 181 182 /** 183 * Test {@link PropertyHalServiceConfigs#isReadable(Context, int)} 184 * and {@link PropertyHalServiceConfigs#isWritable(Context, int)} for system properties 185 */ 186 @Test testIsReadableWritableForSystemProperty()187 public void testIsReadableWritableForSystemProperty() { 188 assertThat(mPropertyHalServiceConfigs 189 .isReadable(mContext, VehiclePropertyIds.ENGINE_OIL_LEVEL)).isTrue(); 190 assertThat(mPropertyHalServiceConfigs 191 .isWritable(mContext, VehiclePropertyIds.ENGINE_OIL_LEVEL)).isFalse(); 192 assertThat(mPropertyHalServiceConfigs 193 .isReadable(mContext, VehiclePropertyIds.HVAC_FAN_SPEED)).isTrue(); 194 assertThat(mPropertyHalServiceConfigs 195 .isWritable(mContext, VehiclePropertyIds.HVAC_FAN_SPEED)).isTrue(); 196 assertThat(mPropertyHalServiceConfigs 197 .isReadable(mContext, VehiclePropertyIds.WINDSHIELD_WIPERS_SWITCH)).isTrue(); 198 assertThat(mPropertyHalServiceConfigs 199 .isWritable(mContext, VehiclePropertyIds.WINDSHIELD_WIPERS_SWITCH)).isTrue(); 200 assertThat(mPropertyHalServiceConfigs 201 .isReadable(mContext, VehiclePropertyIds.CRUISE_CONTROL_COMMAND)).isFalse(); 202 assertThat(mPropertyHalServiceConfigs 203 .isWritable(mContext, VehiclePropertyIds.CRUISE_CONTROL_COMMAND)).isFalse(); 204 assertThat(mPropertyHalServiceConfigs 205 .isReadable(mContext, VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS)).isTrue(); 206 assertThat(mPropertyHalServiceConfigs 207 .isWritable(mContext, VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS)).isTrue(); 208 assertThat(mPropertyHalServiceConfigs 209 .isReadable(mContext, VehiclePropertyIds.DISTANCE_DISPLAY_UNITS)).isFalse(); 210 assertThat(mPropertyHalServiceConfigs 211 .isWritable(mContext, VehiclePropertyIds.DISTANCE_DISPLAY_UNITS)).isTrue(); 212 213 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_CONTROL_CAR_CLIMATE)) 214 .thenReturn(PackageManager.PERMISSION_DENIED); 215 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_VENDOR_EXTENSION)) 216 .thenReturn(PackageManager.PERMISSION_DENIED); 217 assertThat(mPropertyHalServiceConfigs 218 .isReadable(mContext, VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS)).isFalse(); 219 assertThat(mPropertyHalServiceConfigs 220 .isWritable(mContext, VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS)).isFalse(); 221 assertThat(mPropertyHalServiceConfigs 222 .isReadable(mContext, VehiclePropertyIds.DISTANCE_DISPLAY_UNITS)).isFalse(); 223 assertThat(mPropertyHalServiceConfigs 224 .isWritable(mContext, VehiclePropertyIds.DISTANCE_DISPLAY_UNITS)).isFalse(); 225 } 226 227 /** 228 * Test for READ-WRITE system properties that write permissions are present in read permissions. 229 */ 230 @Test testWritePermissionsExistInReadPermissionsForSystemProperty()231 public void testWritePermissionsExistInReadPermissionsForSystemProperty() { 232 List<Integer> allSystemHalPropIds = mPropertyHalServiceConfigs.getAllSystemHalPropIds(); 233 for (int halPropId : allSystemHalPropIds) { 234 PermissionCondition readPermission = 235 mPropertyHalServiceConfigs.getReadPermission(halPropId); 236 if (readPermission == null) { 237 continue; 238 } 239 PermissionCondition writePermission = 240 mPropertyHalServiceConfigs.getWritePermission(halPropId); 241 242 // This skips the _DISPLAY_UNITS properties, which have multiple write permissions. 243 if (!(writePermission instanceof SinglePermission)) { 244 continue; 245 } 246 247 if (readPermission.equals(writePermission)) { 248 continue; 249 } 250 251 assertWithMessage("Read permission " + readPermission + " of property " 252 + VehiclePropertyIds.toString(halPropId) 253 + " should be an instance of AnyOfPermissions if not equal to write permission") 254 .that(readPermission instanceof AnyOfPermissions).isTrue(); 255 assertWithMessage("Read permission " + readPermission + " of property " 256 + VehiclePropertyIds.toString(halPropId) 257 + " should be equal to or contain write permission " + writePermission) 258 .that(((AnyOfPermissions) readPermission) 259 .isMetIfGranted((SinglePermission) writePermission)).isTrue(); 260 } 261 } 262 263 /** 264 * Test {@link PropertyHalServiceConfigs#isReadable(Context, int)} 265 * and {@link PropertyHalServiceConfigs#isWritable(Context, int)} for vendor properties 266 */ 267 @Test testIsReadableWritableForVendorProperty()268 public void testIsReadableWritableForVendorProperty() { 269 for (int vendorProp : VENDOR_PROPERTY_IDS) { 270 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, vendorProp)).isTrue(); 271 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, vendorProp)).isTrue(); 272 } 273 274 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_VENDOR_EXTENSION)) 275 .thenReturn(PackageManager.PERMISSION_DENIED); 276 for (int vendorProp : VENDOR_PROPERTY_IDS) { 277 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, vendorProp)).isFalse(); 278 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, vendorProp)).isFalse(); 279 } 280 } 281 282 /** 283 * Test {@link PropertyHalServiceConfigs#isSupportedProperty} 284 */ 285 @Test testIsSupportedProperty()286 public void testIsSupportedProperty() { 287 for (int vendorProp : VENDOR_PROPERTY_IDS) { 288 expectWithMessage("vendor property: " + vendorProp + " is supported").that( 289 mPropertyHalServiceConfigs.isSupportedProperty(vendorProp)).isTrue(); 290 } 291 for (int systemProp : SYSTEM_PROPERTY_IDS) { 292 expectWithMessage("system property: " + VehiclePropertyIds.toString(systemProp) 293 + " is supported").that( 294 mPropertyHalServiceConfigs.isSupportedProperty(systemProp)).isTrue(); 295 } 296 297 int fakeSystemPropId = 0x1fffffff; 298 expectWithMessage("fake system property: " + fakeSystemPropId + " is not supported").that( 299 mPropertyHalServiceConfigs.isSupportedProperty(fakeSystemPropId)).isFalse(); 300 int fakePropId = 0xffffffff; 301 expectWithMessage("fake property: " + fakePropId + " is not supported").that( 302 mPropertyHalServiceConfigs.isSupportedProperty(fakePropId)).isFalse(); 303 304 expectWithMessage("backported property: " + BACKPORTED_PROPERTY + " is supported").that( 305 mPropertyHalServiceConfigs.isSupportedProperty(BACKPORTED_PROPERTY)).isTrue(); 306 } 307 308 /** 309 * Test {@link PropertyHalServiceConfigs#customizeVendorPermission(int[])} 310 */ 311 @Test testCustomizeVendorPermission()312 public void testCustomizeVendorPermission() { 313 List<Integer> configArray = new ArrayList<>(); 314 // set up read permission and write permission to VENDOR_PROPERTY_1 315 configArray.add(VENDOR_PROPERTY_1); 316 configArray.add(VehicleVendorPermission.PERMISSION_DEFAULT); 317 configArray.add(VehicleVendorPermission.PERMISSION_NOT_ACCESSIBLE); 318 // set up read permission and write permission to VENDOR_PROPERTY_2 319 configArray.add(VENDOR_PROPERTY_2); 320 configArray.add(VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_ENGINE); 321 configArray.add(VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_ENGINE); 322 // set up read permission and write permission to VENDOR_PROPERTY_3 323 configArray.add(VENDOR_PROPERTY_3); 324 configArray.add(VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_INFO); 325 configArray.add(VehicleVendorPermission.PERMISSION_DEFAULT); 326 // set up read permission and write permission to BACKPORTED_PROPERTY 327 configArray.add(BACKPORTED_PROPERTY); 328 configArray.add(VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_INFO); 329 configArray.add(VehicleVendorPermission.PERMISSION_DEFAULT); 330 331 mPropertyHalServiceConfigs.customizeVendorPermission(toIntArray(configArray)); 332 333 assertThat(mPropertyHalServiceConfigs.getReadPermission(VENDOR_PROPERTY_1) 334 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 335 assertThat(mPropertyHalServiceConfigs.getWritePermission(VENDOR_PROPERTY_1)).isNull(); 336 337 assertThat(mPropertyHalServiceConfigs.getReadPermission(VENDOR_PROPERTY_2) 338 .toString()).isEqualTo(android.car.hardware.property 339 .VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_ENGINE); 340 assertThat(mPropertyHalServiceConfigs.getWritePermission(VENDOR_PROPERTY_2) 341 .toString()).isEqualTo(android.car.hardware.property 342 .VehicleVendorPermission.PERMISSION_SET_CAR_VENDOR_CATEGORY_ENGINE); 343 344 assertThat(mPropertyHalServiceConfigs.getReadPermission(VENDOR_PROPERTY_3) 345 .toString()).isEqualTo(android.car.hardware.property 346 .VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_INFO); 347 assertThat(mPropertyHalServiceConfigs.getWritePermission(VENDOR_PROPERTY_3) 348 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 349 350 assertThat(mPropertyHalServiceConfigs.getReadPermission(VENDOR_PROPERTY_4) 351 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 352 assertThat(mPropertyHalServiceConfigs.getWritePermission(VENDOR_PROPERTY_4) 353 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 354 355 assertThat(mPropertyHalServiceConfigs.getReadPermission(BACKPORTED_PROPERTY) 356 .toString()).isEqualTo(android.car.hardware.property 357 .VehicleVendorPermission.PERMISSION_GET_CAR_VENDOR_CATEGORY_INFO); 358 assertThat(mPropertyHalServiceConfigs.getWritePermission(BACKPORTED_PROPERTY) 359 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 360 361 when(mContext.checkCallingOrSelfPermission(Car.PERMISSION_VENDOR_EXTENSION)) 362 .thenReturn(PackageManager.PERMISSION_GRANTED); 363 when(mContext.checkCallingOrSelfPermission( 364 android.car.hardware.property.VehicleVendorPermission 365 .PERMISSION_GET_CAR_VENDOR_CATEGORY_ENGINE)) 366 .thenReturn(PackageManager.PERMISSION_GRANTED); 367 when(mContext.checkCallingOrSelfPermission( 368 android.car.hardware.property.VehicleVendorPermission 369 .PERMISSION_SET_CAR_VENDOR_CATEGORY_ENGINE)) 370 .thenReturn(PackageManager.PERMISSION_GRANTED); 371 when(mContext.checkCallingOrSelfPermission( 372 android.car.hardware.property.VehicleVendorPermission 373 .PERMISSION_GET_CAR_VENDOR_CATEGORY_INFO)) 374 .thenReturn(PackageManager.PERMISSION_DENIED); 375 376 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, VENDOR_PROPERTY_1)).isTrue(); 377 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, VENDOR_PROPERTY_1)).isFalse(); 378 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, VENDOR_PROPERTY_2)).isTrue(); 379 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, VENDOR_PROPERTY_2)).isTrue(); 380 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, VENDOR_PROPERTY_3)).isFalse(); 381 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, VENDOR_PROPERTY_3)).isTrue(); 382 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, VENDOR_PROPERTY_4)).isTrue(); 383 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, VENDOR_PROPERTY_4)).isTrue(); 384 assertThat(mPropertyHalServiceConfigs.isReadable(mContext, BACKPORTED_PROPERTY)).isFalse(); 385 assertThat(mPropertyHalServiceConfigs.isWritable(mContext, BACKPORTED_PROPERTY)).isTrue(); 386 } 387 388 @Test testCustomizeVendorPermission_systemPropertyNotAllowed()389 public void testCustomizeVendorPermission_systemPropertyNotAllowed() { 390 List<Integer> configArray = new ArrayList<>(); 391 configArray.add(VehiclePropertyIds.CURRENT_GEAR); 392 configArray.add( 393 VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_ENGINE); 394 configArray.add( 395 VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_ENGINE); 396 397 assertThrows(IllegalArgumentException.class, () -> 398 mPropertyHalServiceConfigs.customizeVendorPermission(toIntArray(configArray))); 399 } 400 401 @Test testCustomizeVendorPermission_overrideNotAllowed()402 public void testCustomizeVendorPermission_overrideNotAllowed() { 403 List<Integer> configArray = new ArrayList<>(); 404 configArray.add(VENDOR_PROPERTY_1); 405 configArray.add(VehicleVendorPermission.PERMISSION_DEFAULT); 406 configArray.add(VehicleVendorPermission.PERMISSION_NOT_ACCESSIBLE); 407 // This must not take effect. 408 configArray.add(VENDOR_PROPERTY_1); 409 configArray.add(VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_ENGINE); 410 configArray.add(VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_ENGINE); 411 412 mPropertyHalServiceConfigs.customizeVendorPermission(toIntArray(configArray)); 413 414 assertThat(mPropertyHalServiceConfigs.getReadPermission(VENDOR_PROPERTY_1) 415 .toString()).isEqualTo(Car.PERMISSION_VENDOR_EXTENSION); 416 assertThat(mPropertyHalServiceConfigs.getWritePermission(VENDOR_PROPERTY_1)).isNull(); 417 } 418 strToInputStream(String str)419 private InputStream strToInputStream(String str) { 420 return new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8)); 421 } 422 423 @Test testParseJsonConfig_validConfig()424 public void testParseJsonConfig_validConfig() throws Exception { 425 InputStream is = strToInputStream(""" 426 { 427 'version': 1, 428 'properties': { 429 'PROP_NAME': { 430 'propertyName': 'PROP_NAME', 431 'propertyId': 1234, 432 'vhalPropertyId': 2345, 433 'description': 'DESCRIPTION', 434 'readPermission': { 435 'type': 'anyOf', 436 'value': [ 437 { 438 'type': 'single', 439 'value': 'PERM1' 440 }, 441 { 442 'type': 'single', 443 'value': 'PERM2' 444 } 445 ] 446 }, 447 'writePermission': { 448 'type': 'allOf', 449 'value': [ 450 { 451 'type': 'single', 452 'value': 'PERM1' 453 }, 454 { 455 'type': 'single', 456 'value': 'PERM2' 457 } 458 ] 459 }, 460 'dataEnums': [0, 1, 2] 461 } 462 } 463 } 464 """); 465 CarSvcPropertyConfig expectedConfig = new CarSvcPropertyConfig(); 466 expectedConfig.propertyId = 1234; 467 expectedConfig.halPropId = 2345; 468 expectedConfig.propertyName = "PROP_NAME"; 469 expectedConfig.description = "DESCRIPTION"; 470 expectedConfig.permissions = new PropertyPermissions.Builder() 471 .setReadPermission(new AnyOfPermissions( 472 new SinglePermission("PERM1"), 473 new SinglePermission("PERM2") 474 )) 475 .setWritePermission(new AllOfPermissions( 476 new SinglePermission("PERM1"), 477 new SinglePermission("PERM2") 478 )) 479 .build(); 480 expectedConfig.dataEnums = new ArraySet<>(Set.of(0, 1, 2)); 481 482 SparseArray<CarSvcPropertyConfig> configs = mPropertyHalServiceConfigs.parseJsonConfig( 483 is, /* path= */ "test"); 484 485 assertWithMessage("expect one config parsed").that(configs.size()).isEqualTo(1); 486 CarSvcPropertyConfig config = configs.get(2345); 487 assertThat(config).isNotNull(); 488 assertThat(config).isEqualTo(expectedConfig); 489 } 490 491 @Test testParseJsonConfig_halPropIdDefaultEqualPropId()492 public void testParseJsonConfig_halPropIdDefaultEqualPropId() throws Exception { 493 InputStream is = strToInputStream(""" 494 { 495 "version": 1, 496 "properties": { 497 "PROP_NAME": { 498 "propertyName": "PROP_NAME", 499 "propertyId": 1234, 500 "description": "DESCRIPTION", 501 "readPermission": { 502 "type": "single", 503 "value": "PERM1" 504 } 505 } 506 } 507 } 508 """); 509 CarSvcPropertyConfig expectedConfig = new CarSvcPropertyConfig(); 510 expectedConfig.propertyId = 1234; 511 expectedConfig.halPropId = 1234; 512 expectedConfig.propertyName = "PROP_NAME"; 513 expectedConfig.description = "DESCRIPTION"; 514 expectedConfig.permissions = new PropertyPermissions.Builder() 515 .setReadPermission(new SinglePermission("PERM1")) 516 .build(); 517 518 SparseArray<CarSvcPropertyConfig> configs = mPropertyHalServiceConfigs.parseJsonConfig( 519 is, /* path= */ "test"); 520 CarSvcPropertyConfig config = configs.get(1234); 521 assertThat(config).isNotNull(); 522 assertThat(config).isEqualTo(expectedConfig); 523 } 524 525 @Test testParseJsonConfig_dataFlags()526 public void testParseJsonConfig_dataFlags() throws Exception { 527 InputStream is = strToInputStream(""" 528 { 529 "version": 1, 530 "properties": { 531 "PROP_NAME": { 532 "propertyName": "PROP_NAME", 533 "propertyId": 1234, 534 "description": "DESCRIPTION", 535 "readPermission": { 536 "type": "single", 537 "value": "PERM1" 538 }, 539 "dataFlags": [1, 2, 4, 8] 540 } 541 } 542 } 543 """); 544 CarSvcPropertyConfig expectedConfig = new CarSvcPropertyConfig(); 545 expectedConfig.propertyId = 1234; 546 expectedConfig.halPropId = 1234; 547 expectedConfig.propertyName = "PROP_NAME"; 548 expectedConfig.description = "DESCRIPTION"; 549 expectedConfig.permissions = new PropertyPermissions.Builder() 550 .setReadPermission(new SinglePermission("PERM1")) 551 .build(); 552 // Bit: 1111 553 expectedConfig.validBitFlag = 15; 554 555 SparseArray<CarSvcPropertyConfig> configs = mPropertyHalServiceConfigs.parseJsonConfig( 556 is, /* path= */ "test"); 557 CarSvcPropertyConfig config = configs.get(1234); 558 assertThat(config).isNotNull(); 559 assertThat(config).isEqualTo(expectedConfig); 560 } 561 562 @Test testParseJsonConfig_ignoreDeprecate()563 public void testParseJsonConfig_ignoreDeprecate() throws Exception { 564 InputStream is = strToInputStream(""" 565 { 566 "version": 1, 567 "properties": { 568 "OLD_PROP": { 569 "propertyName": "OLD_PROP", 570 "propertyId": 12345, 571 "deprecated": true 572 }, 573 "PROP_NAME": { 574 "propertyName": "PROP_NAME", 575 "propertyId": 1234, 576 "vhalPropertyId": 2345, 577 "description": "DESCRIPTION", 578 "readPermission": { 579 "type": "single", 580 "value": "PERM1" 581 } 582 } 583 } 584 } 585 """); 586 587 SparseArray<CarSvcPropertyConfig> configs = mPropertyHalServiceConfigs.parseJsonConfig( 588 is, /* path= */ "test"); 589 590 assertWithMessage("deprecated property must be ignored").that(configs.get(12345)).isNull(); 591 assertWithMessage("must continue parsing non deprecated property").that(configs.get(2345)) 592 .isNotNull(); 593 } 594 595 @Test testParseJsonConfig_cannotReadFromStream()596 public void testParseJsonConfig_cannotReadFromStream() throws Exception { 597 InputStream is = mock(InputStream.class); 598 when(is.readAllBytes()).thenThrow(new IOException()); 599 600 assertThrows(IllegalArgumentException.class, () -> 601 mPropertyHalServiceConfigs.parseJsonConfig(is, /* path= */ "test")); 602 } 603 604 @Test testParseJsonConfig_invalidJsonFormat()605 public void testParseJsonConfig_invalidJsonFormat() throws Exception { 606 InputStream is = strToInputStream("{"); 607 608 assertThrows(IllegalArgumentException.class, () -> 609 mPropertyHalServiceConfigs.parseJsonConfig(is, /* path= */ "test")); 610 } 611 612 @Test testParseJsonConfig_missingPropertyIdField()613 public void testParseJsonConfig_missingPropertyIdField() throws Exception { 614 InputStream is = strToInputStream(""" 615 { 616 "version": 1, 617 "properties": { 618 "PROP_NAME": { 619 "propertyName": "PROP_NAME", 620 "vhalPropertyId": 2345, 621 "description": "DESCRIPTION", 622 "readPermission": { 623 "type": "single", 624 "value": "PERM1" 625 } 626 } 627 } 628 } 629 """); 630 631 assertThrows(IllegalArgumentException.class, () -> 632 mPropertyHalServiceConfigs.parseJsonConfig(is, /* path= */ "test")); 633 } 634 635 @Test testParseJsonConfig_noReadOrWritePermission()636 public void testParseJsonConfig_noReadOrWritePermission() throws Exception { 637 InputStream is = strToInputStream(""" 638 { 639 "version": 1, 640 "properties": { 641 "PROP_NAME": { 642 "propertyName": "PROP_NAME", 643 "propertyId": 1234, 644 "description": "DESCRIPTION", 645 "dataFlags": [1, 2, 4, 8] 646 } 647 } 648 } 649 """); 650 651 assertThrows(IllegalArgumentException.class, () -> 652 mPropertyHalServiceConfigs.parseJsonConfig(is, /* path= */ "test")); 653 } 654 655 @Test testManagerToHalPropId()656 public void testManagerToHalPropId() { 657 assertThat(mPropertyHalServiceConfigs.managerToHalPropId( 658 VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS)).isEqualTo( 659 VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS); 660 } 661 662 @Test testHalToManagerPropId()663 public void testHalToManagerPropId() { 664 assertThat(mPropertyHalServiceConfigs.halToManagerPropId( 665 VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS)).isEqualTo( 666 VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS); 667 } 668 669 670 @Test testVicVehiclePropertiesFlagDisabled()671 public void testVicVehiclePropertiesFlagDisabled() throws Exception { 672 int vicProperty = VehiclePropertyIds.DRIVER_DROWSINESS_ATTENTION_SYSTEM_ENABLED; 673 mFakeFeatureFlags.setFlag(Flags.FLAG_ANDROID_VIC_VEHICLE_PROPERTIES, false); 674 675 mPropertyHalServiceConfigs = new PropertyHalServiceConfigs(mFakeFeatureFlags); 676 677 assertThat(mPropertyHalServiceConfigs.getAllSystemHalPropIds()).doesNotContain(vicProperty); 678 assertThat(mPropertyHalServiceConfigs.isSupportedProperty(vicProperty)).isFalse(); 679 } 680 } 681