1 /* 2 * Copyright (C) 2023 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.extendedapitest; 18 19 import static android.hardware.automotive.vehicle.TestVendorProperty.VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.junit.Assert.assertThrows; 24 import static org.junit.Assume.assumeTrue; 25 26 import android.car.Car; 27 import android.car.extendedapitest.testbase.CarApiTestBase; 28 import android.car.hardware.CarPropertyConfig; 29 import android.car.hardware.property.CarInternalErrorException; 30 import android.car.hardware.property.CarPropertyManager; 31 import android.car.test.CarTestManager; 32 import android.hardware.automotive.vehicle.VehicleArea; 33 import android.hardware.automotive.vehicle.VehiclePropertyGroup; 34 import android.hardware.automotive.vehicle.VehiclePropertyType; 35 import android.os.Binder; 36 import android.os.Handler; 37 import android.os.HandlerExecutor; 38 import android.os.HandlerThread; 39 import android.util.ArraySet; 40 import android.util.Log; 41 42 import com.android.car.test.TestPropertyAsyncCallback; 43 import com.android.compatibility.common.util.ApiTest; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 49 import java.util.ArrayList; 50 import java.util.List; 51 import java.util.Set; 52 import java.util.concurrent.Executor; 53 54 public final class CarPropertyManagerTest extends CarApiTestBase { 55 private static final int EXPECTED_VENDOR_ERROR_CODE = 0x00ab; 56 private static final int NUMBER_OF_TEST_CODES = 0x2000; 57 // 557862912 58 private static final int STARTING_TEST_CODES = 0x3000 | VehiclePropertyGroup.VENDOR 59 | VehicleArea.GLOBAL | VehiclePropertyType.INT32; 60 private static final int END_TEST_CODES = 0x3000 + NUMBER_OF_TEST_CODES 61 | VehiclePropertyGroup.VENDOR | VehicleArea.GLOBAL | VehiclePropertyType.INT32; 62 private static final String TAG = CarPropertyManagerTest.class.getSimpleName(); 63 64 private final HandlerThread mHandlerThread = new HandlerThread(getClass().getSimpleName()); 65 66 private CarPropertyManager mCarPropertyManager; 67 private CarTestManager mTestManager; 68 private Binder mToken; 69 private Handler mHandler; 70 71 @Before setUp()72 public void setUp() throws Exception { 73 mHandlerThread.start(); 74 mHandler = new Handler(mHandlerThread.getLooper()); 75 mCarPropertyManager = (CarPropertyManager) getCar().getCarManager(Car.PROPERTY_SERVICE); 76 assertThat(mCarPropertyManager).isNotNull(); 77 mTestManager = getCarService(Car.TEST_SERVICE); 78 mToken = new Binder("stop_car_service"); 79 } 80 81 @After tearDown()82 public void tearDown() throws Exception { 83 mHandlerThread.quitSafely(); 84 } 85 86 @ApiTest(apis = {"android.car.hardware.property.CarInternalErrorException#getVendorErrorCode"}) 87 @Test testGetProperty_withVendorPropertyId_throws()88 public void testGetProperty_withVendorPropertyId_throws() { 89 List<CarPropertyConfig> carPropertyConfigList = mCarPropertyManager.getPropertyList( 90 new ArraySet(List.of(VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING))); 91 assumeTrue("VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING is supported", 92 !carPropertyConfigList.isEmpty()); 93 CarInternalErrorException thrown = assertThrows(CarInternalErrorException.class, () -> 94 mCarPropertyManager.getProperty(VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING, 95 /* areaId = */ 0)); 96 97 assertThat(thrown.getVendorErrorCode()).isEqualTo(EXPECTED_VENDOR_ERROR_CODE); 98 } 99 100 @ApiTest(apis = {"android.car.hardware.property.CarInternalErrorException#getVendorErrorCode"}) 101 @Test testSetProperty_withVendorPropertyId_throws()102 public void testSetProperty_withVendorPropertyId_throws() { 103 List<CarPropertyConfig> carPropertyConfigList = mCarPropertyManager.getPropertyList( 104 new ArraySet(List.of(VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING))); 105 assumeTrue("VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING is supported", 106 !carPropertyConfigList.isEmpty()); 107 CarInternalErrorException thrown = assertThrows(CarInternalErrorException.class, 108 () -> mCarPropertyManager.setProperty(Integer.class, 109 VENDOR_PROPERTY_FOR_ERROR_CODE_TESTING, /* areaId = */ 0, /* val= */ 0)); 110 111 assertThat(thrown.getVendorErrorCode()).isEqualTo(EXPECTED_VENDOR_ERROR_CODE); 112 } 113 114 @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getPropertyList()"}) 115 @Test testGetPropertyListWithLargeNumberOfConfigs()116 public void testGetPropertyListWithLargeNumberOfConfigs() throws Exception { 117 List<CarPropertyConfig> carPropertyConfigsListBeforeGenerating = 118 mCarPropertyManager.getPropertyList(); 119 Set<Integer> resultSet = new ArraySet<>(); 120 for (int i = 0; i < carPropertyConfigsListBeforeGenerating.size(); i++) { 121 resultSet.add(carPropertyConfigsListBeforeGenerating.get(i).getPropertyId()); 122 } 123 boolean isDebugCommandSupported = false; 124 try { 125 for (int i = STARTING_TEST_CODES; i < END_TEST_CODES; i++) { 126 assertThat(i).isNotIn(resultSet); 127 } 128 Log.d(TAG, "Stopping car service for test"); 129 mTestManager.stopCarService(mToken); 130 String result = CarApiTestBase.executeShellCommand( 131 "dumpsys car_service gen-test-vendor-configs"); 132 Log.d(TAG, "Starting car service for test"); 133 mTestManager.startCarService(mToken); 134 135 List<CarPropertyConfig> carPropertyConfigsList = mCarPropertyManager.getPropertyList(); 136 resultSet = new ArraySet<>(); 137 for (int i = 0; i < carPropertyConfigsList.size(); i++) { 138 resultSet.add(carPropertyConfigsList.get(i).getPropertyId()); 139 } 140 isDebugCommandSupported = result.equals("successfully generated vendor configs\n"); 141 assumeTrue("successfully generated vendor configs, VHAL gen-test-vendor-configs " 142 + "debug command is supported", 143 isDebugCommandSupported); 144 for (int i = STARTING_TEST_CODES; i < END_TEST_CODES; i++) { 145 assertThat(i).isIn(resultSet); 146 } 147 } finally { 148 restoreCarService(isDebugCommandSupported); 149 } 150 } 151 152 @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#setPropertiesAsync" 153 + "(List, long, CancellationSignal, Executor, SetPropertyCallback)"}) 154 @Test testSetPropertiesAsyncWithLargeNumberRequests()155 public void testSetPropertiesAsyncWithLargeNumberRequests() throws Exception { 156 boolean isDebugCommandSupported = false; 157 try { 158 Log.d(TAG, "Stopping car service for test"); 159 mTestManager.stopCarService(mToken); 160 String result = CarApiTestBase.executeShellCommand( 161 "dumpsys car_service gen-test-vendor-configs"); 162 Log.d(TAG, "Starting car service for test"); 163 mTestManager.startCarService(mToken); 164 isDebugCommandSupported = result.equals("successfully generated vendor configs\n"); 165 assumeTrue("successfully generated vendor configs, VHAL gen-test-vendor-configs " 166 + "debug command is supported", 167 isDebugCommandSupported); 168 Executor callbackExecutor = new HandlerExecutor(mHandler); 169 Set<Integer> setPropertyIds = new ArraySet<>(); 170 List<CarPropertyManager.SetPropertyRequest<?>> setPropertyRequests = new ArrayList<>(); 171 172 for (int i = STARTING_TEST_CODES; i < END_TEST_CODES; i++) { 173 CarPropertyManager.SetPropertyRequest setRequest = 174 mCarPropertyManager.generateSetPropertyRequest( 175 i, /* areaId= */ 0, /* value= */ 10); 176 setRequest.setWaitForPropertyUpdate(false); 177 setPropertyRequests.add(setRequest); 178 setPropertyIds.add(setRequest.getRequestId()); 179 } 180 TestPropertyAsyncCallback callback = new TestPropertyAsyncCallback( 181 setPropertyIds); 182 mCarPropertyManager.setPropertiesAsync(setPropertyRequests, /* timeoutInMs= */ 10000, 183 /* cancellationSignal= */ null, callbackExecutor, callback); 184 185 callback.waitAndFinish(/* timeoutInMs= */ 30000); 186 assertThat(callback.getTestErrors()).isEmpty(); 187 List<CarPropertyManager.SetPropertyResult> results = callback.getSetResultList(); 188 assertThat(results).hasSize(NUMBER_OF_TEST_CODES); 189 assertThat(callback.getErrorList().size()).isEqualTo(0); 190 } finally { 191 Log.d(TAG, "restoring car service"); 192 restoreCarService(isDebugCommandSupported); 193 } 194 } 195 196 @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getPropertiesAsync" 197 + "(List, long, CancellationSignal, Executor, GetPropertyCallback)"}) 198 @Test testGetPropertiesAsyncWithLargeNumberRequests()199 public void testGetPropertiesAsyncWithLargeNumberRequests() throws Exception { 200 boolean isDebugCommandSupported = false; 201 try { 202 Log.d(TAG, "Stopping car service for test"); 203 mTestManager.stopCarService(mToken); 204 String result = CarApiTestBase.executeShellCommand( 205 "dumpsys car_service gen-test-vendor-configs"); 206 isDebugCommandSupported = result.equals("successfully generated vendor configs\n"); 207 Log.d(TAG, "Starting car service for test"); 208 mTestManager.startCarService(mToken); 209 assumeTrue("successfully generated vendor configs, VHAL gen-test-vendor-configs " 210 + "debug command is supported", 211 isDebugCommandSupported); 212 213 Executor callbackExecutor = new HandlerExecutor(mHandler); 214 Set<Integer> getPropertyIds = new ArraySet<>(); 215 List<CarPropertyManager.GetPropertyRequest> getPropertyRequests = new ArrayList<>(); 216 217 for (int i = STARTING_TEST_CODES; i < END_TEST_CODES; i++) { 218 CarPropertyManager.GetPropertyRequest getRequest = 219 mCarPropertyManager.generateGetPropertyRequest( 220 i, /* areaId= */ 0); 221 getPropertyRequests.add(getRequest); 222 getPropertyIds.add(getRequest.getRequestId()); 223 } 224 TestPropertyAsyncCallback callback = new TestPropertyAsyncCallback( 225 getPropertyIds); 226 mCarPropertyManager.getPropertiesAsync(getPropertyRequests, /* timeoutInMs= */ 10000, 227 /* cancellationSignal= */ null, callbackExecutor, callback); 228 229 callback.waitAndFinish(/* timeoutInMs= */ 30000); 230 assertThat(callback.getTestErrors()).isEmpty(); 231 List<CarPropertyManager.GetPropertyResult<?>> results = callback.getGetResultList(); 232 assertThat(results.size()).isEqualTo(NUMBER_OF_TEST_CODES); 233 assertThat(callback.getErrorList()).isEmpty(); 234 } finally { 235 Log.d(TAG, "restoring car service"); 236 restoreCarService(isDebugCommandSupported); 237 } 238 } 239 restoreCarService(boolean isDebugCommandSupported)240 private void restoreCarService(boolean isDebugCommandSupported) throws Exception { 241 Binder restartCarService = new Binder("restart_car_service_after_test"); 242 try { 243 Log.d(TAG, "Stopping car service for test"); 244 mTestManager.stopCarService(restartCarService); 245 if (isDebugCommandSupported) { 246 String result = CarApiTestBase.executeShellCommand( 247 "dumpsys car_service restore-vendor-configs"); 248 assertThat(result.equals("successfully restored vendor configs\n")).isTrue(); 249 } 250 Log.d(TAG, "Starting car service for test"); 251 } finally { 252 mTestManager.startCarService(restartCarService); 253 } 254 } 255 } 256