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 android.car.hardware.property; 18 19 import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; 20 import static android.car.VehiclePropertyIds.FUEL_DOOR_OPEN; 21 import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_SET; 22 import static android.car.VehiclePropertyIds.INFO_EV_CONNECTOR_TYPE; 23 import static android.car.VehiclePropertyIds.INFO_FUEL_DOOR_LOCATION; 24 import static android.car.VehiclePropertyIds.INITIAL_USER_INFO; 25 import static android.car.VehiclePropertyIds.INVALID; 26 import static android.car.hardware.property.CarPropertyManager.GetPropertyResult; 27 import static android.car.hardware.property.CarPropertyManager.PropertyAsyncError; 28 import static android.car.hardware.property.CarPropertyManager.SENSOR_RATE_ONCHANGE; 29 import static android.car.hardware.property.CarPropertyManager.SetPropertyRequest; 30 import static android.car.hardware.property.CarPropertyManager.SetPropertyResult; 31 32 import static com.android.car.internal.property.CarPropertyHelper.SYNC_OP_LIMIT_TRY_AGAIN; 33 import static com.android.car.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; 34 35 import static com.google.common.truth.Truth.assertThat; 36 import static com.google.common.truth.Truth.assertWithMessage; 37 38 import static org.junit.Assert.assertThrows; 39 import static org.mockito.ArgumentMatchers.any; 40 import static org.mockito.ArgumentMatchers.anyInt; 41 import static org.mockito.ArgumentMatchers.anyLong; 42 import static org.mockito.ArgumentMatchers.eq; 43 import static org.mockito.Mockito.clearInvocations; 44 import static org.mockito.Mockito.doAnswer; 45 import static org.mockito.Mockito.doNothing; 46 import static org.mockito.Mockito.doThrow; 47 import static org.mockito.Mockito.mock; 48 import static org.mockito.Mockito.never; 49 import static org.mockito.Mockito.timeout; 50 import static org.mockito.Mockito.times; 51 import static org.mockito.Mockito.verify; 52 import static org.mockito.Mockito.when; 53 54 import android.car.VehicleAreaSeat; 55 import android.car.VehicleAreaType; 56 import android.car.VehiclePropertyIds; 57 import android.car.feature.FeatureFlags; 58 import android.car.feature.Flags; 59 import android.car.hardware.CarPropertyConfig; 60 import android.car.hardware.CarPropertyValue; 61 import android.car.test.AbstractExpectableTestCase; 62 import android.content.Context; 63 import android.content.pm.ApplicationInfo; 64 import android.os.Build; 65 import android.os.CancellationSignal; 66 import android.os.Handler; 67 import android.os.Looper; 68 import android.os.RemoteException; 69 import android.os.ServiceSpecificException; 70 import android.platform.test.annotations.EnableFlags; 71 import android.platform.test.annotations.IgnoreUnderRavenwood; 72 import android.platform.test.flag.junit.SetFlagsRule; 73 import android.platform.test.ravenwood.RavenwoodRule; 74 import android.util.ArraySet; 75 import android.util.SparseArray; 76 77 import com.android.car.internal.ICarBase; 78 import com.android.car.internal.property.AsyncPropertyServiceRequest; 79 import com.android.car.internal.property.AsyncPropertyServiceRequestList; 80 import com.android.car.internal.property.CarPropertyConfigList; 81 import com.android.car.internal.property.CarPropertyErrorCodes; 82 import com.android.car.internal.property.CarSubscription; 83 import com.android.car.internal.property.GetPropertyConfigListResult; 84 import com.android.car.internal.property.GetSetValueResult; 85 import com.android.car.internal.property.GetSetValueResultList; 86 import com.android.car.internal.property.IAsyncPropertyResultCallback; 87 import com.android.car.internal.property.ISupportedValuesChangeCallback; 88 import com.android.car.internal.property.MinMaxSupportedPropertyValue; 89 import com.android.car.internal.property.PropIdAreaId; 90 import com.android.car.internal.property.RawPropertyValue; 91 import com.android.car.internal.util.IntArray; 92 93 import org.junit.Before; 94 import org.junit.Rule; 95 import org.junit.Test; 96 import org.junit.runner.RunWith; 97 import org.mockito.ArgumentCaptor; 98 import org.mockito.Captor; 99 import org.mockito.Mock; 100 import org.mockito.junit.MockitoJUnitRunner; 101 102 import java.time.Duration; 103 import java.util.ArrayList; 104 import java.util.List; 105 import java.util.Set; 106 import java.util.concurrent.Executor; 107 108 /** 109 * <p>This class contains unit tests for the {@link CarPropertyManager}. 110 */ 111 @RunWith(MockitoJUnitRunner.class) 112 public final class CarPropertyManagerUnitTest extends AbstractExpectableTestCase { 113 // Required to set the process ID and set the "main" thread for this test, otherwise 114 // getMainLooper will return null. 115 @Rule 116 public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() 117 .setProcessApp() 118 .setProvideMainThread(true) 119 .build(); 120 121 @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 122 123 // Defined as vendor property. 124 private static final int VENDOR_CONTINUOUS_PROPERTY = 0x21100111; 125 private static final int VENDOR_ON_CHANGE_PROPERTY = 0x21100222; 126 private static final int VENDOR_STATIC_PROPERTY = 0x21100333; 127 128 private static final int BOOLEAN_PROP = FUEL_DOOR_OPEN; 129 private static final int INT32_PROP = INFO_FUEL_DOOR_LOCATION; 130 private static final int INT32_VEC_PROP = INFO_EV_CONNECTOR_TYPE; 131 private static final int FLOAT_PROP = HVAC_TEMPERATURE_SET; 132 133 private static final float MIN_UPDATE_RATE_HZ = 10; 134 private static final float MAX_UPDATE_RATE_HZ = 100; 135 private static final float FIRST_UPDATE_RATE_HZ = 50; 136 private static final float LARGER_UPDATE_RATE_HZ = 50.1f; 137 private static final float SMALLER_UPDATE_RATE_HZ = 49.9f; 138 139 private static final int VENDOR_ERROR_CODE = 0x2; 140 private static final int VENDOR_ERROR_CODE_SHIFT = 16; 141 private static final int UNKNOWN_ERROR = -101; 142 143 private static final long TEST_TIMESTAMP = 1234; 144 145 private Handler mMainHandler; 146 147 private CarPropertyConfig mContinuousCarPropertyConfig; 148 private CarPropertyConfig mOnChangeCarPropertyConfig; 149 private CarPropertyConfig mStaticCarPropertyConfig; 150 private final SparseArray<CarPropertyConfig> mCarPropertyConfigsById = new SparseArray<>(); 151 private final ArraySet<Integer> mUnsupportedPropIds = new ArraySet<>(); 152 private final ArraySet<Integer> mMissingPermissionPropIds = new ArraySet<>(); 153 154 @Mock 155 private ICarBase mCar; 156 @Mock 157 private ApplicationInfo mApplicationInfo; 158 @Mock 159 private ICarProperty mICarProperty; 160 @Mock 161 private Context mContext; 162 @Mock 163 private CarPropertyManager.CarPropertyEventCallback mCarPropertyEventCallback; 164 @Mock 165 private CarPropertyManager.CarPropertyEventCallback mCarPropertyEventCallback2; 166 @Mock 167 private CarPropertyManager.GetPropertyCallback mGetPropertyCallback; 168 @Mock 169 private CarPropertyManager.SetPropertyCallback mSetPropertyCallback; 170 @Mock 171 private Executor mMockExecutor1; 172 @Mock 173 private Executor mMockExecutor2; 174 @Mock 175 private FeatureFlags mFeatureFlags; 176 @Mock 177 private CarPropertyManager.SupportedValuesChangeCallback mSupportedValuesChangeCallback; 178 @Mock 179 private CarPropertyManager.SupportedValuesChangeCallback mSupportedValuesChangeCallback2; 180 181 @Captor 182 private ArgumentCaptor<Integer> mPropertyIdCaptor; 183 @Captor 184 private ArgumentCaptor<List> mCarSubscriptionCaptor; 185 @Captor 186 private ArgumentCaptor<AsyncPropertyServiceRequestList> mAsyncPropertyServiceRequestCaptor; 187 @Captor 188 private ArgumentCaptor<PropertyAsyncError> mPropertyAsyncErrorCaptor; 189 @Captor 190 private ArgumentCaptor<GetPropertyResult<?>> mGetPropertyResultCaptor; 191 @Captor 192 private ArgumentCaptor<SetPropertyResult> mSetPropertyResultCaptor; 193 private CarPropertyManager mCarPropertyManager; 194 combineErrors(int systemError, int vendorError)195 private static int combineErrors(int systemError, int vendorError) { 196 return vendorError << VENDOR_ERROR_CODE_SHIFT | systemError; 197 } 198 createErrorCarPropertyEventList()199 private static List<CarPropertyEvent> createErrorCarPropertyEventList() { 200 CarPropertyValue<Integer> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 201 CarPropertyValue.STATUS_AVAILABLE, 0, -1); 202 CarPropertyEvent carPropertyEvent = new CarPropertyEvent( 203 CarPropertyEvent.PROPERTY_EVENT_ERROR, value, 204 CarPropertyManager.CAR_SET_PROPERTY_ERROR_CODE_UNKNOWN); 205 return List.of(carPropertyEvent); 206 } 207 createCarPropertyEventList()208 private static List<CarPropertyEvent> createCarPropertyEventList() { 209 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 210 CarPropertyEvent carPropertyEvent = new CarPropertyEvent( 211 CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value); 212 return List.of(carPropertyEvent); 213 } 214 createCarSubscriptionOption(int propertyId, int[] areaId, float updateRateHz)215 private static CarSubscription createCarSubscriptionOption(int propertyId, 216 int[] areaId, float updateRateHz) { 217 return createCarSubscriptionOption(propertyId, areaId, updateRateHz, 218 /* enableVur= */ false); 219 } 220 createCarSubscriptionOption(int propertyId, int[] areaId, float updateRateHz, boolean enableVur)221 private static CarSubscription createCarSubscriptionOption(int propertyId, 222 int[] areaId, float updateRateHz, boolean enableVur) { 223 CarSubscription options = new CarSubscription(); 224 options.propertyId = propertyId; 225 options.areaIds = areaId; 226 options.updateRateHz = updateRateHz; 227 options.enableVariableUpdateRate = enableVur; 228 return options; 229 } 230 addCarPropertyConfig(CarPropertyConfig config)231 private void addCarPropertyConfig(CarPropertyConfig config) { 232 mCarPropertyConfigsById.put(config.getPropertyId(), config); 233 } 234 setPropIdWithoutPermission(int propId)235 private void setPropIdWithoutPermission(int propId) { 236 mCarPropertyConfigsById.remove(propId); 237 mMissingPermissionPropIds.add(propId); 238 } 239 setPropIdWithoutConfig(int propId)240 private void setPropIdWithoutConfig(int propId) { 241 mCarPropertyConfigsById.remove(propId); 242 mUnsupportedPropIds.add(propId); 243 } 244 245 @Before setUp()246 public void setUp() throws RemoteException { 247 mMainHandler = new Handler(Looper.getMainLooper()); 248 when(mCar.getContext()).thenReturn(mContext); 249 when(mCar.getEventHandler()).thenReturn(mMainHandler); 250 when(mCar.handleRemoteExceptionFromCarService(any(RemoteException.class), any())) 251 .thenAnswer((inv) -> { 252 return inv.getArgument(1); 253 }); 254 255 mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; 256 when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); 257 258 mContinuousCarPropertyConfig = CarPropertyConfig.newBuilder(Integer.class, 259 VENDOR_CONTINUOUS_PROPERTY, VEHICLE_AREA_TYPE_GLOBAL) 260 .setChangeMode(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) 261 .setMinSampleRate(MIN_UPDATE_RATE_HZ) 262 .setMaxSampleRate(MAX_UPDATE_RATE_HZ) 263 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(0) 264 .setSupportVariableUpdateRate(true).build()) 265 .build(); 266 mOnChangeCarPropertyConfig = CarPropertyConfig.newBuilder(Integer.class, 267 VENDOR_ON_CHANGE_PROPERTY, VEHICLE_AREA_TYPE_GLOBAL) 268 .setChangeMode(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_ONCHANGE) 269 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(0).build()) 270 .build(); 271 mStaticCarPropertyConfig = CarPropertyConfig.newBuilder(Integer.class, 272 VENDOR_STATIC_PROPERTY, VEHICLE_AREA_TYPE_GLOBAL) 273 .setChangeMode(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_STATIC) 274 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(0).build()) 275 .build(); 276 277 when(mICarProperty.getPropertyConfigList(any())).thenAnswer((invocation) -> { 278 Object[] args = invocation.getArguments(); 279 int[] propIds = (int[]) args[0]; 280 GetPropertyConfigListResult result = new GetPropertyConfigListResult(); 281 IntArray unsupportedPropIds = new IntArray(); 282 IntArray missingPermissionPropIds = new IntArray(); 283 List<CarPropertyConfig> configs = new ArrayList<>(); 284 for (int propId : propIds) { 285 if (mUnsupportedPropIds.contains(propId)) { 286 unsupportedPropIds.add(propId); 287 continue; 288 } 289 if (mMissingPermissionPropIds.contains(propId)) { 290 missingPermissionPropIds.add(propId); 291 continue; 292 } 293 var config = mCarPropertyConfigsById.get(propId); 294 if (config == null) { 295 unsupportedPropIds.add(propId); 296 continue; 297 } 298 configs.add(config); 299 } 300 301 result.carPropertyConfigList = new CarPropertyConfigList(configs); 302 result.unsupportedPropIds = unsupportedPropIds.toArray(); 303 result.missingPermissionPropIds = missingPermissionPropIds.toArray(); 304 return result; 305 }); 306 307 addCarPropertyConfig(mContinuousCarPropertyConfig); 308 addCarPropertyConfig(mOnChangeCarPropertyConfig); 309 addCarPropertyConfig(mStaticCarPropertyConfig); 310 when(mICarProperty.getSupportedNoReadPermPropIds(any())).thenReturn(new int[0]); 311 mCarPropertyManager = new CarPropertyManager(mCar, mICarProperty); 312 // Enable the features. 313 when(mFeatureFlags.variableUpdateRate()).thenReturn(true); 314 when(mFeatureFlags.handlePropertyEventsInBinderThread()).thenReturn(true); 315 when(mFeatureFlags.alwaysSendInitialValueEvent()).thenReturn(true); 316 317 mCarPropertyManager.setFeatureFlags(mFeatureFlags); 318 } 319 320 @Test testGetProperty_returnsValue()321 public void testGetProperty_returnsValue() throws RemoteException { 322 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 323 324 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 325 326 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)).isEqualTo(value); 327 } 328 329 @Test testGetProperty_unsupportedProperty_exceptionAtU()330 public void testGetProperty_unsupportedProperty_exceptionAtU() throws Exception { 331 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 332 333 assertThrows(IllegalArgumentException.class, 334 () -> mCarPropertyManager.getProperty(INVALID, 0)); 335 } 336 337 @Test testGetProperty_unsupportedProperty_nullBeforeU()338 public void testGetProperty_unsupportedProperty_nullBeforeU() throws Exception { 339 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 340 341 assertThat(mCarPropertyManager.getProperty(INVALID, 0)).isNull(); 342 } 343 344 @Test testGetProperty_unsupportedPropertyInSvc_exceptionAtU()345 public void testGetProperty_unsupportedPropertyInSvc_exceptionAtU() throws Exception { 346 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 347 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 348 new IllegalArgumentException()); 349 350 assertThrows(IllegalArgumentException.class, 351 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 352 } 353 354 @Test testGetProperty_unsupportedPropertyInSvc_nullBeforeU()355 public void testGetProperty_unsupportedPropertyInSvc_nullBeforeU() throws Exception { 356 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 357 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 358 new IllegalArgumentException()); 359 360 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)).isNull(); 361 } 362 363 @Test testGetProperty_syncOpTryAgain()364 public void testGetProperty_syncOpTryAgain() throws RemoteException { 365 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 366 367 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 368 new ServiceSpecificException(SYNC_OP_LIMIT_TRY_AGAIN)).thenReturn(value); 369 370 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)).isEqualTo(value); 371 verify(mICarProperty, times(2)).getProperty(HVAC_TEMPERATURE_SET, 0); 372 } 373 374 @Test testGetProperty_syncOpTryAgain_exceedRetryCountLimit()375 public void testGetProperty_syncOpTryAgain_exceedRetryCountLimit() throws RemoteException { 376 // Car service will throw CarInternalException with version >= R. 377 setAppTargetSdk(Build.VERSION_CODES.R); 378 379 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 380 new ServiceSpecificException(SYNC_OP_LIMIT_TRY_AGAIN)); 381 382 assertThrows(CarInternalErrorException.class, () -> 383 mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 384 verify(mICarProperty, times(10)).getProperty(HVAC_TEMPERATURE_SET, 0); 385 } 386 setAppTargetSdk(int appTargetSdk)387 private void setAppTargetSdk(int appTargetSdk) { 388 mApplicationInfo.targetSdkVersion = appTargetSdk; 389 mCarPropertyManager = new CarPropertyManager(mCar, mICarProperty); 390 mCarPropertyManager.setFeatureFlags(mFeatureFlags); 391 } 392 393 @Test testGetProperty_notAvailableBeforeR()394 public void testGetProperty_notAvailableBeforeR() throws Exception { 395 setAppTargetSdk(Build.VERSION_CODES.Q); 396 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 397 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE)); 398 399 assertThrows(IllegalStateException.class, 400 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 401 } 402 403 @Test testGetProperty_notAvailableEqualAfterR()404 public void testGetProperty_notAvailableEqualAfterR() throws Exception { 405 setAppTargetSdk(Build.VERSION_CODES.R); 406 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 407 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE)); 408 409 assertThrows(PropertyNotAvailableException.class, 410 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 411 } 412 413 @Test testGetProperty_tryAgainBeforeR()414 public void testGetProperty_tryAgainBeforeR() throws Exception { 415 setAppTargetSdk(Build.VERSION_CODES.Q); 416 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 417 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 418 419 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)).isNull(); 420 } 421 422 @Test testGetProperty_tryAgainEqualAfterR()423 public void testGetProperty_tryAgainEqualAfterR() throws Exception { 424 setAppTargetSdk(Build.VERSION_CODES.R); 425 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 426 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 427 428 assertThrows(PropertyNotAvailableAndRetryException.class, 429 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 430 } 431 432 @Test testGetProperty_accessDeniedBeforeR()433 public void testGetProperty_accessDeniedBeforeR() throws Exception { 434 setAppTargetSdk(Build.VERSION_CODES.Q); 435 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 436 new ServiceSpecificException(VehicleHalStatusCode.STATUS_ACCESS_DENIED)); 437 438 assertThrows(IllegalStateException.class, 439 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 440 } 441 442 @Test testGetProperty_accessDeniedEqualAfterR()443 public void testGetProperty_accessDeniedEqualAfterR() throws Exception { 444 setAppTargetSdk(Build.VERSION_CODES.R); 445 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 446 new ServiceSpecificException(VehicleHalStatusCode.STATUS_ACCESS_DENIED)); 447 448 assertThrows(PropertyAccessDeniedSecurityException.class, 449 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 450 } 451 452 @Test testGetProperty_internalErrorBeforeR()453 public void testGetProperty_internalErrorBeforeR() throws Exception { 454 setAppTargetSdk(Build.VERSION_CODES.Q); 455 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 456 new ServiceSpecificException(VehicleHalStatusCode.STATUS_INTERNAL_ERROR)); 457 458 assertThrows(IllegalStateException.class, 459 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 460 } 461 462 @Test testGetProperty_internalErrorEqualAfterR()463 public void testGetProperty_internalErrorEqualAfterR() throws Exception { 464 setAppTargetSdk(Build.VERSION_CODES.R); 465 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 466 new ServiceSpecificException(VehicleHalStatusCode.STATUS_INTERNAL_ERROR)); 467 468 assertThrows(CarInternalErrorException.class, 469 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 470 } 471 472 @Test testGetProperty_internalErrorEqualAfterU_withVendorErrorCode()473 public void testGetProperty_internalErrorEqualAfterU_withVendorErrorCode() throws Exception { 474 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 475 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 476 new ServiceSpecificException(combineErrors( 477 VehicleHalStatusCode.STATUS_INTERNAL_ERROR, VENDOR_ERROR_CODE))); 478 479 CarInternalErrorException exception = assertThrows(CarInternalErrorException.class, 480 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 481 482 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 483 } 484 485 @Test testGetProperty_unknownErrorBeforeR()486 public void testGetProperty_unknownErrorBeforeR() throws Exception { 487 setAppTargetSdk(Build.VERSION_CODES.Q); 488 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 489 new ServiceSpecificException(UNKNOWN_ERROR)); 490 491 assertThrows(IllegalStateException.class, 492 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 493 } 494 495 @Test testGetProperty_unknownErrorEqualAfterR()496 public void testGetProperty_unknownErrorEqualAfterR() throws Exception { 497 setAppTargetSdk(Build.VERSION_CODES.R); 498 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 499 new ServiceSpecificException(UNKNOWN_ERROR)); 500 501 assertThrows(CarInternalErrorException.class, 502 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 503 } 504 505 @Test testGetProperty_returnsValueWithUnavailableStatusBeforeU()506 public void testGetProperty_returnsValueWithUnavailableStatusBeforeU() throws RemoteException { 507 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 508 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 509 CarPropertyValue.STATUS_UNAVAILABLE, TEST_TIMESTAMP, 17.0f); 510 511 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 512 513 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, /*areaId=*/ 0)).isEqualTo( 514 new CarPropertyValue<>(HVAC_TEMPERATURE_SET, /*areaId=*/0, 515 CarPropertyValue.STATUS_UNAVAILABLE, TEST_TIMESTAMP, 17.0f)); 516 } 517 518 @Test testGetProperty_valueWithUnavailableStatusThrowsAfterU()519 public void testGetProperty_valueWithUnavailableStatusThrowsAfterU() throws RemoteException { 520 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 521 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 522 CarPropertyValue.STATUS_UNAVAILABLE, TEST_TIMESTAMP, 17.0f); 523 524 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 525 526 assertThrows(PropertyNotAvailableException.class, 527 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 528 } 529 530 @Test testGetProperty_returnsValueWithErrorStatusBeforeU()531 public void testGetProperty_returnsValueWithErrorStatusBeforeU() throws RemoteException { 532 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 533 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 534 CarPropertyValue.STATUS_ERROR, TEST_TIMESTAMP, 17.0f); 535 536 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 537 538 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, /*areaId=*/ 0)).isEqualTo( 539 new CarPropertyValue<>(HVAC_TEMPERATURE_SET, /*areaId=*/0, 540 CarPropertyValue.STATUS_ERROR, TEST_TIMESTAMP, 17.0f)); 541 } 542 543 @Test testGetProperty_valueWithErrorStatusThrowsAfterU()544 public void testGetProperty_valueWithErrorStatusThrowsAfterU() throws RemoteException { 545 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 546 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 547 CarPropertyValue.STATUS_ERROR, TEST_TIMESTAMP, 17.0f); 548 549 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 550 551 assertThrows(CarInternalErrorException.class, 552 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 553 } 554 555 @Test testGetProperty_returnsValueWithUnknownStatusBeforeU()556 public void testGetProperty_returnsValueWithUnknownStatusBeforeU() throws RemoteException { 557 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 558 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 559 /*unknown status=*/999, TEST_TIMESTAMP, 17.0f); 560 561 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 562 563 assertThat(mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, /*areaId=*/ 0)).isEqualTo( 564 new CarPropertyValue<>(HVAC_TEMPERATURE_SET, /*areaId=*/0, /*status=*/999, 565 TEST_TIMESTAMP, 17.0f)); 566 } 567 568 @Test testGetProperty_valueWithUnknownStatusThrowsAfterU()569 public void testGetProperty_valueWithUnknownStatusThrowsAfterU() throws RemoteException { 570 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 571 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 572 /*unknown status=*/999, TEST_TIMESTAMP, 17.0f); 573 574 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 575 576 assertThrows(CarInternalErrorException.class, 577 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 578 } 579 580 @Test testGetPropertyWithClass()581 public void testGetPropertyWithClass() throws Exception { 582 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 583 584 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 585 586 assertThat(mCarPropertyManager.getProperty(Float.class, HVAC_TEMPERATURE_SET, 0).getValue()) 587 .isEqualTo(17.0f); 588 } 589 590 @Test testGetPropertyWithClass_mismatchClass()591 public void testGetPropertyWithClass_mismatchClass() throws Exception { 592 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 593 594 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 595 596 assertThrows(IllegalArgumentException.class, 597 () -> mCarPropertyManager.getProperty(Integer.class, HVAC_TEMPERATURE_SET, 0)); 598 } 599 600 @Test testGetPropertyWithClass_tryAgainBeforeR()601 public void testGetPropertyWithClass_tryAgainBeforeR() throws Exception { 602 setAppTargetSdk(Build.VERSION_CODES.Q); 603 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 604 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 605 606 assertThat(mCarPropertyManager.getProperty(Float.class, HVAC_TEMPERATURE_SET, 0)) 607 .isNull(); 608 } 609 610 @Test testGetPropertyWithClass_tryAgainEqualAfterR()611 public void testGetPropertyWithClass_tryAgainEqualAfterR() throws Exception { 612 setAppTargetSdk(Build.VERSION_CODES.R); 613 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 614 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 615 616 assertThrows(PropertyNotAvailableAndRetryException.class, 617 () -> mCarPropertyManager.getProperty(Float.class, HVAC_TEMPERATURE_SET, 0)); 618 } 619 620 621 @Test testGetBooleanProperty()622 public void testGetBooleanProperty() throws Exception { 623 setAppTargetSdk(Build.VERSION_CODES.R); 624 CarPropertyValue<Boolean> value = new CarPropertyValue<>(BOOLEAN_PROP, 0, true); 625 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenReturn(value); 626 627 assertThat(mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)).isTrue(); 628 } 629 630 @Test testGetBooleanProperty_notAvailableBeforeR()631 public void testGetBooleanProperty_notAvailableBeforeR() throws Exception { 632 setAppTargetSdk(Build.VERSION_CODES.Q); 633 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 634 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE)); 635 636 assertThrows(IllegalStateException.class, 637 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 638 } 639 640 @Test testGetBooleanProperty_notAvailableEqualAfterR()641 public void testGetBooleanProperty_notAvailableEqualAfterR() throws Exception { 642 setAppTargetSdk(Build.VERSION_CODES.R); 643 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 644 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE)); 645 646 assertThrows(PropertyNotAvailableException.class, 647 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 648 } 649 650 @Test testGetProperty_notAvailableEqualAfterU_withVendorErrorCode()651 public void testGetProperty_notAvailableEqualAfterU_withVendorErrorCode() throws Exception { 652 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 653 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 654 new ServiceSpecificException(combineErrors( 655 VehicleHalStatusCode.STATUS_NOT_AVAILABLE, VENDOR_ERROR_CODE))); 656 657 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 658 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 659 660 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 661 } 662 663 @Test testGetProperty_notAvailableDisabledBeforeU()664 public void testGetProperty_notAvailableDisabledBeforeU() throws Exception { 665 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 666 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 667 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED)); 668 669 assertThrows(PropertyNotAvailableException.class, 670 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 671 } 672 673 @Test testGetProperty_notAvailableDisabledAfterU()674 public void testGetProperty_notAvailableDisabledAfterU() throws Exception { 675 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 676 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 677 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED)); 678 679 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 680 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 681 assertThat(exception.getDetailedErrorCode()) 682 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_DISABLED); 683 } 684 685 @Test testGetProperty_notAvailableDisabledAfterU_withVendorErrorCode()686 public void testGetProperty_notAvailableDisabledAfterU_withVendorErrorCode() throws Exception { 687 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 688 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 689 new ServiceSpecificException(combineErrors( 690 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED, VENDOR_ERROR_CODE))); 691 692 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 693 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 694 695 assertThat(exception.getDetailedErrorCode()) 696 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_DISABLED); 697 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 698 } 699 700 @Test testGetProperty_notAvailableSafetyBeforeU()701 public void testGetProperty_notAvailableSafetyBeforeU() throws Exception { 702 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 703 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 704 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY)); 705 706 assertThrows(PropertyNotAvailableException.class, 707 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 708 } 709 710 @Test testGetProperty_notAvailableSafetyAfterU()711 public void testGetProperty_notAvailableSafetyAfterU() throws Exception { 712 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 713 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 714 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY)); 715 716 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 717 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 718 assertThat(exception.getDetailedErrorCode()) 719 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SAFETY); 720 } 721 722 @Test testGetProperty_notAvailableSafetyAfterU_withVendorErrorCode()723 public void testGetProperty_notAvailableSafetyAfterU_withVendorErrorCode() throws Exception { 724 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 725 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 726 new ServiceSpecificException(combineErrors( 727 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY, VENDOR_ERROR_CODE))); 728 729 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 730 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 731 732 assertThat(exception.getDetailedErrorCode()) 733 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SAFETY); 734 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 735 } 736 737 @Test testGetProperty_notAvailableSpeedHighBeforeU()738 public void testGetProperty_notAvailableSpeedHighBeforeU() throws Exception { 739 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 740 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 741 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH)); 742 743 assertThrows(PropertyNotAvailableException.class, 744 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 745 } 746 747 @Test testGetProperty_notAvailableSpeedHighAfterU()748 public void testGetProperty_notAvailableSpeedHighAfterU() throws Exception { 749 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 750 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 751 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH)); 752 753 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 754 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 755 assertThat(exception.getDetailedErrorCode()) 756 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_HIGH); 757 } 758 759 @Test testGetProperty_notAvailableSpeedHighAfterU_withVendorErrorCode()760 public void testGetProperty_notAvailableSpeedHighAfterU_withVendorErrorCode() throws Exception { 761 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 762 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 763 new ServiceSpecificException(combineErrors( 764 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH, VENDOR_ERROR_CODE))); 765 766 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 767 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 768 769 assertThat(exception.getDetailedErrorCode()) 770 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_HIGH); 771 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 772 } 773 774 @Test testGetProperty_notAvailableSpeedLowBeforeU()775 public void testGetProperty_notAvailableSpeedLowBeforeU() throws Exception { 776 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 777 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 778 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW)); 779 780 assertThrows(PropertyNotAvailableException.class, 781 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 782 } 783 784 @Test testGetProperty_notAvailableSpeedLowAfterU()785 public void testGetProperty_notAvailableSpeedLowAfterU() throws Exception { 786 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 787 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 788 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW)); 789 790 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 791 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 792 assertThat(exception.getDetailedErrorCode()) 793 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_LOW); 794 } 795 796 @Test testGetProperty_notAvailableSpeedLowAfterU_withVendorErrorCode()797 public void testGetProperty_notAvailableSpeedLowAfterU_withVendorErrorCode() throws Exception { 798 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 799 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 800 new ServiceSpecificException(combineErrors( 801 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW, VENDOR_ERROR_CODE))); 802 803 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 804 () -> mCarPropertyManager.getProperty(HVAC_TEMPERATURE_SET, 0)); 805 806 assertThat(exception.getDetailedErrorCode()) 807 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_LOW); 808 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 809 } 810 811 @Test testGetBooleanProperty_tryAgainBeforeR()812 public void testGetBooleanProperty_tryAgainBeforeR() throws Exception { 813 setAppTargetSdk(Build.VERSION_CODES.Q); 814 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 815 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 816 817 assertThat(mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)).isFalse(); 818 } 819 820 @Test testGetBooleanProperty_tryAgainEqualAfterR()821 public void testGetBooleanProperty_tryAgainEqualAfterR() throws Exception { 822 setAppTargetSdk(Build.VERSION_CODES.R); 823 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 824 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 825 826 assertThrows(PropertyNotAvailableAndRetryException.class, 827 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 828 } 829 830 @Test testGetBooleanProperty_accessDeniedBeforeR()831 public void testGetBooleanProperty_accessDeniedBeforeR() throws Exception { 832 setAppTargetSdk(Build.VERSION_CODES.Q); 833 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 834 new ServiceSpecificException(VehicleHalStatusCode.STATUS_ACCESS_DENIED)); 835 836 assertThrows(IllegalStateException.class, 837 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 838 } 839 840 @Test testGetBooleanProperty_accessDeniedEqualAfterR()841 public void testGetBooleanProperty_accessDeniedEqualAfterR() throws Exception { 842 setAppTargetSdk(Build.VERSION_CODES.R); 843 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 844 new ServiceSpecificException(VehicleHalStatusCode.STATUS_ACCESS_DENIED)); 845 846 assertThrows(PropertyAccessDeniedSecurityException.class, 847 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 848 } 849 850 @Test testGetBooleanProperty_internalErrorBeforeR()851 public void testGetBooleanProperty_internalErrorBeforeR() throws Exception { 852 setAppTargetSdk(Build.VERSION_CODES.Q); 853 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 854 new ServiceSpecificException(VehicleHalStatusCode.STATUS_INTERNAL_ERROR)); 855 856 assertThrows(IllegalStateException.class, 857 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 858 } 859 860 @Test testGetBooleanProperty_internalErrorEqualAfterR()861 public void testGetBooleanProperty_internalErrorEqualAfterR() throws Exception { 862 setAppTargetSdk(Build.VERSION_CODES.R); 863 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 864 new ServiceSpecificException(VehicleHalStatusCode.STATUS_INTERNAL_ERROR)); 865 866 assertThrows(CarInternalErrorException.class, 867 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 868 } 869 870 @Test testGetBooleanProperty_unknownErrorBeforeR()871 public void testGetBooleanProperty_unknownErrorBeforeR() throws Exception { 872 setAppTargetSdk(Build.VERSION_CODES.Q); 873 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 874 new ServiceSpecificException(UNKNOWN_ERROR)); 875 876 assertThrows(IllegalStateException.class, 877 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 878 } 879 880 @Test testGetBooleanProperty_unknownErrorEqualAfterR()881 public void testGetBooleanProperty_unknownErrorEqualAfterR() throws Exception { 882 setAppTargetSdk(Build.VERSION_CODES.R); 883 when(mICarProperty.getProperty(BOOLEAN_PROP, 0)).thenThrow( 884 new ServiceSpecificException(UNKNOWN_ERROR)); 885 886 assertThrows(CarInternalErrorException.class, 887 () -> mCarPropertyManager.getBooleanProperty(BOOLEAN_PROP, 0)); 888 } 889 890 @Test testGetIntProperty()891 public void testGetIntProperty() throws Exception { 892 setAppTargetSdk(Build.VERSION_CODES.R); 893 CarPropertyValue<Integer> value = new CarPropertyValue<>(INT32_PROP, 0, 1); 894 when(mICarProperty.getProperty(INT32_PROP, 0)).thenReturn(value); 895 896 assertThat(mCarPropertyManager.getIntProperty(INT32_PROP, 0)).isEqualTo(1); 897 } 898 899 @Test testGetIntProperty_tryAgainBeforeR()900 public void testGetIntProperty_tryAgainBeforeR() throws Exception { 901 setAppTargetSdk(Build.VERSION_CODES.Q); 902 when(mICarProperty.getProperty(INT32_PROP, 0)).thenThrow( 903 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 904 905 assertThat(mCarPropertyManager.getIntProperty(INT32_PROP, 0)).isEqualTo(0); 906 } 907 908 @Test testGetIntProperty_tryAgainEqualAfterR()909 public void testGetIntProperty_tryAgainEqualAfterR() throws Exception { 910 setAppTargetSdk(Build.VERSION_CODES.R); 911 when(mICarProperty.getProperty(INT32_PROP, 0)).thenThrow( 912 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 913 914 assertThrows(PropertyNotAvailableAndRetryException.class, 915 () -> mCarPropertyManager.getIntProperty(INT32_PROP, 0)); 916 } 917 918 @Test testGetIntProperty_wrongType()919 public void testGetIntProperty_wrongType() throws Exception { 920 CarPropertyValue<Integer> value = new CarPropertyValue<>(INT32_PROP, 0, 1); 921 when(mICarProperty.getProperty(INT32_PROP, 0)).thenReturn(value); 922 923 assertThrows(IllegalArgumentException.class, 924 () -> mCarPropertyManager.getFloatProperty(INT32_PROP, 0)); 925 } 926 927 @Test testGetIntArrayProperty()928 public void testGetIntArrayProperty() throws Exception { 929 setAppTargetSdk(Build.VERSION_CODES.R); 930 CarPropertyValue<Float> value = new CarPropertyValue<>(FLOAT_PROP, 0, 1f); 931 when(mICarProperty.getProperty(FLOAT_PROP, 0)).thenReturn(value); 932 933 assertThrows(IllegalArgumentException.class, 934 () -> mCarPropertyManager.getIntArrayProperty(FLOAT_PROP, 0)); 935 } 936 937 @Test testGetIntArrayProperty_tryAgainBeforeR()938 public void testGetIntArrayProperty_tryAgainBeforeR() throws Exception { 939 setAppTargetSdk(Build.VERSION_CODES.Q); 940 when(mICarProperty.getProperty(INT32_VEC_PROP, 0)).thenThrow( 941 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 942 943 assertThat(mCarPropertyManager.getIntArrayProperty(INT32_VEC_PROP, 0)).isEqualTo( 944 new int[0]); 945 } 946 947 @Test testGetIntArrayProperty_tryAgainEqualAfterR()948 public void testGetIntArrayProperty_tryAgainEqualAfterR() throws Exception { 949 setAppTargetSdk(Build.VERSION_CODES.R); 950 when(mICarProperty.getProperty(INT32_VEC_PROP, 0)).thenThrow( 951 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 952 953 assertThrows(PropertyNotAvailableAndRetryException.class, 954 () -> mCarPropertyManager.getIntArrayProperty(INT32_VEC_PROP, 0)); 955 } 956 957 @Test testGetFloatProperty()958 public void testGetFloatProperty() throws Exception { 959 setAppTargetSdk(Build.VERSION_CODES.R); 960 CarPropertyValue<Float> value = new CarPropertyValue<>(FLOAT_PROP, 0, 1.f); 961 when(mICarProperty.getProperty(FLOAT_PROP, 0)).thenReturn(value); 962 963 assertThat(mCarPropertyManager.getFloatProperty(FLOAT_PROP, 0)).isEqualTo(1.f); 964 } 965 966 @Test testGetFloatProperty_tryAgainBeforeR()967 public void testGetFloatProperty_tryAgainBeforeR() throws Exception { 968 setAppTargetSdk(Build.VERSION_CODES.Q); 969 when(mICarProperty.getProperty(FLOAT_PROP, 0)).thenThrow( 970 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 971 972 assertThat(mCarPropertyManager.getFloatProperty(FLOAT_PROP, 0)).isEqualTo(0.f); 973 } 974 975 @Test testGetFloatProperty_tryAgainEqualAfterR()976 public void testGetFloatProperty_tryAgainEqualAfterR() throws Exception { 977 setAppTargetSdk(Build.VERSION_CODES.R); 978 when(mICarProperty.getProperty(FLOAT_PROP, 0)).thenThrow( 979 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 980 981 assertThrows(PropertyNotAvailableAndRetryException.class, 982 () -> mCarPropertyManager.getFloatProperty(FLOAT_PROP, 0)); 983 } 984 985 @Test testGetFloatProperty_wrongType()986 public void testGetFloatProperty_wrongType() throws Exception { 987 CarPropertyValue<Integer> value = new CarPropertyValue<>(INT32_PROP, 0, 1); 988 when(mICarProperty.getProperty(INT32_PROP, 0)).thenReturn(value); 989 990 assertThrows(IllegalArgumentException.class, 991 () -> mCarPropertyManager.getFloatProperty(INT32_PROP, 0)); 992 } 993 createGetPropertyRequest()994 private CarPropertyManager.GetPropertyRequest createGetPropertyRequest() { 995 return mCarPropertyManager.generateGetPropertyRequest(HVAC_TEMPERATURE_SET, 0); 996 } 997 998 @Test testGetPropertiesAsync()999 public void testGetPropertiesAsync() throws RemoteException { 1000 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), null, null, 1001 mGetPropertyCallback); 1002 1003 ArgumentCaptor<AsyncPropertyServiceRequestList> argumentCaptor = ArgumentCaptor.forClass( 1004 AsyncPropertyServiceRequestList.class); 1005 verify(mICarProperty).getPropertiesAsync(argumentCaptor.capture(), any(), anyLong()); 1006 assertThat(argumentCaptor.getValue().getList().get(0).getRequestId()).isEqualTo(0); 1007 assertThat(argumentCaptor.getValue().getList().get(0).getPropertyId()) 1008 .isEqualTo(HVAC_TEMPERATURE_SET); 1009 assertThat(argumentCaptor.getValue().getList().get(0).getAreaId()).isEqualTo(0); 1010 } 1011 1012 @Test testGetPropertiesAsyncWithTimeout()1013 public void testGetPropertiesAsyncWithTimeout() throws RemoteException { 1014 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), 1015 /* timeoutInMs= */ 1000, null, null, mGetPropertyCallback); 1016 1017 ArgumentCaptor<AsyncPropertyServiceRequestList> argumentCaptor = ArgumentCaptor.forClass( 1018 AsyncPropertyServiceRequestList.class); 1019 verify(mICarProperty).getPropertiesAsync(argumentCaptor.capture(), any(), eq(1000L)); 1020 assertThat(argumentCaptor.getValue().getList().get(0).getRequestId()).isEqualTo(0); 1021 assertThat(argumentCaptor.getValue().getList().get(0).getPropertyId()) 1022 .isEqualTo(HVAC_TEMPERATURE_SET); 1023 assertThat(argumentCaptor.getValue().getList().get(0).getAreaId()).isEqualTo(0); 1024 } 1025 1026 @Test testGetPropertiesAsync_illegalArgumentException()1027 public void testGetPropertiesAsync_illegalArgumentException() throws RemoteException { 1028 IllegalArgumentException exception = new IllegalArgumentException(); 1029 doThrow(exception).when(mICarProperty).getPropertiesAsync(any( 1030 AsyncPropertyServiceRequestList.class), 1031 any(IAsyncPropertyResultCallback.class), anyLong()); 1032 1033 assertThrows(IllegalArgumentException.class, 1034 () -> mCarPropertyManager.getPropertiesAsync( 1035 List.of(createGetPropertyRequest()), null, null, mGetPropertyCallback)); 1036 } 1037 1038 @Test testGetPropertiesAsync_SecurityException()1039 public void testGetPropertiesAsync_SecurityException() throws RemoteException { 1040 SecurityException exception = new SecurityException(); 1041 doThrow(exception).when(mICarProperty).getPropertiesAsync(any( 1042 AsyncPropertyServiceRequestList.class), 1043 any(IAsyncPropertyResultCallback.class), anyLong()); 1044 1045 assertThrows(SecurityException.class, 1046 () -> mCarPropertyManager.getPropertiesAsync( 1047 List.of(createGetPropertyRequest()), null, null, mGetPropertyCallback)); 1048 } 1049 1050 @Test tsetGetPropertiesAsync_unsupportedProperty()1051 public void tsetGetPropertiesAsync_unsupportedProperty() throws Exception { 1052 assertThrows(IllegalArgumentException.class, 1053 () -> mCarPropertyManager.getPropertiesAsync( 1054 List.of(mCarPropertyManager.generateGetPropertyRequest(INVALID, 0)), null, 1055 null, mGetPropertyCallback)); 1056 } 1057 1058 @Test testGetPropertiesAsync_remoteException()1059 public void testGetPropertiesAsync_remoteException() throws RemoteException { 1060 RemoteException remoteException = new RemoteException(); 1061 doThrow(remoteException).when(mICarProperty).getPropertiesAsync(any( 1062 AsyncPropertyServiceRequestList.class), 1063 any(IAsyncPropertyResultCallback.class), anyLong()); 1064 1065 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), null, null, 1066 mGetPropertyCallback); 1067 1068 verify(mCar).handleRemoteExceptionFromCarService(any(RemoteException.class)); 1069 } 1070 1071 @Test testGetPropertiesAsync_clearRequestIdAfterFailed()1072 public void testGetPropertiesAsync_clearRequestIdAfterFailed() throws RemoteException { 1073 CarPropertyManager.GetPropertyRequest getPropertyRequest = createGetPropertyRequest(); 1074 IllegalArgumentException exception = new IllegalArgumentException(); 1075 doThrow(exception).when(mICarProperty).getPropertiesAsync(any( 1076 AsyncPropertyServiceRequestList.class), 1077 any(IAsyncPropertyResultCallback.class), anyLong()); 1078 1079 assertThrows(IllegalArgumentException.class, 1080 () -> mCarPropertyManager.getPropertiesAsync(List.of(getPropertyRequest), null, 1081 null, mGetPropertyCallback)); 1082 1083 clearInvocations(mICarProperty); 1084 doNothing().when(mICarProperty).getPropertiesAsync(any( 1085 AsyncPropertyServiceRequestList.class), 1086 any(IAsyncPropertyResultCallback.class), anyLong()); 1087 ArgumentCaptor<AsyncPropertyServiceRequestList> argumentCaptor = ArgumentCaptor.forClass( 1088 AsyncPropertyServiceRequestList.class); 1089 1090 mCarPropertyManager.getPropertiesAsync(List.of(getPropertyRequest), null, null, 1091 mGetPropertyCallback); 1092 1093 verify(mICarProperty).getPropertiesAsync(argumentCaptor.capture(), any(), anyLong()); 1094 assertThat(argumentCaptor.getValue().getList().get(0).getRequestId()).isEqualTo(0); 1095 assertThat(argumentCaptor.getValue().getList().get(0).getPropertyId()) 1096 .isEqualTo(HVAC_TEMPERATURE_SET); 1097 assertThat(argumentCaptor.getValue().getList().get(0).getAreaId()).isEqualTo(0); 1098 } 1099 1100 @Test 1101 @IgnoreUnderRavenwood(blockedBy = android.os.CancellationSignal.class) testGetPropertiesAsync_cancellationSignalCancelRequests()1102 public void testGetPropertiesAsync_cancellationSignalCancelRequests() throws Exception { 1103 CarPropertyManager.GetPropertyRequest getPropertyRequest = createGetPropertyRequest(); 1104 CancellationSignal cancellationSignal = new CancellationSignal(); 1105 List<IAsyncPropertyResultCallback> callbackWrapper = new ArrayList<>(); 1106 doAnswer((invocation) -> { 1107 Object[] args = invocation.getArguments(); 1108 callbackWrapper.add((IAsyncPropertyResultCallback) args[1]); 1109 return null; 1110 }).when(mICarProperty).getPropertiesAsync(any(), any(), anyLong()); 1111 1112 mCarPropertyManager.getPropertiesAsync(List.of(getPropertyRequest), cancellationSignal, 1113 /* callbackExecutor= */ null, mGetPropertyCallback); 1114 1115 // Cancel the pending request. 1116 cancellationSignal.cancel(); 1117 1118 verify(mICarProperty).cancelRequests(new int[]{0}); 1119 1120 // Call the manager callback after the request is already cancelled. 1121 GetSetValueResult getValueResult = GetSetValueResult.newErrorResult( 1122 0, 1123 new CarPropertyErrorCodes( 1124 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR, 1125 /* vendorErrorCode= */ 0, 1126 /* systemErrorCode= */ 0)); 1127 assertThat(callbackWrapper.size()).isEqualTo(1); 1128 callbackWrapper.get(0).onGetValueResults( 1129 new GetSetValueResultList(List.of(getValueResult))); 1130 1131 // No client callbacks should be called. 1132 verify(mGetPropertyCallback, never()).onFailure(any()); 1133 verify(mGetPropertyCallback, never()).onSuccess(any()); 1134 } 1135 1136 @Test testOnGetValueResult_onSuccess()1137 public void testOnGetValueResult_onSuccess() throws RemoteException { 1138 doAnswer((invocation) -> { 1139 Object[] args = invocation.getArguments(); 1140 AsyncPropertyServiceRequestList asyncGetPropertyServiceRequestList = 1141 (AsyncPropertyServiceRequestList) args[0]; 1142 List getPropertyServiceList = asyncGetPropertyServiceRequestList.getList(); 1143 AsyncPropertyServiceRequest getPropertyServiceRequest = 1144 (AsyncPropertyServiceRequest) getPropertyServiceList.get(0); 1145 IAsyncPropertyResultCallback getAsyncPropertyResultCallback = 1146 (IAsyncPropertyResultCallback) args[1]; 1147 1148 assertThat(getPropertyServiceRequest.getRequestId()).isEqualTo(0); 1149 assertThat(getPropertyServiceRequest.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1150 1151 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 1152 GetSetValueResult getValueResult = GetSetValueResult.newGetValueResult(0, value); 1153 1154 getAsyncPropertyResultCallback.onGetValueResults( 1155 new GetSetValueResultList(List.of(getValueResult))); 1156 return null; 1157 }).when(mICarProperty).getPropertiesAsync(any(), any(), anyLong()); 1158 1159 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), null, null, 1160 mGetPropertyCallback); 1161 1162 verify(mGetPropertyCallback, timeout(1000)).onSuccess( 1163 mGetPropertyResultCaptor.capture()); 1164 GetPropertyResult<Float> gotResult = (GetPropertyResult<Float>) 1165 mGetPropertyResultCaptor.getValue(); 1166 assertThat(gotResult.getRequestId()).isEqualTo(0); 1167 assertThat(gotResult.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1168 assertThat(gotResult.getAreaId()).isEqualTo(0); 1169 assertThat(gotResult.getValue()).isEqualTo(17.0f); 1170 } 1171 1172 @Test testOnGetValueResult_onSuccessMultipleRequests()1173 public void testOnGetValueResult_onSuccessMultipleRequests() throws RemoteException { 1174 doAnswer((invocation) -> { 1175 Object[] args = invocation.getArguments(); 1176 AsyncPropertyServiceRequestList getPropertyServiceRequest = 1177 (AsyncPropertyServiceRequestList) args[0]; 1178 List<AsyncPropertyServiceRequest> getPropertyServiceRequests = 1179 getPropertyServiceRequest.getList(); 1180 IAsyncPropertyResultCallback getAsyncPropertyResultCallback = 1181 (IAsyncPropertyResultCallback) args[1]; 1182 1183 assertThat(getPropertyServiceRequests.size()).isEqualTo(2); 1184 assertThat(getPropertyServiceRequests.get(0).getRequestId()).isEqualTo(0); 1185 assertThat(getPropertyServiceRequests.get(0).getPropertyId()).isEqualTo( 1186 HVAC_TEMPERATURE_SET); 1187 assertThat(getPropertyServiceRequests.get(1).getRequestId()).isEqualTo(1); 1188 assertThat(getPropertyServiceRequests.get(1).getPropertyId()).isEqualTo( 1189 HVAC_TEMPERATURE_SET); 1190 1191 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 17.0f); 1192 List<GetSetValueResult> getValueResults = List.of( 1193 GetSetValueResult.newGetValueResult(0, value), 1194 GetSetValueResult.newGetValueResult(1, value)); 1195 1196 getAsyncPropertyResultCallback.onGetValueResults( 1197 new GetSetValueResultList(getValueResults)); 1198 return null; 1199 }).when(mICarProperty).getPropertiesAsync(any(), any(), anyLong()); 1200 1201 List<CarPropertyManager.GetPropertyRequest> getPropertyRequests = new ArrayList<>(); 1202 getPropertyRequests.add(createGetPropertyRequest()); 1203 getPropertyRequests.add(createGetPropertyRequest()); 1204 1205 mCarPropertyManager.getPropertiesAsync(getPropertyRequests, null, null, 1206 mGetPropertyCallback); 1207 1208 verify(mGetPropertyCallback, timeout(1000).times(2)).onSuccess( 1209 mGetPropertyResultCaptor.capture()); 1210 List<GetPropertyResult<?>> gotPropertyResults = mGetPropertyResultCaptor.getAllValues(); 1211 assertThat(gotPropertyResults.get(0).getRequestId()).isEqualTo(0); 1212 assertThat(gotPropertyResults.get(0).getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1213 assertThat(gotPropertyResults.get(0).getAreaId()).isEqualTo(0); 1214 assertThat(gotPropertyResults.get(0).getValue()).isEqualTo(17.0f); 1215 assertThat(gotPropertyResults.get(1).getRequestId()).isEqualTo(1); 1216 assertThat(gotPropertyResults.get(1).getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1217 assertThat(gotPropertyResults.get(1).getAreaId()).isEqualTo(0); 1218 assertThat(gotPropertyResults.get(1).getValue()).isEqualTo(17.0f); 1219 } 1220 1221 @Test testOnGetValueResult_onFailure()1222 public void testOnGetValueResult_onFailure() throws RemoteException { 1223 doAnswer((invocation) -> { 1224 Object[] args = invocation.getArguments(); 1225 AsyncPropertyServiceRequestList asyncPropertyServiceRequestList = 1226 (AsyncPropertyServiceRequestList) args[0]; 1227 List getPropertyServiceList = asyncPropertyServiceRequestList.getList(); 1228 AsyncPropertyServiceRequest getPropertyServiceRequest = 1229 (AsyncPropertyServiceRequest) getPropertyServiceList.get(0); 1230 IAsyncPropertyResultCallback getAsyncPropertyResultCallback = 1231 (IAsyncPropertyResultCallback) args[1]; 1232 1233 assertThat(getPropertyServiceRequest.getRequestId()).isEqualTo(0); 1234 assertThat(getPropertyServiceRequest.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1235 1236 GetSetValueResult getValueResult = GetSetValueResult.newErrorResult( 1237 /* requestId= */ 0, 1238 new CarPropertyErrorCodes( 1239 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR, VENDOR_ERROR_CODE, 0)); 1240 1241 getAsyncPropertyResultCallback.onGetValueResults( 1242 new GetSetValueResultList(List.of(getValueResult))); 1243 return null; 1244 }).when(mICarProperty).getPropertiesAsync(any(), any(), anyLong()); 1245 1246 1247 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), null, null, 1248 mGetPropertyCallback); 1249 1250 verify(mGetPropertyCallback, timeout(1000)).onFailure(mPropertyAsyncErrorCaptor.capture()); 1251 PropertyAsyncError error = mPropertyAsyncErrorCaptor.getValue(); 1252 assertThat(error.getRequestId()).isEqualTo(0); 1253 assertThat(error.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1254 assertThat(error.getAreaId()).isEqualTo(0); 1255 assertThat(error.getErrorCode()).isEqualTo( 1256 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1257 assertThat(error.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1258 } 1259 1260 @Test 1261 @EnableFlags(Flags.FLAG_CAR_PROPERTY_DETAILED_ERROR_CODES) testPropertyAsyncError_GetDetailedErrorCode()1262 public void testPropertyAsyncError_GetDetailedErrorCode() throws RemoteException { 1263 doAnswer((invocation) -> { 1264 Object[] args = invocation.getArguments(); 1265 IAsyncPropertyResultCallback getAsyncPropertyResultCallback = 1266 (IAsyncPropertyResultCallback) args[1]; 1267 1268 GetSetValueResult getValueResult = GetSetValueResult.newErrorResult( 1269 /* requestId= */ 0, 1270 new CarPropertyErrorCodes( 1271 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR, 1272 /* vendorErrorCode= */ 0, 1273 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH)); 1274 1275 getAsyncPropertyResultCallback.onGetValueResults( 1276 new GetSetValueResultList(List.of(getValueResult))); 1277 return null; 1278 }).when(mICarProperty).getPropertiesAsync(any(), any(), anyLong()); 1279 1280 mCarPropertyManager.getPropertiesAsync(List.of(createGetPropertyRequest()), null, null, 1281 mGetPropertyCallback); 1282 1283 verify(mGetPropertyCallback, timeout(1000)).onFailure(mPropertyAsyncErrorCaptor.capture()); 1284 PropertyAsyncError error = mPropertyAsyncErrorCaptor.getValue(); 1285 assertThat(error.getDetailedErrorCode()).isEqualTo( 1286 DetailedErrorCode.NOT_AVAILABLE_SPEED_HIGH); 1287 } 1288 1289 @Test testSetProperty_setsValue()1290 public void testSetProperty_setsValue() throws RemoteException { 1291 mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f); 1292 1293 ArgumentCaptor<CarPropertyValue> value = ArgumentCaptor.forClass(CarPropertyValue.class); 1294 1295 verify(mICarProperty).setProperty(value.capture(), any()); 1296 assertThat(value.getValue().getValue()).isEqualTo(17.0f); 1297 } 1298 1299 @Test testSetProperty_syncOpTryAgain()1300 public void testSetProperty_syncOpTryAgain() throws RemoteException { 1301 doThrow(new ServiceSpecificException(SYNC_OP_LIMIT_TRY_AGAIN)).doNothing() 1302 .when(mICarProperty).setProperty(any(), any()); 1303 1304 mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f); 1305 1306 verify(mICarProperty, times(2)).setProperty(any(), any()); 1307 } 1308 1309 @Test testSetProperty_unsupportedProperty()1310 public void testSetProperty_unsupportedProperty() throws RemoteException { 1311 assertThrows(IllegalArgumentException.class, 1312 () -> mCarPropertyManager.setProperty(Float.class, INVALID, 0, 17.0f)); 1313 } 1314 createSetPropertyRequest()1315 private SetPropertyRequest<Float> createSetPropertyRequest() { 1316 return mCarPropertyManager.generateSetPropertyRequest(HVAC_TEMPERATURE_SET, 0, 1317 Float.valueOf(17.0f)); 1318 } 1319 1320 @Test testSetPropertiesAsync()1321 public void testSetPropertiesAsync() throws RemoteException { 1322 SetPropertyRequest<Float> setPropertyRequest = createSetPropertyRequest(); 1323 setPropertyRequest.setUpdateRateHz(10.1f); 1324 setPropertyRequest.setWaitForPropertyUpdate(false); 1325 mCarPropertyManager.setPropertiesAsync(List.of(setPropertyRequest), null, null, 1326 mSetPropertyCallback); 1327 1328 verify(mICarProperty).setPropertiesAsync(mAsyncPropertyServiceRequestCaptor.capture(), 1329 any(), anyLong()); 1330 1331 AsyncPropertyServiceRequest request = mAsyncPropertyServiceRequestCaptor.getValue() 1332 .getList().get(0); 1333 1334 assertThat(request.getRequestId()).isEqualTo(0); 1335 assertThat(request.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1336 assertThat(request.getAreaId()).isEqualTo(0); 1337 assertThat(request.isWaitForPropertyUpdate()).isFalse(); 1338 assertThat(request.getUpdateRateHz()).isEqualTo(10.1f); 1339 CarPropertyValue requestValue = request.getCarPropertyValue(); 1340 assertThat(requestValue).isNotNull(); 1341 assertThat(requestValue.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1342 assertThat(requestValue.getAreaId()).isEqualTo(0); 1343 assertThat(requestValue.getValue()).isEqualTo(17.0f); 1344 } 1345 1346 @Test testSetPropertiesAsync_nullRequests()1347 public void testSetPropertiesAsync_nullRequests() throws RemoteException { 1348 assertThrows(NullPointerException.class, 1349 () -> mCarPropertyManager.setPropertiesAsync( 1350 null, null, null, mSetPropertyCallback)); 1351 } 1352 1353 @Test testSetPropertiesAsync_nullCallback()1354 public void testSetPropertiesAsync_nullCallback() throws RemoteException { 1355 assertThrows(NullPointerException.class, 1356 () -> mCarPropertyManager.setPropertiesAsync( 1357 List.of(createSetPropertyRequest()), null, null, null)); 1358 } 1359 1360 @Test testSetPropertiesAsyncWithTimeout()1361 public void testSetPropertiesAsyncWithTimeout() throws RemoteException { 1362 mCarPropertyManager.setPropertiesAsync(List.of(createSetPropertyRequest()), 1363 /* timeoutInMs= */ 1000, /* cancellationSignal= */ null, 1364 /* callbackExecutor= */ null, mSetPropertyCallback); 1365 1366 verify(mICarProperty).setPropertiesAsync(mAsyncPropertyServiceRequestCaptor.capture(), 1367 any(), eq(1000L)); 1368 AsyncPropertyServiceRequest request = mAsyncPropertyServiceRequestCaptor.getValue() 1369 .getList().get(0); 1370 assertThat(request.getRequestId()).isEqualTo(0); 1371 assertThat(request.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1372 assertThat(request.getAreaId()).isEqualTo(0); 1373 CarPropertyValue requestValue = request.getCarPropertyValue(); 1374 assertThat(requestValue).isNotNull(); 1375 assertThat(requestValue.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1376 assertThat(requestValue.getAreaId()).isEqualTo(0); 1377 assertThat(requestValue.getValue()).isEqualTo(17.0f); 1378 } 1379 1380 @Test testSetPropertiesAsync_illegalArgumentException()1381 public void testSetPropertiesAsync_illegalArgumentException() throws RemoteException { 1382 doThrow(new IllegalArgumentException()).when(mICarProperty).setPropertiesAsync( 1383 any(AsyncPropertyServiceRequestList.class), any(IAsyncPropertyResultCallback.class), 1384 anyLong()); 1385 1386 assertThrows(IllegalArgumentException.class, 1387 () -> mCarPropertyManager.setPropertiesAsync( 1388 List.of(createSetPropertyRequest()), null, null, mSetPropertyCallback)); 1389 } 1390 1391 @Test testSetPropertiesAsync_SecurityException()1392 public void testSetPropertiesAsync_SecurityException() throws RemoteException { 1393 doThrow(new SecurityException()).when(mICarProperty).setPropertiesAsync( 1394 any(AsyncPropertyServiceRequestList.class), 1395 any(IAsyncPropertyResultCallback.class), anyLong()); 1396 1397 assertThrows(SecurityException.class, 1398 () -> mCarPropertyManager.setPropertiesAsync( 1399 List.of(createSetPropertyRequest()), null, null, mSetPropertyCallback)); 1400 } 1401 1402 @Test testSetPropertiesAsync_unsupportedProperty()1403 public void testSetPropertiesAsync_unsupportedProperty() throws Exception { 1404 assertThrows(IllegalArgumentException.class, 1405 () -> mCarPropertyManager.setPropertiesAsync( 1406 List.of(mCarPropertyManager.generateSetPropertyRequest( 1407 INVALID, 0, Integer.valueOf(0))), 1408 null, null, mSetPropertyCallback)); 1409 } 1410 1411 @Test testSetPropertiesAsync_remoteException()1412 public void testSetPropertiesAsync_remoteException() throws RemoteException { 1413 doThrow(new RemoteException()).when(mICarProperty).setPropertiesAsync( 1414 any(AsyncPropertyServiceRequestList.class), 1415 any(IAsyncPropertyResultCallback.class), anyLong()); 1416 1417 mCarPropertyManager.setPropertiesAsync(List.of(createSetPropertyRequest()), null, null, 1418 mSetPropertyCallback); 1419 1420 verify(mCar).handleRemoteExceptionFromCarService(any(RemoteException.class)); 1421 } 1422 1423 @Test testSetPropertiesAsync_duplicateRequestId()1424 public void testSetPropertiesAsync_duplicateRequestId() throws RemoteException { 1425 SetPropertyRequest request = createSetPropertyRequest(); 1426 1427 mCarPropertyManager.setPropertiesAsync(List.of(request), null, null, 1428 mSetPropertyCallback); 1429 1430 // Send the same request again with the same request ID is not allowed. 1431 assertThrows(IllegalArgumentException.class, 1432 () -> mCarPropertyManager.setPropertiesAsync(List.of(request), null, null, 1433 mSetPropertyCallback)); 1434 } 1435 1436 @Test testSetPropertiesAsync_clearRequestIdAfterFailed()1437 public void testSetPropertiesAsync_clearRequestIdAfterFailed() throws RemoteException { 1438 SetPropertyRequest setPropertyRequest = createSetPropertyRequest(); 1439 IllegalArgumentException exception = new IllegalArgumentException(); 1440 doThrow(exception).when(mICarProperty).setPropertiesAsync( 1441 any(AsyncPropertyServiceRequestList.class), any(IAsyncPropertyResultCallback.class), 1442 anyLong()); 1443 1444 assertThrows(IllegalArgumentException.class, 1445 () -> mCarPropertyManager.setPropertiesAsync(List.of(setPropertyRequest), null, 1446 null, mSetPropertyCallback)); 1447 1448 clearInvocations(mICarProperty); 1449 doNothing().when(mICarProperty).setPropertiesAsync( 1450 any(AsyncPropertyServiceRequestList.class), 1451 any(IAsyncPropertyResultCallback.class), anyLong()); 1452 1453 // After the first request failed, the request ID map should be cleared so we can use the 1454 // same request ID again. 1455 mCarPropertyManager.setPropertiesAsync(List.of(setPropertyRequest), null, null, 1456 mSetPropertyCallback); 1457 1458 verify(mICarProperty).setPropertiesAsync(any(), any(), anyLong()); 1459 } 1460 1461 @Test testSetProperty_notAvailableAfterU_withVendorErrorCode()1462 public void testSetProperty_notAvailableAfterU_withVendorErrorCode() throws Exception { 1463 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1464 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1465 HVAC_TEMPERATURE_SET, 0, 17.0f); 1466 doThrow(new ServiceSpecificException(combineErrors( 1467 VehicleHalStatusCode.STATUS_NOT_AVAILABLE, VENDOR_ERROR_CODE))).when(mICarProperty) 1468 .setProperty(eq(carPropertyValue), any()); 1469 1470 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1471 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1472 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1473 } 1474 1475 @Test testSetProperty_internalErrorAfterU_withVendorErrorCode()1476 public void testSetProperty_internalErrorAfterU_withVendorErrorCode() throws Exception { 1477 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1478 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1479 HVAC_TEMPERATURE_SET, 0, 17.0f); 1480 doThrow(new ServiceSpecificException(combineErrors( 1481 VehicleHalStatusCode.STATUS_INTERNAL_ERROR, VENDOR_ERROR_CODE))).when(mICarProperty) 1482 .setProperty(eq(carPropertyValue), any()); 1483 1484 CarInternalErrorException exception = assertThrows(CarInternalErrorException.class, 1485 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1486 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1487 } 1488 1489 @Test testSetProperty_notAvailableDisabledBeforeU()1490 public void testSetProperty_notAvailableDisabledBeforeU() throws Exception { 1491 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 1492 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1493 HVAC_TEMPERATURE_SET, 0, 17.0f); 1494 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED)) 1495 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1496 1497 assertThrows(PropertyNotAvailableException.class, 1498 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1499 } 1500 1501 @Test testSetProperty_notAvailableDisabledAfterU()1502 public void testSetProperty_notAvailableDisabledAfterU() throws Exception { 1503 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1504 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1505 HVAC_TEMPERATURE_SET, 0, 17.0f); 1506 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED)) 1507 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1508 1509 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1510 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1511 assertThat(exception.getDetailedErrorCode()) 1512 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_DISABLED); 1513 } 1514 1515 @Test testSetProperty_notAvailableDisabledAfterU_withVendorErrorCode()1516 public void testSetProperty_notAvailableDisabledAfterU_withVendorErrorCode() throws Exception { 1517 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1518 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1519 HVAC_TEMPERATURE_SET, 0, 17.0f); 1520 doThrow(new ServiceSpecificException(combineErrors( 1521 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_DISABLED, VENDOR_ERROR_CODE))) 1522 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1523 1524 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1525 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1526 assertThat(exception.getDetailedErrorCode()) 1527 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_DISABLED); 1528 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1529 } 1530 1531 @Test testSetProperty_notAvailableSafetyBeforeU()1532 public void testSetProperty_notAvailableSafetyBeforeU() throws Exception { 1533 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 1534 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1535 HVAC_TEMPERATURE_SET, 0, 17.0f); 1536 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY)) 1537 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1538 1539 assertThrows(PropertyNotAvailableException.class, 1540 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1541 } 1542 1543 @Test testSetProperty_notAvailableSafetyAfterU()1544 public void testSetProperty_notAvailableSafetyAfterU() throws Exception { 1545 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1546 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1547 HVAC_TEMPERATURE_SET, 0, 17.0f); 1548 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY)) 1549 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1550 1551 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1552 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1553 assertThat(exception.getDetailedErrorCode()) 1554 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SAFETY); 1555 } 1556 1557 @Test testSetProperty_notAvailableSafetyAfterU_withVendorErrorCode()1558 public void testSetProperty_notAvailableSafetyAfterU_withVendorErrorCode() throws Exception { 1559 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1560 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1561 HVAC_TEMPERATURE_SET, 0, 17.0f); 1562 doThrow(new ServiceSpecificException(combineErrors( 1563 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SAFETY, VENDOR_ERROR_CODE))) 1564 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1565 1566 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1567 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1568 assertThat(exception.getDetailedErrorCode()) 1569 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SAFETY); 1570 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1571 } 1572 1573 @Test testSetProperty_notAvailableSpeedHighBeforeU()1574 public void testSetProperty_notAvailableSpeedHighBeforeU() throws Exception { 1575 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 1576 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1577 HVAC_TEMPERATURE_SET, 0, 17.0f); 1578 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH)) 1579 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1580 1581 assertThrows(PropertyNotAvailableException.class, 1582 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1583 } 1584 1585 @Test testSetProperty_notAvailableSpeedHighAfterU()1586 public void testSetProperty_notAvailableSpeedHighAfterU() throws Exception { 1587 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1588 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1589 HVAC_TEMPERATURE_SET, 0, 17.0f); 1590 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH)) 1591 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1592 1593 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1594 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1595 assertThat(exception.getDetailedErrorCode()) 1596 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_HIGH); 1597 } 1598 1599 @Test testSetProperty_notAvailableSpeedHighAfterU_withVendorErrorCode()1600 public void testSetProperty_notAvailableSpeedHighAfterU_withVendorErrorCode() throws Exception { 1601 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1602 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1603 HVAC_TEMPERATURE_SET, 0, 17.0f); 1604 doThrow(new ServiceSpecificException(combineErrors( 1605 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_HIGH, VENDOR_ERROR_CODE))) 1606 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1607 1608 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1609 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1610 assertThat(exception.getDetailedErrorCode()) 1611 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_HIGH); 1612 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1613 } 1614 1615 @Test testSetProperty_notAvailableSpeedLowBeforeU()1616 public void testSetProperty_notAvailableSpeedLowBeforeU() throws Exception { 1617 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 1618 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1619 HVAC_TEMPERATURE_SET, 0, 17.0f); 1620 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW)) 1621 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1622 1623 assertThrows(PropertyNotAvailableException.class, 1624 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1625 } 1626 1627 @Test testSetProperty_notAvailableSpeedLowAfterU()1628 public void testSetProperty_notAvailableSpeedLowAfterU() throws Exception { 1629 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1630 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1631 HVAC_TEMPERATURE_SET, 0, 17.0f); 1632 doThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW)) 1633 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1634 1635 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1636 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1637 assertThat(exception.getDetailedErrorCode()) 1638 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_LOW); 1639 } 1640 1641 @Test testSetProperty_notAvailableSpeedLowAfterU_withVendorErrorCode()1642 public void testSetProperty_notAvailableSpeedLowAfterU_withVendorErrorCode() throws Exception { 1643 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 1644 CarPropertyValue<Float> carPropertyValue = new CarPropertyValue<>( 1645 HVAC_TEMPERATURE_SET, 0, 17.0f); 1646 doThrow(new ServiceSpecificException(combineErrors( 1647 VehicleHalStatusCode.STATUS_NOT_AVAILABLE_SPEED_LOW, VENDOR_ERROR_CODE))) 1648 .when(mICarProperty).setProperty(eq(carPropertyValue), any()); 1649 1650 PropertyNotAvailableException exception = assertThrows(PropertyNotAvailableException.class, 1651 () -> mCarPropertyManager.setProperty(Float.class, HVAC_TEMPERATURE_SET, 0, 17.0f)); 1652 assertThat(exception.getDetailedErrorCode()) 1653 .isEqualTo(PropertyNotAvailableErrorCode.NOT_AVAILABLE_SPEED_LOW); 1654 assertThat(exception.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1655 } 1656 1657 @Test testOnSetValueResult_onSuccess()1658 public void testOnSetValueResult_onSuccess() throws RemoteException { 1659 doAnswer((invocation) -> { 1660 Object[] args = invocation.getArguments(); 1661 AsyncPropertyServiceRequestList setPropertyRequest = 1662 (AsyncPropertyServiceRequestList) args[0]; 1663 List setPropertyServiceList = setPropertyRequest.getList(); 1664 AsyncPropertyServiceRequest setPropertyServiceRequest = 1665 (AsyncPropertyServiceRequest) setPropertyServiceList.get(0); 1666 IAsyncPropertyResultCallback setAsyncPropertyResultCallback = 1667 (IAsyncPropertyResultCallback) args[1]; 1668 1669 assertThat(setPropertyServiceRequest.getRequestId()).isEqualTo(0); 1670 assertThat(setPropertyServiceRequest.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1671 assertThat(setPropertyServiceRequest.getCarPropertyValue().getValue()).isEqualTo( 1672 17.0f); 1673 1674 GetSetValueResult setValueResult = GetSetValueResult.newSetValueResult(0, 1675 /* updateTimestampNanos= */ TEST_TIMESTAMP); 1676 1677 setAsyncPropertyResultCallback.onSetValueResults( 1678 new GetSetValueResultList(List.of(setValueResult))); 1679 return null; 1680 }).when(mICarProperty).setPropertiesAsync(any(), any(), anyLong()); 1681 1682 1683 mCarPropertyManager.setPropertiesAsync(List.of(createSetPropertyRequest()), null, null, 1684 mSetPropertyCallback); 1685 1686 verify(mSetPropertyCallback, timeout(1000)).onSuccess(mSetPropertyResultCaptor.capture()); 1687 SetPropertyResult gotResult = mSetPropertyResultCaptor.getValue(); 1688 assertThat(gotResult.getRequestId()).isEqualTo(0); 1689 assertThat(gotResult.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1690 assertThat(gotResult.getAreaId()).isEqualTo(0); 1691 assertThat(gotResult.getUpdateTimestampNanos()).isEqualTo(TEST_TIMESTAMP); 1692 } 1693 1694 @Test testOnSetValueResult_onSuccessMultipleRequests()1695 public void testOnSetValueResult_onSuccessMultipleRequests() throws RemoteException { 1696 doAnswer((invocation) -> { 1697 Object[] args = invocation.getArguments(); 1698 AsyncPropertyServiceRequestList setPropertyServiceRequest = 1699 (AsyncPropertyServiceRequestList) args[0]; 1700 List<AsyncPropertyServiceRequest> setPropertyServiceRequests = 1701 setPropertyServiceRequest.getList(); 1702 IAsyncPropertyResultCallback setAsyncPropertyResultCallback = 1703 (IAsyncPropertyResultCallback) args[1]; 1704 1705 assertThat(setPropertyServiceRequests.size()).isEqualTo(2); 1706 assertThat(setPropertyServiceRequests.get(0).getRequestId()).isEqualTo(0); 1707 assertThat(setPropertyServiceRequests.get(0).getPropertyId()).isEqualTo( 1708 HVAC_TEMPERATURE_SET); 1709 assertThat(setPropertyServiceRequests.get(1).getRequestId()).isEqualTo(1); 1710 assertThat(setPropertyServiceRequests.get(1).getPropertyId()).isEqualTo( 1711 HVAC_TEMPERATURE_SET); 1712 1713 List<GetSetValueResult> setValueResults = List.of( 1714 GetSetValueResult.newSetValueResult(0, 1715 /* updateTimestampNanos= */ TEST_TIMESTAMP), 1716 GetSetValueResult.newSetValueResult(1, 1717 /* updateTimestampNanos= */ TEST_TIMESTAMP)); 1718 1719 setAsyncPropertyResultCallback.onSetValueResults( 1720 new GetSetValueResultList(setValueResults)); 1721 return null; 1722 }).when(mICarProperty).setPropertiesAsync(any(), any(), anyLong()); 1723 1724 List<SetPropertyRequest<?>> setPropertyRequests = new ArrayList<>(); 1725 setPropertyRequests.add(createSetPropertyRequest()); 1726 setPropertyRequests.add(createSetPropertyRequest()); 1727 1728 mCarPropertyManager.setPropertiesAsync(setPropertyRequests, null, null, 1729 mSetPropertyCallback); 1730 1731 verify(mSetPropertyCallback, timeout(1000).times(2)).onSuccess( 1732 mSetPropertyResultCaptor.capture()); 1733 List<SetPropertyResult> gotPropertyResults = mSetPropertyResultCaptor.getAllValues(); 1734 assertThat(gotPropertyResults.get(0).getRequestId()).isEqualTo(0); 1735 assertThat(gotPropertyResults.get(0).getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1736 assertThat(gotPropertyResults.get(0).getAreaId()).isEqualTo(0); 1737 assertThat(gotPropertyResults.get(0).getUpdateTimestampNanos()).isEqualTo(TEST_TIMESTAMP); 1738 assertThat(gotPropertyResults.get(1).getRequestId()).isEqualTo(1); 1739 assertThat(gotPropertyResults.get(1).getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1740 assertThat(gotPropertyResults.get(1).getAreaId()).isEqualTo(0); 1741 assertThat(gotPropertyResults.get(1).getUpdateTimestampNanos()).isEqualTo(TEST_TIMESTAMP); 1742 } 1743 1744 @Test testOnSetValueResult_onFailure()1745 public void testOnSetValueResult_onFailure() throws RemoteException { 1746 doAnswer((invocation) -> { 1747 Object[] args = invocation.getArguments(); 1748 AsyncPropertyServiceRequestList setPropertyService = 1749 (AsyncPropertyServiceRequestList) args[0]; 1750 List setPropertyServiceList = setPropertyService.getList(); 1751 AsyncPropertyServiceRequest setPropertyServiceRequest = 1752 (AsyncPropertyServiceRequest) setPropertyServiceList.get(0); 1753 IAsyncPropertyResultCallback setAsyncPropertyResultCallback = 1754 (IAsyncPropertyResultCallback) args[1]; 1755 1756 assertThat(setPropertyServiceRequest.getRequestId()).isEqualTo(0); 1757 assertThat(setPropertyServiceRequest.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1758 1759 GetSetValueResult setValueResult = GetSetValueResult.newErrorSetValueResult( 1760 0, 1761 new CarPropertyErrorCodes( 1762 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR, VENDOR_ERROR_CODE, 0)); 1763 1764 setAsyncPropertyResultCallback.onSetValueResults( 1765 new GetSetValueResultList(List.of(setValueResult))); 1766 return null; 1767 }).when(mICarProperty).setPropertiesAsync(any(), any(), anyLong()); 1768 1769 mCarPropertyManager.setPropertiesAsync(List.of(createSetPropertyRequest()), null, null, 1770 mSetPropertyCallback); 1771 1772 verify(mSetPropertyCallback, timeout(1000)).onFailure(mPropertyAsyncErrorCaptor.capture()); 1773 PropertyAsyncError error = mPropertyAsyncErrorCaptor.getValue(); 1774 assertThat(error.getRequestId()).isEqualTo(0); 1775 assertThat(error.getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 1776 assertThat(error.getAreaId()).isEqualTo(0); 1777 assertThat(error.getErrorCode()).isEqualTo( 1778 CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1779 assertThat(error.getVendorErrorCode()).isEqualTo(VENDOR_ERROR_CODE); 1780 } 1781 1782 @Test testRegisterCallback_returnsFalseIfPropertyIdNotSupportedInVehicle()1783 public void testRegisterCallback_returnsFalseIfPropertyIdNotSupportedInVehicle() 1784 throws RemoteException { 1785 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1786 VehiclePropertyIds.INVALID, FIRST_UPDATE_RATE_HZ)).isFalse(); 1787 verify(mICarProperty, never()).registerListener(any(), 1788 any(ICarPropertyEventListener.class)); 1789 } 1790 1791 @Test testRegisterCallback_registersWithServiceOnFirstCallback()1792 public void testRegisterCallback_registersWithServiceOnFirstCallback() throws RemoteException { 1793 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1794 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1795 verify(mICarProperty).registerListener(eq(List.of( 1796 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 1797 FIRST_UPDATE_RATE_HZ))), any(ICarPropertyEventListener.class)); 1798 } 1799 1800 @Test testRegisterCallback_registersWithMaxUpdateRateOnFirstCallback()1801 public void testRegisterCallback_registersWithMaxUpdateRateOnFirstCallback() 1802 throws RemoteException { 1803 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1804 VENDOR_CONTINUOUS_PROPERTY, MAX_UPDATE_RATE_HZ + 1)).isTrue(); 1805 verify(mICarProperty).registerListener(eq(List.of( 1806 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 1807 MAX_UPDATE_RATE_HZ))), any(ICarPropertyEventListener.class)); 1808 } 1809 1810 @Test testRegisterCallback_registersWithMinUpdateRateOnFirstCallback()1811 public void testRegisterCallback_registersWithMinUpdateRateOnFirstCallback() 1812 throws RemoteException { 1813 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1814 VENDOR_CONTINUOUS_PROPERTY, MIN_UPDATE_RATE_HZ - 1)).isTrue(); 1815 verify(mICarProperty).registerListener(eq(List.of( 1816 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 1817 MIN_UPDATE_RATE_HZ))), any(ICarPropertyEventListener.class)); 1818 } 1819 1820 @Test testRegisterCallback_registersWithOnChangeRateForOnChangeProperty()1821 public void testRegisterCallback_registersWithOnChangeRateForOnChangeProperty() 1822 throws RemoteException { 1823 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1824 VENDOR_ON_CHANGE_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1825 verify(mICarProperty).registerListener(eq(List.of( 1826 createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[]{0}, 1827 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 1828 any(ICarPropertyEventListener.class)); 1829 } 1830 1831 @Test testRegisterCallback_registersWithOnChangeRateForStaticProperty()1832 public void testRegisterCallback_registersWithOnChangeRateForStaticProperty() 1833 throws RemoteException { 1834 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1835 VENDOR_STATIC_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1836 verify(mICarProperty).registerListener(eq(List.of( 1837 createCarSubscriptionOption(VENDOR_STATIC_PROPERTY, new int[]{0}, 1838 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 1839 any(ICarPropertyEventListener.class)); 1840 } 1841 1842 @Test testRegisterCallback_returnsFalseForRemoteException()1843 public void testRegisterCallback_returnsFalseForRemoteException() throws RemoteException { 1844 RemoteException remoteException = new RemoteException(); 1845 doThrow(remoteException).when(mICarProperty).registerListener( 1846 eq(List.of(createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[] {0}, 1847 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 1848 any(ICarPropertyEventListener.class)); 1849 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1850 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isFalse(); 1851 } 1852 1853 @Test testRegisterCallback_recoversAfterFirstRemoteException()1854 public void testRegisterCallback_recoversAfterFirstRemoteException() throws RemoteException { 1855 RemoteException remoteException = new RemoteException(); 1856 doThrow(remoteException).doNothing().when(mICarProperty) 1857 .registerListener(eq(List.of( 1858 createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[] {0}, 1859 SENSOR_RATE_ONCHANGE))), 1860 any(ICarPropertyEventListener.class)); 1861 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1862 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isFalse(); 1863 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1864 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 1865 verify(mICarProperty, times(2)).registerListener( 1866 eq(List.of(createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[] {0}, 1867 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 1868 any(ICarPropertyEventListener.class)); 1869 } 1870 1871 @Test testRegisterCallback_returnsFalseForIllegalArgumentException()1872 public void testRegisterCallback_returnsFalseForIllegalArgumentException() 1873 throws RemoteException { 1874 doThrow(IllegalArgumentException.class).when(mICarProperty) 1875 .registerListener(eq(List.of(createCarSubscriptionOption( 1876 VENDOR_ON_CHANGE_PROPERTY, new int[] {0}, SENSOR_RATE_ONCHANGE))), 1877 any(ICarPropertyEventListener.class)); 1878 1879 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1880 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isFalse(); 1881 } 1882 1883 @Test testRegisterCallback_registersTwiceWithHigherRateCallback()1884 public void testRegisterCallback_registersTwiceWithHigherRateCallback() throws RemoteException { 1885 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1886 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1887 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 1888 VENDOR_CONTINUOUS_PROPERTY, LARGER_UPDATE_RATE_HZ)).isTrue(); 1889 verify(mICarProperty, times(2)).registerListener( 1890 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1891 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 1892 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1893 LARGER_UPDATE_RATE_HZ)), 1894 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1895 FIRST_UPDATE_RATE_HZ))); 1896 } 1897 1898 @Test testRegisterCallback_registersOnSecondHigherRateWithSameCallback()1899 public void testRegisterCallback_registersOnSecondHigherRateWithSameCallback() 1900 throws RemoteException { 1901 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1902 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1903 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 1904 VENDOR_CONTINUOUS_PROPERTY, LARGER_UPDATE_RATE_HZ)).isTrue(); 1905 verify(mICarProperty, times(2)).registerListener( 1906 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1907 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 1908 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1909 LARGER_UPDATE_RATE_HZ)), 1910 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1911 FIRST_UPDATE_RATE_HZ))); 1912 } 1913 1914 @Test testRegisterCallback_registersOnSecondLowerRateWithSameCallback()1915 public void testRegisterCallback_registersOnSecondLowerRateWithSameCallback() 1916 throws RemoteException { 1917 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1918 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1919 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1920 VENDOR_CONTINUOUS_PROPERTY, SMALLER_UPDATE_RATE_HZ)).isTrue(); 1921 verify(mICarProperty, times(2)).registerListener( 1922 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1923 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 1924 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1925 FIRST_UPDATE_RATE_HZ)), 1926 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1927 SMALLER_UPDATE_RATE_HZ))); 1928 } 1929 1930 @Test testRegisterCallback_doesNotRegistersOnSecondLowerRateCallback()1931 public void testRegisterCallback_doesNotRegistersOnSecondLowerRateCallback() 1932 throws RemoteException { 1933 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1934 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1935 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 1936 VENDOR_CONTINUOUS_PROPERTY, SMALLER_UPDATE_RATE_HZ)).isTrue(); 1937 verify(mICarProperty).registerListener(eq(List.of( 1938 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 1939 FIRST_UPDATE_RATE_HZ))), 1940 any(ICarPropertyEventListener.class)); 1941 } 1942 1943 @Test testRegisterCallback_registersTwiceForDifferentProperties()1944 public void testRegisterCallback_registersTwiceForDifferentProperties() throws RemoteException { 1945 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1946 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 1947 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 1948 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 1949 verify(mICarProperty, times(2)).registerListener( 1950 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1951 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 1952 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1953 FIRST_UPDATE_RATE_HZ)), 1954 List.of(createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[] {0}, 1955 CarPropertyManager.SENSOR_RATE_ONCHANGE))); 1956 } 1957 1958 @Test testRegisterCallback_registerInvalidProp()1959 public void testRegisterCallback_registerInvalidProp() throws Exception { 1960 assertThat(mCarPropertyManager.registerCallback( 1961 mCarPropertyEventCallback, /* propertyId= */ -1, FIRST_UPDATE_RATE_HZ)).isFalse(); 1962 } 1963 1964 // We annotate the update rate to be within 0 and 100, however, in the actual implementation, 1965 // we will fit update rate outside this range to the min and max update rate. 1966 @Test testRegisterCallback_updateRateOutsideFloatRangeMustNotThrow_tooLarge()1967 public void testRegisterCallback_updateRateOutsideFloatRangeMustNotThrow_tooLarge() 1968 throws Exception { 1969 assertThat(mCarPropertyManager.registerCallback( 1970 mCarPropertyEventCallback, VENDOR_CONTINUOUS_PROPERTY, /* updateRateHz= */ 101.f)) 1971 .isTrue(); 1972 1973 verify(mICarProperty).registerListener( 1974 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1975 assertThat(mCarSubscriptionCaptor.getValue()).isEqualTo( 1976 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1977 MAX_UPDATE_RATE_HZ))); 1978 } 1979 1980 @Test testRegisterCallback_updateRateOutsideFloatRangeMustNotThrow_tooSmall()1981 public void testRegisterCallback_updateRateOutsideFloatRangeMustNotThrow_tooSmall() 1982 throws Exception { 1983 assertThat(mCarPropertyManager.registerCallback( 1984 mCarPropertyEventCallback, VENDOR_CONTINUOUS_PROPERTY, /* updateRateHz= */ -1.f)) 1985 .isTrue(); 1986 1987 verify(mICarProperty).registerListener( 1988 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 1989 assertThat(mCarSubscriptionCaptor.getValue()).isEqualTo( 1990 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 1991 MIN_UPDATE_RATE_HZ))); 1992 } 1993 1994 @Test testRegisterCallback_isSupportedAndHasWritePermissionOnly()1995 public void testRegisterCallback_isSupportedAndHasWritePermissionOnly() throws Exception { 1996 int propId = VENDOR_CONTINUOUS_PROPERTY; 1997 when(mICarProperty.isSupportedAndHasWritePermissionOnly(propId)).thenReturn(true); 1998 1999 assertThrows(SecurityException.class, () -> mCarPropertyManager.registerCallback( 2000 mCarPropertyEventCallback, VENDOR_CONTINUOUS_PROPERTY, 0)); 2001 } 2002 2003 @Test testRegisterCallback_isSupportedAndHasWritePermissionOnly_remoteException()2004 public void testRegisterCallback_isSupportedAndHasWritePermissionOnly_remoteException() 2005 throws Exception { 2006 int propId = VENDOR_CONTINUOUS_PROPERTY; 2007 when(mICarProperty.isSupportedAndHasWritePermissionOnly(propId)).thenThrow( 2008 new RemoteException()); 2009 2010 assertThat(mCarPropertyManager.registerCallback( 2011 mCarPropertyEventCallback, VENDOR_CONTINUOUS_PROPERTY, 0)).isFalse(); 2012 } 2013 2014 @Test testSubscribePropertyEvents_registerMultipleEvents()2015 public void testSubscribePropertyEvents_registerMultipleEvents() throws Exception { 2016 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2017 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2018 .setUpdateRateFast().build(), 2019 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0).build()), 2020 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2021 2022 verify(mICarProperty).registerListener( 2023 eq(List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2024 CarPropertyManager.SENSOR_RATE_FAST, /* enableVur= */ true), 2025 createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[]{0}, 2026 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 2027 any(ICarPropertyEventListener.class)); 2028 } 2029 2030 @Test testSubscribePropertyEvents_sanitizeSampleRate()2031 public void testSubscribePropertyEvents_sanitizeSampleRate() throws Exception { 2032 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2033 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2034 .setUpdateRateHz(0.f).build()), 2035 /* callbackExecutor= */ null, mCarPropertyEventCallback)) 2036 .isTrue(); 2037 2038 verify(mICarProperty).registerListener( 2039 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 2040 assertThat(mCarSubscriptionCaptor.getValue()).isEqualTo( 2041 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[] {0}, 2042 MIN_UPDATE_RATE_HZ, /* enableVur= */ true))); 2043 } 2044 2045 @Test testSubscribePropertyEvents_registerMultipleEventsSameProperty_throws()2046 public void testSubscribePropertyEvents_registerMultipleEventsSameProperty_throws() 2047 throws Exception { 2048 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 2049 () -> mCarPropertyManager.subscribePropertyEvents(List.of( 2050 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2051 .addAreaId(0).setUpdateRateFast().build(), 2052 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2053 .addAreaId(0).build()), 2054 /* callbackExecutor= */ null, mCarPropertyEventCallback)); 2055 2056 assertWithMessage("Overlapping areaIds").that(thrown).hasMessageThat() 2057 .contains("Subscribe options contain overlapping propertyId"); 2058 } 2059 2060 @Test testSubscribePropertyEvents_registerMultipleEvents_unsubscribe()2061 public void testSubscribePropertyEvents_registerMultipleEvents_unsubscribe() throws Exception { 2062 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2063 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2064 .setUpdateRateFast().build(), 2065 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2066 .build()), 2067 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2068 2069 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2070 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2071 any(ICarPropertyEventListener.class)); 2072 verify(mICarProperty).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2073 any(ICarPropertyEventListener.class)); 2074 } 2075 2076 @Test testSubscribePropertyEvents_registerMultipleEventsWithSameProperty_unsubscribe()2077 public void testSubscribePropertyEvents_registerMultipleEventsWithSameProperty_unsubscribe() 2078 throws Exception { 2079 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2080 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2081 .setUpdateRateFastest().build(), 2082 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2083 .build()), 2084 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2085 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2086 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2087 .setUpdateRateFast().build()), 2088 /* callbackExecutor= */ null, mCarPropertyEventCallback2)).isTrue(); 2089 clearInvocations(mICarProperty); 2090 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2091 2092 verify(mICarProperty).registerListener(eq(List.of( 2093 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2094 CarPropertyManager.SENSOR_RATE_FAST, /* enableVur= */ true))), 2095 any(ICarPropertyEventListener.class)); 2096 verify(mICarProperty).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2097 any(ICarPropertyEventListener.class)); 2098 } 2099 2100 @Test testSubscribePropertyEvents_withPropertyIdCallback()2101 public void testSubscribePropertyEvents_withPropertyIdCallback() throws Exception { 2102 assertThat(mCarPropertyManager.subscribePropertyEvents( 2103 VENDOR_CONTINUOUS_PROPERTY, mCarPropertyEventCallback)).isTrue(); 2104 2105 verify(mICarProperty).registerListener(eq(List.of( 2106 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2107 MIN_UPDATE_RATE_HZ, /* enableVur= */ true))), 2108 any(ICarPropertyEventListener.class)); 2109 } 2110 2111 @Test testSubscribePropertyEvents_withPropertyIdUpdateRateCallback()2112 public void testSubscribePropertyEvents_withPropertyIdUpdateRateCallback() throws Exception { 2113 assertThat(mCarPropertyManager.subscribePropertyEvents( 2114 VENDOR_CONTINUOUS_PROPERTY, CarPropertyManager.SENSOR_RATE_FAST, 2115 mCarPropertyEventCallback)).isTrue(); 2116 2117 verify(mICarProperty).registerListener(eq(List.of( 2118 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2119 CarPropertyManager.SENSOR_RATE_FAST, /* enableVur= */ true))), 2120 any(ICarPropertyEventListener.class)); 2121 } 2122 2123 @Test testSubscribePropertyEvents_withPropertyIdAreaIdCallback()2124 public void testSubscribePropertyEvents_withPropertyIdAreaIdCallback() throws Exception { 2125 assertThat(mCarPropertyManager.subscribePropertyEvents( 2126 VENDOR_CONTINUOUS_PROPERTY, /* areaId= */ 0, 2127 mCarPropertyEventCallback)).isTrue(); 2128 2129 verify(mICarProperty).registerListener(eq(List.of( 2130 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2131 MIN_UPDATE_RATE_HZ, /* enableVur= */ true))), 2132 any(ICarPropertyEventListener.class)); 2133 } 2134 2135 @Test testSubscribePropertyEvents_withPropertyIdAreaIdUpdateRateCallback()2136 public void testSubscribePropertyEvents_withPropertyIdAreaIdUpdateRateCallback() 2137 throws Exception { 2138 assertThat(mCarPropertyManager.subscribePropertyEvents( 2139 VENDOR_CONTINUOUS_PROPERTY, /* areaId= */ 0, 2140 CarPropertyManager.SENSOR_RATE_FAST, 2141 mCarPropertyEventCallback)).isTrue(); 2142 2143 verify(mICarProperty).registerListener(eq(List.of( 2144 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2145 CarPropertyManager.SENSOR_RATE_FAST, /* enableVur= */ true))), 2146 any(ICarPropertyEventListener.class)); 2147 } 2148 2149 // TODO(b/372530534): remove this once we remove the flag. 2150 @Test testSubscribePropertyEvents_doNotSendGetInitialValueRequest_flagDisabled()2151 public void testSubscribePropertyEvents_doNotSendGetInitialValueRequest_flagDisabled() 2152 throws Exception { 2153 when(mFeatureFlags.alwaysSendInitialValueEvent()).thenReturn(false); 2154 2155 mCarPropertyManager.subscribePropertyEvents( 2156 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2157 mCarPropertyEventCallback); 2158 mCarPropertyManager.subscribePropertyEvents( 2159 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2160 mCarPropertyEventCallback); 2161 2162 verify(mICarProperty, never()).getAndDispatchInitialValue(any(), any()); 2163 } 2164 2165 @Test testSubscribePropertyEvents_doNotSendGetInitialValueRequest_legacyClient()2166 public void testSubscribePropertyEvents_doNotSendGetInitialValueRequest_legacyClient() 2167 throws Exception { 2168 setAppTargetSdk(Build.VERSION_CODES.VANILLA_ICE_CREAM); 2169 2170 mCarPropertyManager.subscribePropertyEvents( 2171 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2172 mCarPropertyEventCallback); 2173 mCarPropertyManager.subscribePropertyEvents( 2174 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2175 mCarPropertyEventCallback); 2176 2177 verify(mICarProperty, never()).getAndDispatchInitialValue(any(), any()); 2178 } 2179 2180 // Make sure that if a the subscription request does not need to be sent to car service, we will 2181 // send the getAndDispatchInitialValue request to make sure initial values are generated. 2182 @Test testSubscribePropertyEvents_sendGetInitialValueRequest_sameCallback()2183 public void testSubscribePropertyEvents_sendGetInitialValueRequest_sameCallback() 2184 throws Exception { 2185 mCarPropertyManager.subscribePropertyEvents( 2186 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2187 mCarPropertyEventCallback); 2188 mCarPropertyManager.subscribePropertyEvents( 2189 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2190 mCarPropertyEventCallback); 2191 2192 PropIdAreaId propIdAreaId = new PropIdAreaId(); 2193 propIdAreaId.propId = VENDOR_ON_CHANGE_PROPERTY; 2194 propIdAreaId.areaId = 0; 2195 verify(mICarProperty).getAndDispatchInitialValue(eq(List.of(propIdAreaId)), 2196 any(ICarPropertyEventListener.class)); 2197 } 2198 2199 // Make sure that if a the subscription request does not need to be sent to car service, we will 2200 // send the getAndDispatchInitialValue request to make sure initial values are generated. 2201 @Test testSubscribePropertyEvents_sendGetInitialValueRequest_differentCallback()2202 public void testSubscribePropertyEvents_sendGetInitialValueRequest_differentCallback() 2203 throws Exception { 2204 mCarPropertyManager.subscribePropertyEvents( 2205 VENDOR_ON_CHANGE_PROPERTY, /* areaId= */ 0, 2206 mCarPropertyEventCallback); 2207 mCarPropertyManager.subscribePropertyEvents(List.of( 2208 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2209 .setUpdateRateFast().build(), 2210 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2211 .build()), /* callbackExecutor= */ null, mCarPropertyEventCallback2); 2212 2213 // VENDOR_ON_CHANGE_PROPERTY is already subscribed, so we need initial value event for it. 2214 PropIdAreaId propIdAreaId = new PropIdAreaId(); 2215 propIdAreaId.propId = VENDOR_ON_CHANGE_PROPERTY; 2216 propIdAreaId.areaId = 0; 2217 verify(mICarProperty).getAndDispatchInitialValue(eq(List.of(propIdAreaId)), 2218 any(ICarPropertyEventListener.class)); 2219 } 2220 2221 @Test testSubscribePropertyEvents_noReadPermission()2222 public void testSubscribePropertyEvents_noReadPermission() throws Exception { 2223 int propId = VENDOR_CONTINUOUS_PROPERTY; 2224 when(mICarProperty.getSupportedNoReadPermPropIds(any())) 2225 .thenReturn(new int[] {propId}); 2226 2227 assertThrows(SecurityException.class, () -> mCarPropertyManager.subscribePropertyEvents( 2228 propId, mCarPropertyEventCallback)); 2229 } 2230 2231 @Test testSubscribePropertyEvents_getSupportedNoReadPermPropIds_remoteException()2232 public void testSubscribePropertyEvents_getSupportedNoReadPermPropIds_remoteException() 2233 throws Exception { 2234 int propId = VENDOR_CONTINUOUS_PROPERTY; 2235 when(mICarProperty.getSupportedNoReadPermPropIds(any())) 2236 .thenThrow(new RemoteException()); 2237 2238 assertThat(mCarPropertyManager.subscribePropertyEvents( 2239 propId, mCarPropertyEventCallback)).isFalse(); 2240 } 2241 2242 @Test testRegisterCallback_registersAgainWithDifferentExecutor_throws()2243 public void testRegisterCallback_registersAgainWithDifferentExecutor_throws() throws Exception { 2244 mCarPropertyManager.subscribePropertyEvents(List.of( 2245 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2246 .setUpdateRateFast().build(), 2247 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2248 .build()), 2249 mMockExecutor1, mCarPropertyEventCallback); 2250 2251 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 2252 mCarPropertyManager.subscribePropertyEvents(List.of( 2253 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2254 .setUpdateRateFast().build(), 2255 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2256 .build()), 2257 mMockExecutor2, mCarPropertyEventCallback)); 2258 assertWithMessage("Two executor subscription").that(thrown).hasMessageThat() 2259 .contains("A different executor is already associated with this callback," 2260 + " please use the same executor"); 2261 } 2262 2263 @Test testRegisterCallback_registersAgainWithSameExecutor()2264 public void testRegisterCallback_registersAgainWithSameExecutor() throws Exception { 2265 mCarPropertyManager.subscribePropertyEvents(List.of( 2266 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2267 .setUpdateRateFast().build(), 2268 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2269 .build()), 2270 mMockExecutor1, mCarPropertyEventCallback); 2271 mCarPropertyManager.subscribePropertyEvents(List.of( 2272 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY).addAreaId(0) 2273 .setUpdateRateFast().build(), 2274 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).addAreaId(0) 2275 .build()), 2276 mMockExecutor1, mCarPropertyEventCallback); 2277 2278 verify(mICarProperty).registerListener( 2279 eq(List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2280 CarPropertyManager.SENSOR_RATE_FAST, /* enableVur= */ true), 2281 createCarSubscriptionOption(VENDOR_ON_CHANGE_PROPERTY, new int[]{0}, 2282 CarPropertyManager.SENSOR_RATE_ONCHANGE))), 2283 any(ICarPropertyEventListener.class)); 2284 } 2285 2286 @Test testRegisterCallback_registersAgainIfTheFirstCallbackReturnsFalse()2287 public void testRegisterCallback_registersAgainIfTheFirstCallbackReturnsFalse() 2288 throws RemoteException { 2289 doThrow(IllegalArgumentException.class).doNothing().when(mICarProperty) 2290 .registerListener(eq(List.of( 2291 createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, 2292 new int[]{0}, FIRST_UPDATE_RATE_HZ))), 2293 any(ICarPropertyEventListener.class)); 2294 2295 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2296 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isFalse(); 2297 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2298 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2299 } 2300 2301 @Test testRegisterCallback_restoresOriginalRateHzIfTheSecondCallbackReturnsFalse()2302 public void testRegisterCallback_restoresOriginalRateHzIfTheSecondCallbackReturnsFalse() 2303 throws RemoteException { 2304 Float smallerUpdate = 1F; 2305 Float largerUpdate = 2F; 2306 doThrow(IllegalArgumentException.class).when(mICarProperty) 2307 .registerListener(eq(List.of(createCarSubscriptionOption( 2308 HVAC_TEMPERATURE_SET, new int[]{0}, largerUpdate))), 2309 any(ICarPropertyEventListener.class)); 2310 2311 CarPropertyValue<Float> goodValue = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 2312 Duration.ofSeconds(1).toNanos(), 17.0f); 2313 CarPropertyValue<Float> almostFreshValue = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 2314 Duration.ofMillis(1899).toNanos(), 18.0f); 2315 List<CarPropertyEvent> eventList = List.of( 2316 new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, goodValue), 2317 new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, 2318 almostFreshValue) 2319 ); 2320 CarPropertyConfig config = CarPropertyConfig.newBuilder(Float.class, HVAC_TEMPERATURE_SET, 2321 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2322 .addAreaIdConfig(new AreaIdConfig.Builder<Float>(0).build()) 2323 .setChangeMode(CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) 2324 .setMinSampleRate(0f) 2325 .setMaxSampleRate(10f).build(); 2326 addCarPropertyConfig(config); 2327 ICarPropertyEventListener listener = getCarPropertyEventListener(); 2328 ArgumentCaptor<CarPropertyValue> valueCaptor = 2329 ArgumentCaptor.forClass(CarPropertyValue.class); 2330 2331 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2332 HVAC_TEMPERATURE_SET, smallerUpdate)).isTrue(); 2333 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2334 HVAC_TEMPERATURE_SET, largerUpdate)).isFalse(); 2335 verify(mICarProperty, times(3)).registerListener( 2336 any(), any(ICarPropertyEventListener.class)); 2337 2338 listener.onEvent(eventList); 2339 verify(mCarPropertyEventCallback, timeout(5000)).onChangeEvent(valueCaptor.capture()); 2340 assertThat(valueCaptor.getAllValues()).containsExactly(goodValue); 2341 } 2342 2343 @Test testUnregisterCallback_doesNothingIfNothingRegistered()2344 public void testUnregisterCallback_doesNothingIfNothingRegistered() throws Exception { 2345 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, VENDOR_STATIC_PROPERTY); 2346 verify(mICarProperty, never()).unregisterListener(anyInt(), 2347 any(ICarPropertyEventListener.class)); 2348 } 2349 2350 @Test testUnsubscribePropertyEvents_doesNothingIfNothingRegistered()2351 public void testUnsubscribePropertyEvents_doesNothingIfNothingRegistered() throws Exception { 2352 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_STATIC_PROPERTY, 2353 mCarPropertyEventCallback); 2354 verify(mICarProperty, never()).unregisterListener(anyInt(), 2355 any(ICarPropertyEventListener.class)); 2356 } 2357 2358 @Test testUnregisterCallback_doesNothingIfPropertyIsNotRegisteredForCallback()2359 public void testUnregisterCallback_doesNothingIfPropertyIsNotRegisteredForCallback() 2360 throws Exception { 2361 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2362 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2363 2364 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, VENDOR_STATIC_PROPERTY); 2365 verify(mICarProperty, never()).unregisterListener(anyInt(), 2366 any(ICarPropertyEventListener.class)); 2367 } 2368 2369 @Test testUnsubscribePropertyEvents_doesNothingIfNothingIsNotRegisteredForCallback()2370 public void testUnsubscribePropertyEvents_doesNothingIfNothingIsNotRegisteredForCallback() 2371 throws Exception { 2372 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2373 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2374 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2375 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2376 2377 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_STATIC_PROPERTY, 2378 mCarPropertyEventCallback); 2379 verify(mICarProperty, never()).unregisterListener(anyInt(), 2380 any(ICarPropertyEventListener.class)); 2381 } 2382 2383 @Test testUnregisterCallback_doesNothingIfCallbackIsNotRegisteredForProperty()2384 public void testUnregisterCallback_doesNothingIfCallbackIsNotRegisteredForProperty() 2385 throws Exception { 2386 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2387 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2388 2389 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback2, 2390 VENDOR_CONTINUOUS_PROPERTY); 2391 verify(mICarProperty, never()).unregisterListener(anyInt(), 2392 any(ICarPropertyEventListener.class)); 2393 } 2394 2395 @Test testUnsubscribePropertyEvents_doesNothingIfCallbackIsNotRegisteredForProperty()2396 public void testUnsubscribePropertyEvents_doesNothingIfCallbackIsNotRegisteredForProperty() 2397 throws Exception { 2398 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2399 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2400 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2401 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2402 2403 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_CONTINUOUS_PROPERTY, 2404 mCarPropertyEventCallback2); 2405 verify(mICarProperty, never()).unregisterListener(anyInt(), 2406 any(ICarPropertyEventListener.class)); 2407 } 2408 2409 @Test testUnregisterCallback_doesNothingIfCarPropertyConfigNull()2410 public void testUnregisterCallback_doesNothingIfCarPropertyConfigNull() throws Exception { 2411 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2412 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2413 2414 setPropIdWithoutConfig(VENDOR_CONTINUOUS_PROPERTY); 2415 2416 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2417 VENDOR_CONTINUOUS_PROPERTY); 2418 verify(mICarProperty, never()).unregisterListener(anyInt(), 2419 any(ICarPropertyEventListener.class)); 2420 } 2421 2422 @Test testUnregisterCallback_doesNothingIfNoPermission()2423 public void testUnregisterCallback_doesNothingIfNoPermission() throws Exception { 2424 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2425 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2426 2427 setPropIdWithoutPermission(VENDOR_CONTINUOUS_PROPERTY); 2428 2429 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2430 VENDOR_CONTINUOUS_PROPERTY); 2431 verify(mICarProperty, never()).unregisterListener(anyInt(), 2432 any(ICarPropertyEventListener.class)); 2433 } 2434 2435 @Test testUnsubscribePropertyEvents_doesNothingIfCarPropertyConfigNull()2436 public void testUnsubscribePropertyEvents_doesNothingIfCarPropertyConfigNull() 2437 throws Exception { 2438 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2439 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2440 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2441 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2442 2443 setPropIdWithoutConfig(VENDOR_CONTINUOUS_PROPERTY); 2444 2445 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_CONTINUOUS_PROPERTY, 2446 mCarPropertyEventCallback); 2447 verify(mICarProperty, never()).unregisterListener(anyInt(), 2448 any(ICarPropertyEventListener.class)); 2449 } 2450 2451 @Test testUnsubscribePropertyEvents_doesNothingIfNoPermission()2452 public void testUnsubscribePropertyEvents_doesNothingIfNoPermission() 2453 throws Exception { 2454 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2455 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2456 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2457 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2458 2459 setPropIdWithoutPermission(VENDOR_CONTINUOUS_PROPERTY); 2460 2461 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_CONTINUOUS_PROPERTY, 2462 mCarPropertyEventCallback); 2463 verify(mICarProperty, never()).unregisterListener(anyInt(), 2464 any(ICarPropertyEventListener.class)); 2465 } 2466 2467 @Test testUnregisterCallback_unregistersCallbackForSingleProperty()2468 public void testUnregisterCallback_unregistersCallbackForSingleProperty() 2469 throws Exception { 2470 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2471 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2472 2473 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2474 VENDOR_CONTINUOUS_PROPERTY); 2475 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2476 any(ICarPropertyEventListener.class)); 2477 } 2478 2479 @Test testUnregisterCallback_unsubscribeCallbackForSingleProperty()2480 public void testUnregisterCallback_unsubscribeCallbackForSingleProperty() 2481 throws Exception { 2482 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2483 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2484 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2485 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2486 2487 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2488 VENDOR_CONTINUOUS_PROPERTY); 2489 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2490 any(ICarPropertyEventListener.class)); 2491 } 2492 2493 @Test testUnregisterCallback_unregistersCallbackForSpecificProperty()2494 public void testUnregisterCallback_unregistersCallbackForSpecificProperty() 2495 throws Exception { 2496 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2497 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2498 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2499 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2500 2501 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2502 VENDOR_ON_CHANGE_PROPERTY); 2503 verify(mICarProperty).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2504 any(ICarPropertyEventListener.class)); 2505 } 2506 2507 @Test testUnsubscribePropertyEvents_ignoreUserHalProp()2508 public void testUnsubscribePropertyEvents_ignoreUserHalProp() 2509 throws Exception { 2510 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 2511 2512 mCarPropertyManager.unsubscribePropertyEvents(INITIAL_USER_INFO, 2513 mCarPropertyEventCallback); 2514 2515 verify(mICarProperty, never()).unregisterListener(anyInt(), any()); 2516 } 2517 2518 @Test testUnregisterCallback_ignoreUserHalProp_beforeU()2519 public void testUnregisterCallback_ignoreUserHalProp_beforeU() 2520 throws Exception { 2521 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 2522 2523 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, INITIAL_USER_INFO); 2524 2525 verify(mICarProperty, never()).unregisterListener(anyInt(), any()); 2526 } 2527 2528 @Test testUnregisterCallback_ignoreUserHalProp_afterU()2529 public void testUnregisterCallback_ignoreUserHalProp_afterU() 2530 throws Exception { 2531 setAppTargetSdk(Build.VERSION_CODES.UPSIDE_DOWN_CAKE); 2532 2533 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, INITIAL_USER_INFO); 2534 2535 verify(mICarProperty, never()).unregisterListener(anyInt(), any()); 2536 } 2537 2538 @Test testUnsubscribePropertyEvents_unsubscribeCallbackForSpecificProperty()2539 public void testUnsubscribePropertyEvents_unsubscribeCallbackForSpecificProperty() 2540 throws Exception { 2541 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2542 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2543 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build(), 2544 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY) 2545 .build()), 2546 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2547 2548 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2549 VENDOR_CONTINUOUS_PROPERTY); 2550 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2551 any(ICarPropertyEventListener.class)); 2552 verify(mICarProperty, never()).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2553 any(ICarPropertyEventListener.class)); 2554 } 2555 2556 @Test testUnregisterCallback_unregistersCallbackForBothProperties()2557 public void testUnregisterCallback_unregistersCallbackForBothProperties() 2558 throws Exception { 2559 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2560 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2561 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2562 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2563 2564 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2565 verify(mICarProperty, times(2)).unregisterListener(mPropertyIdCaptor.capture(), 2566 any(ICarPropertyEventListener.class)); 2567 assertThat(mPropertyIdCaptor.getAllValues()).containsExactly(VENDOR_CONTINUOUS_PROPERTY, 2568 VENDOR_ON_CHANGE_PROPERTY); 2569 } 2570 2571 @Test testUnsubscribePropertyEvents_unsubscribeCallbackForBothProperties()2572 public void testUnsubscribePropertyEvents_unsubscribeCallbackForBothProperties() 2573 throws Exception { 2574 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2575 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2576 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build(), 2577 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY) 2578 .setUpdateRateNormal().build()), 2579 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2580 2581 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_CONTINUOUS_PROPERTY, 2582 mCarPropertyEventCallback); 2583 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2584 any(ICarPropertyEventListener.class)); 2585 } 2586 2587 @Test testUnregisterCallback_unregistersAllCallbackForSingleProperty()2588 public void testUnregisterCallback_unregistersAllCallbackForSingleProperty() 2589 throws Exception { 2590 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2591 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2592 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 2593 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2594 2595 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2596 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2597 any(ICarPropertyEventListener.class)); 2598 } 2599 2600 @Test testUnsubscribePropertyEvents_unsubscribeAllCallbackForSingleProperty()2601 public void testUnsubscribePropertyEvents_unsubscribeAllCallbackForSingleProperty() 2602 throws Exception { 2603 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2604 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2605 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2606 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2607 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2608 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY) 2609 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2610 /* callbackExecutor= */ null, mCarPropertyEventCallback2)).isTrue(); 2611 2612 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_CONTINUOUS_PROPERTY, 2613 mCarPropertyEventCallback); 2614 verify(mICarProperty).unregisterListener(eq(VENDOR_CONTINUOUS_PROPERTY), 2615 any(ICarPropertyEventListener.class)); 2616 verify(mICarProperty, never()).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2617 any(ICarPropertyEventListener.class)); 2618 } 2619 2620 @Test testUnregisterCallback_registerCalledIfBiggerRateRemoved()2621 public void testUnregisterCallback_registerCalledIfBiggerRateRemoved() throws Exception { 2622 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2623 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2624 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 2625 VENDOR_CONTINUOUS_PROPERTY, LARGER_UPDATE_RATE_HZ)).isTrue(); 2626 2627 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback2); 2628 verify(mICarProperty, never()).unregisterListener(anyInt(), 2629 any(ICarPropertyEventListener.class)); 2630 verify(mICarProperty, times(3)).registerListener( 2631 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 2632 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 2633 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2634 FIRST_UPDATE_RATE_HZ)), 2635 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2636 LARGER_UPDATE_RATE_HZ)), 2637 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2638 FIRST_UPDATE_RATE_HZ)) 2639 ); 2640 } 2641 2642 @Test testUnsubscribePropertyEvents_registerCalledIfBiggerRateRemoved()2643 public void testUnsubscribePropertyEvents_registerCalledIfBiggerRateRemoved() 2644 throws Exception { 2645 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2646 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2647 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2648 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2649 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2650 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2651 .setUpdateRateHz(LARGER_UPDATE_RATE_HZ).build()), 2652 /* callbackExecutor= */ null, mCarPropertyEventCallback2)).isTrue(); 2653 clearInvocations(mICarProperty); 2654 2655 mCarPropertyManager.unsubscribePropertyEvents(mCarPropertyEventCallback2); 2656 2657 verify(mICarProperty, never()).unregisterListener(anyInt(), 2658 any(ICarPropertyEventListener.class)); 2659 verify(mICarProperty, times(1)).registerListener( 2660 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 2661 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 2662 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2663 FIRST_UPDATE_RATE_HZ, /* enableVur= */ true)) 2664 ); 2665 } 2666 2667 @Test testUnregisterCallback_registerNotCalledIfSmallerRateRemoved()2668 public void testUnregisterCallback_registerNotCalledIfSmallerRateRemoved() 2669 throws Exception { 2670 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2671 VENDOR_CONTINUOUS_PROPERTY, FIRST_UPDATE_RATE_HZ)).isTrue(); 2672 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback2, 2673 VENDOR_CONTINUOUS_PROPERTY, LARGER_UPDATE_RATE_HZ)).isTrue(); 2674 2675 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2676 verify(mICarProperty, never()).unregisterListener(anyInt(), 2677 any(ICarPropertyEventListener.class)); 2678 verify(mICarProperty, times(2)).registerListener( 2679 mCarSubscriptionCaptor.capture(), any(ICarPropertyEventListener.class)); 2680 assertThat(mCarSubscriptionCaptor.getAllValues()).containsExactly( 2681 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2682 FIRST_UPDATE_RATE_HZ)), 2683 List.of(createCarSubscriptionOption(VENDOR_CONTINUOUS_PROPERTY, new int[]{0}, 2684 LARGER_UPDATE_RATE_HZ))); 2685 } 2686 2687 @Test testUnsubscribePropertyEvents_subscribeNotCalledIfSmallerRateremoved()2688 public void testUnsubscribePropertyEvents_subscribeNotCalledIfSmallerRateremoved() 2689 throws Exception { 2690 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2691 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2692 .setUpdateRateHz(FIRST_UPDATE_RATE_HZ).build()), 2693 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2694 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2695 new Subscription.Builder(VENDOR_CONTINUOUS_PROPERTY) 2696 .setUpdateRateHz(LARGER_UPDATE_RATE_HZ).build()), 2697 /* callbackExecutor= */ null, mCarPropertyEventCallback2)).isTrue(); 2698 clearInvocations(mICarProperty); 2699 2700 mCarPropertyManager.unsubscribePropertyEvents(mCarPropertyEventCallback2); 2701 2702 verify(mICarProperty, never()).unregisterListener(anyInt(), 2703 any(ICarPropertyEventListener.class)); 2704 } 2705 2706 @Test testUnregisterCallback_doesNothingWithPropertyIdIfNothingRegistered()2707 public void testUnregisterCallback_doesNothingWithPropertyIdIfNothingRegistered() 2708 throws Exception { 2709 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback); 2710 verify(mICarProperty, never()).unregisterListener(anyInt(), 2711 any(ICarPropertyEventListener.class)); 2712 } 2713 2714 @Test testUnsubscribePropertyEvents_doesNothingWithPropertyIdIfNothingRegistered()2715 public void testUnsubscribePropertyEvents_doesNothingWithPropertyIdIfNothingRegistered() 2716 throws Exception { 2717 mCarPropertyManager.unsubscribePropertyEvents(mCarPropertyEventCallback); 2718 verify(mICarProperty, never()).unregisterListener(anyInt(), 2719 any(ICarPropertyEventListener.class)); 2720 } 2721 2722 @Test testUnregisterCallback_returnsVoidForIllegalArgumentException()2723 public void testUnregisterCallback_returnsVoidForIllegalArgumentException() 2724 throws RemoteException { 2725 doThrow(IllegalArgumentException.class).when(mICarProperty).unregisterListener( 2726 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2727 2728 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2729 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2730 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2731 VENDOR_ON_CHANGE_PROPERTY); 2732 2733 verify(mICarProperty).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2734 any(ICarPropertyEventListener.class)); 2735 } 2736 2737 @Test testUnsubscribePropertyEvents_returnsVoidForIllegalArgumentException()2738 public void testUnsubscribePropertyEvents_returnsVoidForIllegalArgumentException() 2739 throws Exception { 2740 doThrow(IllegalArgumentException.class).when(mICarProperty).unregisterListener( 2741 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2742 2743 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2744 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).build()), 2745 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2746 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2747 VENDOR_ON_CHANGE_PROPERTY); 2748 2749 verify(mICarProperty).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2750 any(ICarPropertyEventListener.class)); 2751 } 2752 2753 @Test testUnregisterCallback_SecurityException()2754 public void testUnregisterCallback_SecurityException() throws Exception { 2755 doThrow(SecurityException.class).when(mICarProperty).unregisterListener( 2756 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2757 2758 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2759 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2760 assertThrows(SecurityException.class, 2761 () -> mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2762 VENDOR_ON_CHANGE_PROPERTY)); 2763 } 2764 2765 @Test testUnsubscribePropertyEvents_SecurityException()2766 public void testUnsubscribePropertyEvents_SecurityException() throws Exception { 2767 doThrow(SecurityException.class).when(mICarProperty).unregisterListener( 2768 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2769 2770 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2771 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).build()), 2772 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2773 2774 assertThrows(SecurityException.class, 2775 () -> mCarPropertyManager.unsubscribePropertyEvents(VENDOR_ON_CHANGE_PROPERTY, 2776 mCarPropertyEventCallback)); 2777 } 2778 2779 @Test testUnregisterCallback_recoversAfterSecurityException()2780 public void testUnregisterCallback_recoversAfterSecurityException() throws Exception { 2781 doThrow(SecurityException.class).doNothing().when(mICarProperty).unregisterListener( 2782 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2783 2784 assertThat(mCarPropertyManager.registerCallback(mCarPropertyEventCallback, 2785 VENDOR_ON_CHANGE_PROPERTY, CarPropertyManager.SENSOR_RATE_ONCHANGE)).isTrue(); 2786 assertThrows(SecurityException.class, 2787 () -> mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2788 VENDOR_ON_CHANGE_PROPERTY)); 2789 2790 mCarPropertyManager.unregisterCallback(mCarPropertyEventCallback, 2791 VENDOR_ON_CHANGE_PROPERTY); 2792 2793 verify(mICarProperty, times(2)).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2794 any(ICarPropertyEventListener.class)); 2795 } 2796 2797 @Test testUnsubscribePropertyEvents_recoversAfterSecurityException()2798 public void testUnsubscribePropertyEvents_recoversAfterSecurityException() throws Exception { 2799 doThrow(SecurityException.class).doNothing().when(mICarProperty).unregisterListener( 2800 eq(VENDOR_ON_CHANGE_PROPERTY), any(ICarPropertyEventListener.class)); 2801 assertThat(mCarPropertyManager.subscribePropertyEvents(List.of( 2802 new Subscription.Builder(VENDOR_ON_CHANGE_PROPERTY).build()), 2803 /* callbackExecutor= */ null, mCarPropertyEventCallback)).isTrue(); 2804 2805 assertThrows(SecurityException.class, 2806 () -> mCarPropertyManager.unsubscribePropertyEvents(VENDOR_ON_CHANGE_PROPERTY, 2807 mCarPropertyEventCallback)); 2808 mCarPropertyManager.unsubscribePropertyEvents(VENDOR_ON_CHANGE_PROPERTY, 2809 mCarPropertyEventCallback); 2810 2811 verify(mICarProperty, times(2)).unregisterListener(eq(VENDOR_ON_CHANGE_PROPERTY), 2812 any(ICarPropertyEventListener.class)); 2813 } 2814 2815 @Test testOnErrorEvent_callbackIsCalledWithErrorEvent()2816 public void testOnErrorEvent_callbackIsCalledWithErrorEvent() throws RemoteException { 2817 List<CarPropertyEvent> eventList = createErrorCarPropertyEventList(); 2818 CarPropertyConfig config = CarPropertyConfig.newBuilder(Float.class, HVAC_TEMPERATURE_SET, 2819 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2820 .addAreaIdConfig(new AreaIdConfig.Builder<Float>(0).build()).build(); 2821 addCarPropertyConfig(config); 2822 ICarPropertyEventListener listener = getCarPropertyEventListener(); 2823 2824 listener.onEvent(eventList); 2825 2826 // Wait until we get the on error event for the initial value. 2827 verify(mCarPropertyEventCallback, timeout(5000)).onErrorEvent(HVAC_TEMPERATURE_SET, 0, 2828 CarPropertyManager.CAR_SET_PROPERTY_ERROR_CODE_UNKNOWN); 2829 } 2830 2831 @Test testOnChangeEvent_callbackIsCalledWithEvent()2832 public void testOnChangeEvent_callbackIsCalledWithEvent() throws RemoteException { 2833 List<CarPropertyEvent> eventList = createCarPropertyEventList(); 2834 CarPropertyConfig config = CarPropertyConfig.newBuilder(Float.class, HVAC_TEMPERATURE_SET, 2835 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2836 .addAreaIdConfig(new AreaIdConfig.Builder<Float>(0).build()).build(); 2837 addCarPropertyConfig(config); 2838 ICarPropertyEventListener listener = getCarPropertyEventListener(); 2839 ArgumentCaptor<CarPropertyValue> value = ArgumentCaptor.forClass(CarPropertyValue.class); 2840 2841 listener.onEvent(eventList); 2842 2843 // Wait until we get the on property change event for the initial value. 2844 verify(mCarPropertyEventCallback, timeout(5000)).onChangeEvent(value.capture()); 2845 assertThat(value.getValue().getPropertyId()).isEqualTo(HVAC_TEMPERATURE_SET); 2846 assertThat(value.getValue().getValue()).isEqualTo(17.0f); 2847 } 2848 getCarPropertyEventListener()2849 private ICarPropertyEventListener getCarPropertyEventListener() throws RemoteException { 2850 ArgumentCaptor<ICarPropertyEventListener> carPropertyEventListenerArgumentCaptor = 2851 ArgumentCaptor.forClass(ICarPropertyEventListener.class); 2852 mCarPropertyManager.registerCallback(mCarPropertyEventCallback, HVAC_TEMPERATURE_SET, 2853 SENSOR_RATE_ONCHANGE); 2854 2855 verify(mICarProperty).registerListener(eq(List.of( 2856 createCarSubscriptionOption(HVAC_TEMPERATURE_SET, new int[]{0}, 2857 SENSOR_RATE_ONCHANGE))), 2858 carPropertyEventListenerArgumentCaptor.capture()); 2859 2860 return carPropertyEventListenerArgumentCaptor.getValue(); 2861 } 2862 2863 @Test testGetPropertyList()2864 public void testGetPropertyList() throws Exception { 2865 List<CarPropertyConfig> expectedConfigs = mock(List.class); 2866 when(mICarProperty.getPropertyList()) 2867 .thenReturn(new CarPropertyConfigList(expectedConfigs)); 2868 2869 2870 assertThat(mCarPropertyManager.getPropertyList()).isEqualTo(expectedConfigs); 2871 } 2872 2873 @Test testGetPropertyList_withPropertyIds()2874 public void testGetPropertyList_withPropertyIds() throws Exception { 2875 ArraySet<Integer> requestedPropertyIds = new ArraySet<>(Set.of( 2876 VENDOR_CONTINUOUS_PROPERTY, HVAC_TEMPERATURE_SET)); 2877 CarPropertyConfig config1 = CarPropertyConfig.newBuilder(Integer.class, 2878 VENDOR_CONTINUOUS_PROPERTY, 2879 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2880 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(0).build()).build(); 2881 CarPropertyConfig config2 = CarPropertyConfig.newBuilder(Float.class, 2882 HVAC_TEMPERATURE_SET, 2883 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2884 .addAreaIdConfig(new AreaIdConfig.Builder<Float>(0).build()).build(); 2885 addCarPropertyConfig(config1); 2886 addCarPropertyConfig(config2); 2887 2888 assertThat(mCarPropertyManager.getPropertyList(requestedPropertyIds)) 2889 .containsExactly(config1, config2); 2890 } 2891 2892 @Test testGetPropertyList_filterUnsupportedPropertyIds()2893 public void testGetPropertyList_filterUnsupportedPropertyIds() throws Exception { 2894 ArraySet<Integer> requestedPropertyIds = new ArraySet<>(Set.of( 2895 0, 1, VENDOR_CONTINUOUS_PROPERTY, HVAC_TEMPERATURE_SET)); 2896 CarPropertyConfig config1 = CarPropertyConfig.newBuilder(Integer.class, 2897 VENDOR_CONTINUOUS_PROPERTY, 2898 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2899 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(0).build()).build(); 2900 CarPropertyConfig config2 = CarPropertyConfig.newBuilder(Float.class, 2901 HVAC_TEMPERATURE_SET, 2902 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 2903 .addAreaIdConfig(new AreaIdConfig.Builder<Float>(0).build()).build(); 2904 addCarPropertyConfig(config1); 2905 addCarPropertyConfig(config2); 2906 2907 assertThat(mCarPropertyManager.getPropertyList(requestedPropertyIds)) 2908 .containsExactly(config1, config2); 2909 } 2910 2911 @Test testGetCarPropertyConfig()2912 public void testGetCarPropertyConfig() throws Exception { 2913 assertThat(mCarPropertyManager.getCarPropertyConfig(VENDOR_ON_CHANGE_PROPERTY)) 2914 .isEqualTo(mOnChangeCarPropertyConfig); 2915 } 2916 2917 @Test testGetCarPropertyConfig_noConfigReturned_notSupported()2918 public void testGetCarPropertyConfig_noConfigReturned_notSupported() throws Exception { 2919 setPropIdWithoutConfig(HVAC_TEMPERATURE_SET); 2920 2921 assertThat(mCarPropertyManager.getCarPropertyConfig(HVAC_TEMPERATURE_SET)).isNull(); 2922 } 2923 2924 @Test testGetCarPropertyConfig_noConfigReturned_noPermission()2925 public void testGetCarPropertyConfig_noConfigReturned_noPermission() throws Exception { 2926 setPropIdWithoutPermission(HVAC_TEMPERATURE_SET); 2927 2928 assertThat(mCarPropertyManager.getCarPropertyConfig(HVAC_TEMPERATURE_SET)).isNull(); 2929 } 2930 2931 @Test testGetCarPropertyConfig_unsupported()2932 public void testGetCarPropertyConfig_unsupported() throws Exception { 2933 assertThat(mCarPropertyManager.getCarPropertyConfig(/* propId= */ 0)).isNull(); 2934 } 2935 2936 @Test testGetAreaId_global()2937 public void testGetAreaId_global() throws Exception { 2938 assertThat(mCarPropertyManager.getAreaId(VENDOR_ON_CHANGE_PROPERTY, 0)).isEqualTo(0); 2939 } 2940 2941 @Test testGetAreaId_withArea()2942 public void testGetAreaId_withArea() throws Exception { 2943 int areaId = VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_1_CENTER; 2944 CarPropertyConfig config1 = CarPropertyConfig.newBuilder(Integer.class, 2945 HVAC_TEMPERATURE_SET, 2946 VehicleAreaType.VEHICLE_AREA_TYPE_SEAT) 2947 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId) 2948 .build()).build(); 2949 addCarPropertyConfig(config1); 2950 2951 assertThat(mCarPropertyManager.getAreaId( 2952 HVAC_TEMPERATURE_SET, VehicleAreaSeat.SEAT_ROW_1_LEFT)).isEqualTo(areaId); 2953 assertThat(mCarPropertyManager.getAreaId( 2954 HVAC_TEMPERATURE_SET, VehicleAreaSeat.SEAT_ROW_1_CENTER)).isEqualTo(areaId); 2955 } 2956 2957 @Test testGetAreaId_areaNotSupported()2958 public void testGetAreaId_areaNotSupported() throws Exception { 2959 int areaId = VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_1_CENTER; 2960 CarPropertyConfig config1 = CarPropertyConfig.newBuilder(Integer.class, 2961 HVAC_TEMPERATURE_SET, 2962 VehicleAreaType.VEHICLE_AREA_TYPE_SEAT) 2963 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId) 2964 .build()).build(); 2965 addCarPropertyConfig(config1); 2966 2967 assertThrows(IllegalArgumentException.class, () -> mCarPropertyManager.getAreaId( 2968 HVAC_TEMPERATURE_SET, VehicleAreaSeat.SEAT_ROW_1_RIGHT)); 2969 } 2970 2971 @Test testGetAreaId_propertyNotSupported()2972 public void testGetAreaId_propertyNotSupported() throws Exception { 2973 setPropIdWithoutConfig(HVAC_TEMPERATURE_SET); 2974 2975 assertThrows(IllegalArgumentException.class, () -> mCarPropertyManager.getAreaId( 2976 HVAC_TEMPERATURE_SET, 0)); 2977 } 2978 2979 @Test testGetAreaId_noPermissionToProperty()2980 public void testGetAreaId_noPermissionToProperty() throws Exception { 2981 setPropIdWithoutPermission(HVAC_TEMPERATURE_SET); 2982 2983 assertThrows(IllegalArgumentException.class, () -> mCarPropertyManager.getAreaId( 2984 HVAC_TEMPERATURE_SET, 0)); 2985 } 2986 2987 @Test testGetAreaId_remoteExceptionFromCarService()2988 public void testGetAreaId_remoteExceptionFromCarService() throws Exception { 2989 when(mICarProperty.getPropertyConfigList(new int[]{HVAC_TEMPERATURE_SET})) 2990 .thenThrow(new RemoteException()); 2991 2992 assertThrows(IllegalArgumentException.class, () -> mCarPropertyManager.getAreaId( 2993 HVAC_TEMPERATURE_SET, 0)); 2994 } 2995 2996 @Test testIsPropertyAvailable_withValueWithNotAvailableStatus()2997 public void testIsPropertyAvailable_withValueWithNotAvailableStatus() throws Exception { 2998 CarPropertyValue<Float> value = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 0, 2999 CarPropertyValue.STATUS_ERROR, TEST_TIMESTAMP, 17.0f); 3000 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(value); 3001 3002 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3003 .isFalse(); 3004 } 3005 3006 @Test testIsPropertyAvailable()3007 public void testIsPropertyAvailable() throws Exception { 3008 CarPropertyValue<Integer> expectedValue = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 3009 /* areaId= */ 0, CarPropertyValue.STATUS_AVAILABLE, /* timestamp= */ 0, 3010 /* value= */ 1); 3011 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenReturn(expectedValue); 3012 3013 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3014 .isTrue(); 3015 } 3016 3017 @Test testIsPropertyAvailable_syncOpTryAgain()3018 public void testIsPropertyAvailable_syncOpTryAgain() throws Exception { 3019 CarPropertyValue<Integer> expectedValue = new CarPropertyValue<>(HVAC_TEMPERATURE_SET, 3020 /* areaId= */ 0, CarPropertyValue.STATUS_AVAILABLE, /* timestamp= */ 0, 3021 /* value= */ 1); 3022 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 3023 new ServiceSpecificException(SYNC_OP_LIMIT_TRY_AGAIN)).thenReturn(expectedValue); 3024 3025 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3026 .isTrue(); 3027 verify(mICarProperty, times(2)).getProperty(HVAC_TEMPERATURE_SET, 0); 3028 } 3029 3030 @Test testIsPropertyAvailable_notAvailable()3031 public void testIsPropertyAvailable_notAvailable() throws Exception { 3032 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 3033 new ServiceSpecificException(VehicleHalStatusCode.STATUS_NOT_AVAILABLE)); 3034 3035 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3036 .isFalse(); 3037 } 3038 3039 @Test testIsPropertyAvailable_tryAgain()3040 public void testIsPropertyAvailable_tryAgain() throws Exception { 3041 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 3042 new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN)); 3043 3044 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3045 .isFalse(); 3046 } 3047 3048 3049 @Test testIsPropertyAvailable_RemoteException()3050 public void testIsPropertyAvailable_RemoteException() throws Exception { 3051 when(mICarProperty.getProperty(HVAC_TEMPERATURE_SET, 0)).thenThrow( 3052 new RemoteException()); 3053 3054 assertThat(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, /* areaId= */ 0)) 3055 .isFalse(); 3056 } 3057 3058 @Test testIsPropertyAvailable_unsupported()3059 public void testIsPropertyAvailable_unsupported() throws Exception { 3060 assertThat(mCarPropertyManager.isPropertyAvailable(/* propId= */ 0, /* areaId= */ 0)) 3061 .isFalse(); 3062 } 3063 3064 @Test testGetCarPropertyConfig_userHalProperty()3065 public void testGetCarPropertyConfig_userHalProperty() throws Exception { 3066 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3067 3068 assertThrows(IllegalArgumentException.class, 3069 () -> mCarPropertyManager.getCarPropertyConfig(INITIAL_USER_INFO)); 3070 } 3071 3072 @Test testGetPropertyList_userHalProperty()3073 public void testGetPropertyList_userHalProperty() throws Exception { 3074 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3075 3076 assertThrows(IllegalArgumentException.class, 3077 () -> mCarPropertyManager.getPropertyList( 3078 new ArraySet<Integer>(Set.of(HVAC_TEMPERATURE_SET, INITIAL_USER_INFO)))); 3079 } 3080 3081 @Test testGetAreaId_userHalProperty()3082 public void testGetAreaId_userHalProperty() throws Exception { 3083 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3084 3085 assertThrows(IllegalArgumentException.class, 3086 () -> mCarPropertyManager.getAreaId(INITIAL_USER_INFO, /* area= */ 0)); 3087 } 3088 3089 @Test testGetReadPermission_userHalProperty()3090 public void testGetReadPermission_userHalProperty() throws Exception { 3091 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3092 3093 assertThrows(IllegalArgumentException.class, 3094 () -> mCarPropertyManager.getReadPermission(INITIAL_USER_INFO)); 3095 } 3096 3097 @Test testGetWritePermission_userHalProperty()3098 public void testGetWritePermission_userHalProperty() throws Exception { 3099 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3100 3101 assertThrows(IllegalArgumentException.class, 3102 () -> mCarPropertyManager.getWritePermission(INITIAL_USER_INFO)); 3103 } 3104 3105 @Test testIsPropertyAvailable_userHalProperty()3106 public void testIsPropertyAvailable_userHalProperty() throws Exception { 3107 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3108 3109 assertThrows(IllegalArgumentException.class, 3110 () -> mCarPropertyManager.isPropertyAvailable(INITIAL_USER_INFO, /* areaId= */ 0)); 3111 } 3112 3113 @Test testGetProperty_userHalProperty()3114 public void testGetProperty_userHalProperty() throws Exception { 3115 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3116 3117 assertThrows(IllegalArgumentException.class, 3118 () -> mCarPropertyManager.getProperty(INITIAL_USER_INFO, /* areaId= */ 0)); 3119 } 3120 3121 @Test testGetBooleanProperty_userHalProperty()3122 public void testGetBooleanProperty_userHalProperty() throws Exception { 3123 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3124 3125 assertThrows(IllegalArgumentException.class, 3126 () -> mCarPropertyManager.getBooleanProperty(INITIAL_USER_INFO, /* areaId= */ 0)); 3127 } 3128 3129 @Test testSetBooleanProperty_userHalProperty()3130 public void testSetBooleanProperty_userHalProperty() throws Exception { 3131 setAppTargetSdk(Build.VERSION_CODES.TIRAMISU); 3132 3133 assertThrows(IllegalArgumentException.class, 3134 () -> mCarPropertyManager.setBooleanProperty(INITIAL_USER_INFO, /* areaId= */ 0, 3135 true)); 3136 } 3137 3138 @Test 3139 @IgnoreUnderRavenwood(blockedBy = android.os.ParcelableHolder.class) testGetMinMaxSupportedValue()3140 public void testGetMinMaxSupportedValue() throws Exception { 3141 int minValue = 123; 3142 int maxValue = 321; 3143 var minMaxSupportedPropertyValue = new MinMaxSupportedPropertyValue(); 3144 minMaxSupportedPropertyValue.minValue.setParcelable(new RawPropertyValue(minValue)); 3145 minMaxSupportedPropertyValue.maxValue.setParcelable(new RawPropertyValue(maxValue)); 3146 3147 when(mICarProperty.getMinMaxSupportedValue(INT32_PROP, 0)).thenReturn( 3148 minMaxSupportedPropertyValue); 3149 3150 MinMaxSupportedValue<Integer> result = mCarPropertyManager.getMinMaxSupportedValue( 3151 INT32_PROP, 0); 3152 3153 expectThat(result.getMinValue()).isEqualTo(minValue); 3154 expectThat(result.getMaxValue()).isEqualTo(maxValue); 3155 } 3156 3157 @Test 3158 @IgnoreUnderRavenwood(blockedBy = android.os.ParcelableHolder.class) testGetMinMaxSupportedValue_nullMinValue()3159 public void testGetMinMaxSupportedValue_nullMinValue() throws Exception { 3160 int maxValue = 321; 3161 var minMaxSupportedPropertyValue = new MinMaxSupportedPropertyValue(); 3162 minMaxSupportedPropertyValue.maxValue.setParcelable(new RawPropertyValue(maxValue)); 3163 3164 when(mICarProperty.getMinMaxSupportedValue(INT32_PROP, 0)).thenReturn( 3165 minMaxSupportedPropertyValue); 3166 3167 MinMaxSupportedValue<Integer> result = mCarPropertyManager.getMinMaxSupportedValue( 3168 INT32_PROP, 0); 3169 3170 expectThat(result.getMinValue()).isNull(); 3171 expectThat(result.getMaxValue()).isEqualTo(maxValue); 3172 } 3173 3174 @Test 3175 @IgnoreUnderRavenwood(blockedBy = android.os.ParcelableHolder.class) testGetMinMaxSupportedValue_nullMaxValue()3176 public void testGetMinMaxSupportedValue_nullMaxValue() throws Exception { 3177 int minValue = 123; 3178 var minMaxSupportedPropertyValue = new MinMaxSupportedPropertyValue(); 3179 minMaxSupportedPropertyValue.minValue.setParcelable(new RawPropertyValue(minValue)); 3180 3181 when(mICarProperty.getMinMaxSupportedValue(INT32_PROP, 0)).thenReturn( 3182 minMaxSupportedPropertyValue); 3183 3184 MinMaxSupportedValue<Integer> result = mCarPropertyManager.getMinMaxSupportedValue( 3185 INT32_PROP, 0); 3186 3187 expectThat(result.getMinValue()).isEqualTo(minValue); 3188 expectThat(result.getMaxValue()).isNull(); 3189 } 3190 3191 @Test testGetMinMaxSupportedValue_notSupportedPropertyId()3192 public void testGetMinMaxSupportedValue_notSupportedPropertyId() throws Exception { 3193 assertThrows(IllegalArgumentException.class, 3194 () -> mCarPropertyManager.getMinMaxSupportedValue(INVALID, 0)); 3195 } 3196 3197 @Test testGetMinMaxSupportedValue_remoteExceptionFromCarService()3198 public void testGetMinMaxSupportedValue_remoteExceptionFromCarService() throws Exception { 3199 when(mICarProperty.getMinMaxSupportedValue(anyInt(), anyInt())).thenThrow( 3200 new RemoteException()); 3201 3202 var minMaxSupportedValue = mCarPropertyManager.getMinMaxSupportedValue(INT32_PROP, 0); 3203 3204 assertThat(minMaxSupportedValue).isNotNull(); 3205 expectThat(minMaxSupportedValue.getMaxValue()).isNull(); 3206 expectThat(minMaxSupportedValue.getMinValue()).isNull(); 3207 } 3208 3209 @Test testGetMinMaxSupportedValue_IllegalArgumentExceptionFromCarService()3210 public void testGetMinMaxSupportedValue_IllegalArgumentExceptionFromCarService() 3211 throws Exception { 3212 when(mICarProperty.getMinMaxSupportedValue(anyInt(), anyInt())).thenThrow( 3213 new IllegalArgumentException()); 3214 3215 assertThrows(IllegalArgumentException.class, () -> 3216 mCarPropertyManager.getMinMaxSupportedValue(INT32_PROP, 0)); 3217 } 3218 3219 @Test testGetMinMaxSupportedValue_SecurityExceptionFromCarService()3220 public void testGetMinMaxSupportedValue_SecurityExceptionFromCarService() 3221 throws Exception { 3222 when(mICarProperty.getMinMaxSupportedValue(anyInt(), anyInt())).thenThrow( 3223 new SecurityException()); 3224 3225 assertThrows(SecurityException.class, () -> 3226 mCarPropertyManager.getMinMaxSupportedValue(INT32_PROP, 0)); 3227 } 3228 3229 @Test testGetMinMaxSupportedValue_ServiceSpecificExceptionFromCarService()3230 public void testGetMinMaxSupportedValue_ServiceSpecificExceptionFromCarService() 3231 throws Exception { 3232 when(mICarProperty.getMinMaxSupportedValue(anyInt(), anyInt())).thenThrow( 3233 new ServiceSpecificException(1)); 3234 3235 assertThrows(CarInternalErrorException.class, () -> 3236 mCarPropertyManager.getMinMaxSupportedValue(INT32_PROP, 0)); 3237 } 3238 3239 @Test testGetSupportedValuesList()3240 public void testGetSupportedValuesList() throws Exception { 3241 List<RawPropertyValue> resultsFromCarService = new ArrayList<>(); 3242 resultsFromCarService.add(new RawPropertyValue(0)); 3243 resultsFromCarService.add(new RawPropertyValue(1)); 3244 3245 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenReturn(resultsFromCarService); 3246 3247 List<Integer> result = mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0); 3248 3249 assertThat(result).containsExactly(0, 1); 3250 } 3251 3252 @Test testGetSupportedValuesList_notSupportedPropertyId()3253 public void testGetSupportedValuesList_notSupportedPropertyId() throws Exception { 3254 assertThrows(IllegalArgumentException.class, 3255 () -> mCarPropertyManager.getSupportedValuesList(INVALID, 0)); 3256 } 3257 3258 @Test testGetSupportedValuesList_nullFromCarService()3259 public void testGetSupportedValuesList_nullFromCarService() throws Exception { 3260 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenReturn(null); 3261 3262 List<Integer> result = mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0); 3263 3264 assertThat(result).isNull(); 3265 } 3266 3267 @Test testGetSupportedValuesList_RemoteExceptionFromCarService()3268 public void testGetSupportedValuesList_RemoteExceptionFromCarService() throws Exception { 3269 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenThrow(new RemoteException()); 3270 3271 List<Integer> result = mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0); 3272 3273 assertThat(result).isNull(); 3274 } 3275 3276 @Test testGetSupportedValuesList_SecurityExceptionFromCarService()3277 public void testGetSupportedValuesList_SecurityExceptionFromCarService() throws Exception { 3278 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenThrow( 3279 new SecurityException()); 3280 3281 assertThrows(SecurityException.class, 3282 () -> mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0)); 3283 } 3284 3285 @Test testGetSupportedValuesList_ServiceSpecificExceptionFromCarService()3286 public void testGetSupportedValuesList_ServiceSpecificExceptionFromCarService() 3287 throws Exception { 3288 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenThrow( 3289 new ServiceSpecificException(1)); 3290 3291 assertThrows(CarInternalErrorException.class, 3292 () -> mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0)); 3293 } 3294 3295 @Test testGetSupportedValuesList_IllegalArgumentExceptionFromCarService()3296 public void testGetSupportedValuesList_IllegalArgumentExceptionFromCarService() 3297 throws Exception { 3298 when(mICarProperty.getSupportedValuesList(INT32_PROP, 0)).thenThrow( 3299 new IllegalArgumentException()); 3300 3301 assertThrows(IllegalArgumentException.class, 3302 () -> mCarPropertyManager.getSupportedValuesList(INT32_PROP, 0)); 3303 } 3304 3305 @Test testRegisterSupportedValuesChangeCallback_propertyId_cb()3306 public void testRegisterSupportedValuesChangeCallback_propertyId_cb() throws Exception { 3307 int propertyId = INT32_PROP; 3308 int areaId1 = 1; 3309 int areaId2 = 2; 3310 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3311 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3312 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3313 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3314 .build()); 3315 3316 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3317 mSupportedValuesChangeCallback)).isTrue(); 3318 3319 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3320 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3321 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3322 3323 verify(mICarProperty).registerSupportedValuesChangeCallback( 3324 propIdAreaIdsCaptor.capture(), callbackCaptor.capture()); 3325 3326 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3327 assertThat(propIdAreaIds).hasSize(2); 3328 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3329 expectThat(propIdAreaIds.get(1).propId).isEqualTo(propertyId); 3330 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId1); 3331 expectThat(propIdAreaIds.get(1).areaId).isEqualTo(areaId2); 3332 3333 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3334 3335 PropIdAreaId propIdAreaId1 = new PropIdAreaId(); 3336 propIdAreaId1.propId = propertyId; 3337 propIdAreaId1.areaId = areaId1; 3338 PropIdAreaId propIdAreaId2 = new PropIdAreaId(); 3339 propIdAreaId2.propId = propertyId; 3340 propIdAreaId2.areaId = areaId2; 3341 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3342 3343 verify(mSupportedValuesChangeCallback, timeout(1000)).onSupportedValuesChange(propertyId, 3344 areaId1); 3345 verify(mSupportedValuesChangeCallback, timeout(1000)).onSupportedValuesChange(propertyId, 3346 areaId2); 3347 } 3348 3349 @Test testRegisterSupportedValuesChangeCallback_propertyId_areaId_cb()3350 public void testRegisterSupportedValuesChangeCallback_propertyId_areaId_cb() 3351 throws Exception { 3352 int propertyId = INT32_PROP; 3353 int areaId1 = 1; 3354 int areaId2 = 2; 3355 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3356 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3357 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3358 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3359 .build()); 3360 3361 // Only register to areaId2. 3362 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, areaId2, 3363 mSupportedValuesChangeCallback)).isTrue(); 3364 3365 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3366 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3367 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3368 3369 verify(mICarProperty).registerSupportedValuesChangeCallback( 3370 propIdAreaIdsCaptor.capture(), callbackCaptor.capture()); 3371 3372 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3373 assertThat(propIdAreaIds).hasSize(1); 3374 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3375 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId2); 3376 3377 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3378 3379 PropIdAreaId propIdAreaId1 = new PropIdAreaId(); 3380 propIdAreaId1.propId = propertyId; 3381 propIdAreaId1.areaId = areaId1; 3382 PropIdAreaId propIdAreaId2 = new PropIdAreaId(); 3383 propIdAreaId2.propId = propertyId; 3384 propIdAreaId2.areaId = areaId2; 3385 // The update for areaId1 must be ignored. 3386 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3387 3388 verify(mSupportedValuesChangeCallback, timeout(1000).times(1)).onSupportedValuesChange( 3389 propertyId, areaId2); 3390 } 3391 3392 @Test testRegisterSupportedValuesChangeCallback_propertyId_executor_cb()3393 public void testRegisterSupportedValuesChangeCallback_propertyId_executor_cb() 3394 throws Exception { 3395 int propertyId = INT32_PROP; 3396 int areaId1 = 1; 3397 int areaId2 = 2; 3398 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3399 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3400 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3401 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3402 .build()); 3403 3404 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3405 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3406 3407 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3408 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3409 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3410 3411 verify(mICarProperty).registerSupportedValuesChangeCallback( 3412 propIdAreaIdsCaptor.capture(), callbackCaptor.capture()); 3413 3414 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3415 assertThat(propIdAreaIds).hasSize(2); 3416 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3417 expectThat(propIdAreaIds.get(1).propId).isEqualTo(propertyId); 3418 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId1); 3419 expectThat(propIdAreaIds.get(1).areaId).isEqualTo(areaId2); 3420 3421 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3422 3423 PropIdAreaId propIdAreaId1 = new PropIdAreaId(); 3424 propIdAreaId1.propId = propertyId; 3425 propIdAreaId1.areaId = areaId1; 3426 PropIdAreaId propIdAreaId2 = new PropIdAreaId(); 3427 propIdAreaId2.propId = propertyId; 3428 propIdAreaId2.areaId = areaId2; 3429 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3430 3431 // Because we use a DirectExecutor, the callback is invoked synchronously. 3432 verify(mSupportedValuesChangeCallback).onSupportedValuesChange(propertyId, areaId1); 3433 verify(mSupportedValuesChangeCallback).onSupportedValuesChange(propertyId, areaId2); 3434 } 3435 3436 @Test testRegisterSupportedValuesChangeCallback_propertyId_areaId_executor_cb()3437 public void testRegisterSupportedValuesChangeCallback_propertyId_areaId_executor_cb() 3438 throws Exception { 3439 int propertyId = INT32_PROP; 3440 int areaId1 = 1; 3441 int areaId2 = 2; 3442 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3443 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3444 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3445 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3446 .build()); 3447 3448 // Only register to areaId2. 3449 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, areaId2, 3450 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3451 3452 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3453 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3454 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3455 3456 verify(mICarProperty).registerSupportedValuesChangeCallback( 3457 propIdAreaIdsCaptor.capture(), callbackCaptor.capture()); 3458 3459 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3460 assertThat(propIdAreaIds).hasSize(1); 3461 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3462 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId2); 3463 3464 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3465 3466 PropIdAreaId propIdAreaId1 = new PropIdAreaId(); 3467 propIdAreaId1.propId = propertyId; 3468 propIdAreaId1.areaId = areaId1; 3469 PropIdAreaId propIdAreaId2 = new PropIdAreaId(); 3470 propIdAreaId2.propId = propertyId; 3471 propIdAreaId2.areaId = areaId2; 3472 // The update for areaId1 must be ignored. 3473 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3474 3475 // Because we use a DirectExecutor, the callback is invoked synchronously. 3476 verify(mSupportedValuesChangeCallback, times(1)).onSupportedValuesChange( 3477 propertyId, areaId2); 3478 } 3479 3480 @Test testRegisterSupportedValuesChangeCallback_nullCallback()3481 public void testRegisterSupportedValuesChangeCallback_nullCallback() throws Exception { 3482 assertThrows(NullPointerException.class, () -> { 3483 mCarPropertyManager.registerSupportedValuesChangeCallback(INT32_PROP, /* cb= */ null); 3484 }); 3485 } 3486 3487 @Test testRegisterSupportedValuesChangeCallback_nullExecutor()3488 public void testRegisterSupportedValuesChangeCallback_nullExecutor() throws Exception { 3489 assertThrows(NullPointerException.class, () -> { 3490 mCarPropertyManager.registerSupportedValuesChangeCallback(INT32_PROP, 3491 /* executor= */ null, mSupportedValuesChangeCallback); 3492 }); 3493 } 3494 3495 @Test testRegisterSupportedValuesChangeCallback_withAreaId_nullExecutor()3496 public void testRegisterSupportedValuesChangeCallback_withAreaId_nullExecutor() 3497 throws Exception { 3498 assertThrows(NullPointerException.class, () -> { 3499 mCarPropertyManager.registerSupportedValuesChangeCallback(INT32_PROP, 3500 /* areaId= */ 0, /* executor= */ null, mSupportedValuesChangeCallback); 3501 }); 3502 } 3503 3504 @Test testRegisterSupportedValuesChangeCallback_propertyIdNotSupported()3505 public void testRegisterSupportedValuesChangeCallback_propertyIdNotSupported() 3506 throws Exception { 3507 assertThrows(IllegalArgumentException.class, () -> { 3508 mCarPropertyManager.registerSupportedValuesChangeCallback(INVALID, 3509 mSupportedValuesChangeCallback); 3510 }); 3511 } 3512 3513 @Test testRegisterSupportedValuesChangeCallback_noPermission()3514 public void testRegisterSupportedValuesChangeCallback_noPermission() throws Exception { 3515 setPropIdWithoutPermission(INT32_PROP); 3516 3517 assertThrows(SecurityException.class, () -> { 3518 mCarPropertyManager.registerSupportedValuesChangeCallback(INT32_PROP, 3519 mSupportedValuesChangeCallback); 3520 }); 3521 } 3522 3523 @Test testRegisterSupportedValuesChangeCallback_wrongExecutor()3524 public void testRegisterSupportedValuesChangeCallback_wrongExecutor() throws Exception { 3525 int propertyId = INT32_PROP; 3526 int areaId1 = 1; 3527 int areaId2 = 2; 3528 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3529 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3530 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3531 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3532 .build()); 3533 3534 // Associate the callback with the default executor. 3535 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3536 mSupportedValuesChangeCallback)).isTrue(); 3537 3538 // Associating the same callback with a different executor is not allowed. 3539 assertThrows(IllegalArgumentException.class, () -> { 3540 mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3541 DIRECT_EXECUTOR, mSupportedValuesChangeCallback); 3542 }); 3543 } 3544 3545 @Test testRegisterSupportedValuesChangeCallback_RemoteExceptionFromCarService()3546 public void testRegisterSupportedValuesChangeCallback_RemoteExceptionFromCarService() 3547 throws Exception { 3548 int propertyId = INT32_PROP; 3549 int areaId1 = 1; 3550 int areaId2 = 2; 3551 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3552 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3553 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3554 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3555 .build()); 3556 3557 doThrow(new RemoteException()).when(mICarProperty) 3558 .registerSupportedValuesChangeCallback(any(), any()); 3559 3560 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3561 mSupportedValuesChangeCallback)).isFalse(); 3562 } 3563 3564 @Test testRegisterSupportedValuesChangeCallback_ServiceSpecificExceptionFromCarService()3565 public void testRegisterSupportedValuesChangeCallback_ServiceSpecificExceptionFromCarService() 3566 throws Exception { 3567 int propertyId = INT32_PROP; 3568 int areaId1 = 1; 3569 int areaId2 = 2; 3570 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3571 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3572 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3573 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3574 .build()); 3575 3576 doThrow(new ServiceSpecificException(0)).when(mICarProperty) 3577 .registerSupportedValuesChangeCallback(any(), any()); 3578 3579 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3580 mSupportedValuesChangeCallback)).isFalse(); 3581 } 3582 3583 @Test testUnregisterSupportedValuesChangeCallback_propertyId()3584 public void testUnregisterSupportedValuesChangeCallback_propertyId() throws Exception { 3585 int propertyId = INT32_PROP; 3586 int areaId1 = 1; 3587 int areaId2 = 2; 3588 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3589 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3590 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3591 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3592 .build()); 3593 3594 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3595 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3596 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3597 DIRECT_EXECUTOR, mSupportedValuesChangeCallback2)).isTrue(); 3598 3599 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId); 3600 3601 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3602 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3603 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3604 3605 verify(mICarProperty, times(2)).registerSupportedValuesChangeCallback(any(), 3606 callbackCaptor.capture()); 3607 verify(mICarProperty).unregisterSupportedValuesChangeCallback(propIdAreaIdsCaptor.capture(), 3608 any()); 3609 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3610 assertThat(propIdAreaIds).hasSize(2); 3611 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3612 expectThat(propIdAreaIds.get(1).propId).isEqualTo(propertyId); 3613 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId1); 3614 expectThat(propIdAreaIds.get(1).areaId).isEqualTo(areaId2); 3615 3616 // After unregister, a new update event must not trigger the callback. 3617 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3618 PropIdAreaId propIdAreaId = new PropIdAreaId(); 3619 propIdAreaId.propId = propertyId; 3620 propIdAreaId.areaId = areaId1; 3621 callback.onSupportedValuesChange(List.of(propIdAreaId)); 3622 3623 verify(mSupportedValuesChangeCallback, never()).onSupportedValuesChange(anyInt(), anyInt()); 3624 verify(mSupportedValuesChangeCallback2, never()).onSupportedValuesChange(anyInt(), 3625 anyInt()); 3626 } 3627 3628 @Test testUnregisterSupportedValuesChangeCallback_propertyId_cb()3629 public void testUnregisterSupportedValuesChangeCallback_propertyId_cb() throws Exception { 3630 int propertyId = INT32_PROP; 3631 int areaId1 = 1; 3632 int areaId2 = 2; 3633 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3634 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3635 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3636 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3637 .build()); 3638 3639 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3640 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3641 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3642 DIRECT_EXECUTOR, mSupportedValuesChangeCallback2)).isTrue(); 3643 3644 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, 3645 mSupportedValuesChangeCallback2); 3646 3647 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3648 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3649 3650 verify(mICarProperty, times(2)).registerSupportedValuesChangeCallback(any(), 3651 callbackCaptor.capture()); 3652 verify(mICarProperty, never()).unregisterSupportedValuesChangeCallback(any(), any()); 3653 3654 // After unregister, a new update event must not trigger the callback. 3655 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3656 PropIdAreaId propIdAreaId = new PropIdAreaId(); 3657 propIdAreaId.propId = propertyId; 3658 propIdAreaId.areaId = areaId1; 3659 callback.onSupportedValuesChange(List.of(propIdAreaId)); 3660 3661 verify(mSupportedValuesChangeCallback).onSupportedValuesChange(propertyId, areaId1); 3662 verify(mSupportedValuesChangeCallback2, never()).onSupportedValuesChange(anyInt(), 3663 anyInt()); 3664 } 3665 3666 @Test testUnregisterSupportedValuesChangeCallback_propertyId_areaId_cb()3667 public void testUnregisterSupportedValuesChangeCallback_propertyId_areaId_cb() 3668 throws Exception { 3669 int propertyId = INT32_PROP; 3670 int areaId1 = 1; 3671 int areaId2 = 2; 3672 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3673 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3674 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3675 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3676 .build()); 3677 3678 // areaId1, areaid2 is registered for mSupportedValuesChangeCallback 3679 // areaId1, areaid2 is registered for mSupportedValuesChangeCallback2 3680 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3681 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3682 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3683 DIRECT_EXECUTOR, mSupportedValuesChangeCallback2)).isTrue(); 3684 3685 // areaId1 is registered for mSupportedValuesChangeCallback 3686 // areaId1, areaId2 is registered for mSupportedValuesChangeCallback2 3687 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, areaId2, 3688 mSupportedValuesChangeCallback); 3689 3690 ArgumentCaptor<List> propIdAreaIdsCaptor = ArgumentCaptor.forClass(List.class); 3691 ArgumentCaptor<ISupportedValuesChangeCallback> callbackCaptor = 3692 ArgumentCaptor.forClass(ISupportedValuesChangeCallback.class); 3693 3694 verify(mICarProperty, times(2)).registerSupportedValuesChangeCallback(any(), 3695 callbackCaptor.capture()); 3696 verify(mICarProperty, never()).unregisterSupportedValuesChangeCallback(any(), any()); 3697 3698 ISupportedValuesChangeCallback callback = callbackCaptor.getValue(); 3699 PropIdAreaId propIdAreaId1 = new PropIdAreaId(); 3700 propIdAreaId1.propId = propertyId; 3701 propIdAreaId1.areaId = areaId1; 3702 PropIdAreaId propIdAreaId2 = new PropIdAreaId(); 3703 propIdAreaId2.propId = propertyId; 3704 propIdAreaId2.areaId = areaId2; 3705 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3706 3707 verify(mSupportedValuesChangeCallback).onSupportedValuesChange(propertyId, areaId1); 3708 verify(mSupportedValuesChangeCallback, never()).onSupportedValuesChange(propertyId, 3709 areaId2); 3710 verify(mSupportedValuesChangeCallback2).onSupportedValuesChange(propertyId, areaId1); 3711 verify(mSupportedValuesChangeCallback2).onSupportedValuesChange(propertyId, areaId2); 3712 3713 // All callbacks for areaId2 is unregistered. 3714 // areaId1 is registered for mSupportedValuesChangeCallback 3715 // areaId1 is registered for mSupportedValuesChangeCallback2 3716 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, areaId2, 3717 mSupportedValuesChangeCallback2); 3718 3719 verify(mICarProperty).unregisterSupportedValuesChangeCallback(propIdAreaIdsCaptor.capture(), 3720 any()); 3721 List<PropIdAreaId> propIdAreaIds = (List<PropIdAreaId>) propIdAreaIdsCaptor.getValue(); 3722 assertThat(propIdAreaIds).hasSize(1); 3723 expectThat(propIdAreaIds.get(0).propId).isEqualTo(propertyId); 3724 expectThat(propIdAreaIds.get(0).areaId).isEqualTo(areaId2); 3725 3726 clearInvocations(mSupportedValuesChangeCallback); 3727 clearInvocations(mSupportedValuesChangeCallback2); 3728 3729 // Now both callbacks are only registered for areaId1. 3730 callback.onSupportedValuesChange(List.of(propIdAreaId1, propIdAreaId2)); 3731 3732 verify(mSupportedValuesChangeCallback).onSupportedValuesChange(propertyId, areaId1); 3733 verify(mSupportedValuesChangeCallback, never()).onSupportedValuesChange(propertyId, 3734 areaId2); 3735 verify(mSupportedValuesChangeCallback2).onSupportedValuesChange(propertyId, areaId1); 3736 verify(mSupportedValuesChangeCallback2, never()).onSupportedValuesChange(propertyId, 3737 areaId2); 3738 } 3739 3740 @Test testUnregisterSupportedValuesChangeCallback_ignoreUnregistered()3741 public void testUnregisterSupportedValuesChangeCallback_ignoreUnregistered() throws Exception { 3742 int propertyId = INT32_PROP; 3743 int areaId1 = 1; 3744 int areaId2 = 2; 3745 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3746 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3747 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3748 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3749 .build()); 3750 3751 // This does nothing. 3752 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId); 3753 } 3754 3755 @Test testUnregisterSupportedValuesChangeCallback_ignoreUnregisteredAreaId()3756 public void testUnregisterSupportedValuesChangeCallback_ignoreUnregisteredAreaId() 3757 throws Exception { 3758 int propertyId = INT32_PROP; 3759 int areaId1 = 1; 3760 int areaId2 = 2; 3761 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3762 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3763 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3764 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3765 .build()); 3766 3767 mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, areaId1, 3768 mSupportedValuesChangeCallback); 3769 3770 // This does nothing. 3771 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, areaId2, 3772 mSupportedValuesChangeCallback); 3773 } 3774 3775 @Test testUnregisterSupportedValuesChangeCallback_remoteExceptionIgnored()3776 public void testUnregisterSupportedValuesChangeCallback_remoteExceptionIgnored() 3777 throws Exception { 3778 int propertyId = INT32_PROP; 3779 int areaId1 = 1; 3780 int areaId2 = 2; 3781 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3782 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3783 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3784 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3785 .build()); 3786 doThrow(new RemoteException()).when(mICarProperty).unregisterSupportedValuesChangeCallback( 3787 any(), any()); 3788 3789 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3790 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3791 3792 // This must not throw any exception. 3793 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId); 3794 } 3795 3796 @Test testUnregisterSupportedValuesChangeCallback_unsetExecutor()3797 public void testUnregisterSupportedValuesChangeCallback_unsetExecutor() 3798 throws Exception { 3799 int propertyId = INT32_PROP; 3800 int areaId1 = 1; 3801 int areaId2 = 2; 3802 addCarPropertyConfig(CarPropertyConfig.newBuilder(Integer.class, 3803 INT32_PROP, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL) 3804 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId1).build()) 3805 .addAreaIdConfig(new AreaIdConfig.Builder<Integer>(areaId2).build()) 3806 .build()); 3807 3808 // areaId1, areaid2 is registered for mSupportedValuesChangeCallback 3809 // areaId1, areaid2 is registered for mSupportedValuesChangeCallback2 3810 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3811 DIRECT_EXECUTOR, mSupportedValuesChangeCallback)).isTrue(); 3812 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3813 DIRECT_EXECUTOR, mSupportedValuesChangeCallback2)).isTrue(); 3814 3815 // After this mSupportedValuesChangeCallback is unlinked with DIRECT_EXECUTOR. 3816 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, 3817 mSupportedValuesChangeCallback); 3818 3819 // Associate mSupportedValuesChangeCallback with the default executor should be allowed. 3820 assertThat(mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3821 mSupportedValuesChangeCallback)).isTrue(); 3822 3823 // At this point, mSupportedValuesChangeCallback2 is still registered for 3824 // [propertyId, areaId2] and linked with DEFAULT_EXECUTOR. 3825 mCarPropertyManager.unregisterSupportedValuesChangeCallback(propertyId, 3826 areaId1, mSupportedValuesChangeCallback2); 3827 3828 // Linking mSupportedValuesChangeCallback2 with the default executor must not be allowed. 3829 assertThrows(IllegalArgumentException.class, () -> { 3830 mCarPropertyManager.registerSupportedValuesChangeCallback(propertyId, 3831 areaId1, mSupportedValuesChangeCallback2); 3832 }); 3833 } 3834 } 3835