1 /* 2 * Copyright (C) 2025 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.car.Car.CAR_PROPERTY_SIMULATION_SERVICE; 20 import static android.car.Car.PROPERTY_SERVICE; 21 22 import static com.google.common.truth.Truth.assertThat; 23 import static com.google.common.truth.Truth.assertWithMessage; 24 25 import static org.junit.Assert.assertThrows; 26 import static org.junit.Assume.assumeTrue; 27 28 import android.annotation.Nullable; 29 import android.car.Car; 30 import android.car.builtin.os.BuildHelper; 31 import android.car.extendedapitest.testbase.CarApiTestBase; 32 import android.car.feature.Flags; 33 import android.car.hardware.CarPropertyConfig; 34 import android.car.hardware.CarPropertyValue; 35 import android.car.hardware.property.CarPropertyManager; 36 import android.car.hardware.property.CarPropertySimulationManager; 37 import android.car.test.PermissionsCheckerRule; 38 import android.car.test.PermissionsCheckerRule.EnsureHasPermission; 39 import android.platform.test.annotations.RequiresFlagsEnabled; 40 41 import androidx.annotation.NonNull; 42 43 import com.android.compatibility.common.util.ApiTest; 44 45 import org.junit.Before; 46 import org.junit.Rule; 47 import org.junit.Test; 48 49 import java.util.List; 50 import java.util.concurrent.CountDownLatch; 51 import java.util.concurrent.TimeUnit; 52 53 public class CarPropertySimulationManagerTest extends CarApiTestBase { 54 55 private static final long TIMEOUT_MS = 5000; 56 57 @Nullable 58 private CarPropertySimulationManager mCarPropertySimulationManager; 59 private CarPropertyManager mCarPropertyManager; 60 61 @Rule 62 public final PermissionsCheckerRule mPermissionsCheckerRule = new PermissionsCheckerRule(); 63 64 @Before setUp()65 public void setUp() throws Exception { 66 mCarPropertySimulationManager = 67 (CarPropertySimulationManager) 68 getCar().getCarManager(CAR_PROPERTY_SIMULATION_SERVICE); 69 mCarPropertyManager = (CarPropertyManager) getCar().getCarManager(PROPERTY_SERVICE); 70 } 71 72 @Test 73 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 74 @ApiTest( 75 apis = { 76 "android.car.CarProjectionManager#enableInjectionMode", 77 "android.car.CarProjectionManager#isVehiclePropertyInjectionModeEnabled", 78 "android.car.CarProjectionManager#disableInjectionMode" 79 }) 80 @EnsureHasPermission(Car.PERMISSION_INJECT_VEHICLE_PROPERTIES) testEnableInjectionMode()81 public void testEnableInjectionMode() { 82 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 83 84 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isFalse(); 85 long injectionModeStartTimeNanos = 86 mCarPropertySimulationManager.enableInjectionMode(List.of()); 87 88 assertThat(injectionModeStartTimeNanos).isGreaterThan(0L); 89 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isTrue(); 90 mCarPropertySimulationManager.disableInjectionMode(); 91 92 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isFalse(); 93 } 94 95 @Test 96 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 97 @ApiTest( 98 apis = { 99 "android.car.CarProjectionManager#startRecordingVehicleProperties", 100 "android.car.CarProjectionManager#isRecordingVehicleProperties", 101 "android.car.CarProjectionManager#stopRecordingVehicleProperties" 102 }) 103 @EnsureHasPermission(Car.PERMISSION_RECORD_VEHICLE_PROPERTIES) testRecordingVehicleProperties()104 public void testRecordingVehicleProperties() throws Exception { 105 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 106 107 CountDownLatch onRecordingFinishedLatch = new CountDownLatch(1); 108 CarRecordingListener listener = new CarRecordingListener(/* carPropertyEventsLatch= */ null, 109 onRecordingFinishedLatch); 110 List<CarPropertyConfig> configList = mCarPropertyManager.getPropertyList(); 111 112 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 113 List<CarPropertyConfig> carPropertyConfigsRecorded = 114 mCarPropertySimulationManager.startRecordingVehicleProperties( 115 /* callbackExecutor= */ null, listener); 116 117 assertThat(carPropertyConfigsRecorded).isNotNull(); 118 assertThat(carPropertyConfigsRecorded.size()).isAtLeast(configList.size()); 119 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isTrue(); 120 mCarPropertySimulationManager.stopRecordingVehicleProperties(); 121 assertWithMessage("CarPropertySimulationManager stop recording") 122 .that(onRecordingFinishedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); 123 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 124 } 125 126 @Test 127 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 128 @ApiTest( 129 apis = { 130 "android.car.CarProjectionManager#startRecordingVehicleProperties", 131 "android.car.CarProjectionManager#isRecordingVehicleProperties", 132 "android.car.CarProjectionManager#stopRecordingVehicleProperties" 133 }) 134 @EnsureHasPermission(Car.PERMISSION_RECORD_VEHICLE_PROPERTIES) testRecordingVehiclePropertiesTwice()135 public void testRecordingVehiclePropertiesTwice() throws Exception { 136 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 137 138 CountDownLatch onRecordingFinishedLatch = new CountDownLatch(1); 139 CarRecordingListener listener = new CarRecordingListener(/* carPropertyEventsLatch= */ null, 140 onRecordingFinishedLatch); 141 142 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 143 mCarPropertySimulationManager.startRecordingVehicleProperties( 144 /* callbackExecutor= */ null, listener); 145 IllegalStateException thrown = 146 assertThrows( 147 IllegalStateException.class, 148 () -> 149 mCarPropertySimulationManager.startRecordingVehicleProperties( 150 /* callbackExecutor= */ null, listener)); 151 152 assertThat(thrown).hasMessageThat().contains("Recording already in progress"); 153 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isTrue(); 154 mCarPropertySimulationManager.stopRecordingVehicleProperties(); 155 assertWithMessage("CarPropertySimulationManager stop recording") 156 .that(onRecordingFinishedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); 157 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 158 } 159 160 @Test 161 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 162 @ApiTest(apis = {"android.car.CarProjectionManager#startRecordingVehicleProperties"}) 163 @EnsureHasPermission(Car.PERMISSION_RECORD_VEHICLE_PROPERTIES) testRecordingVehiclePropertiesNullListener()164 public void testRecordingVehiclePropertiesNullListener() { 165 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 166 167 assertThrows( 168 NullPointerException.class, 169 () -> 170 mCarPropertySimulationManager.startRecordingVehicleProperties( 171 /* callbackExecutor= */ null, /* listener= */ null)); 172 } 173 174 @Test 175 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 176 @ApiTest( 177 apis = { 178 "android.car.CarProjectionManager#enableInjectionMode", 179 "android.car.CarProjectionManager#isVehiclePropertyInjectionModeEnabled", 180 "android.car.CarProjectionManager#disableInjectionMode" 181 }) 182 @EnsureHasPermission(Car.PERMISSION_INJECT_VEHICLE_PROPERTIES) testEnableInjectionModeTwice()183 public void testEnableInjectionModeTwice() { 184 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 185 186 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isFalse(); 187 long injectionStartTime = mCarPropertySimulationManager.enableInjectionMode(List.of()); 188 assertThat(injectionStartTime).isAtLeast(0L); 189 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isTrue(); 190 191 long secondInjectionStartTime = 192 mCarPropertySimulationManager.enableInjectionMode(List.of()); 193 194 assertThat(secondInjectionStartTime).isEqualTo(-1L); 195 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isTrue(); 196 mCarPropertySimulationManager.disableInjectionMode(); 197 assertThat(mCarPropertySimulationManager.isVehiclePropertyInjectionModeEnabled()).isFalse(); 198 } 199 200 @Test 201 @RequiresFlagsEnabled(Flags.FLAG_CAR_PROPERTY_SIMULATION) 202 @ApiTest( 203 apis = { 204 "android.car.CarProjectionManager#isRecordingVehicleProperties", 205 "android.car.CarProjectionManager#stopRecordingVehicleProperties" 206 }) 207 @EnsureHasPermission(Car.PERMISSION_RECORD_VEHICLE_PROPERTIES) testStopRecordingVehiclePropertiesWhenAlreadyDisabled()208 public void testStopRecordingVehiclePropertiesWhenAlreadyDisabled() { 209 assumeTrue(BuildHelper.isEngBuild() || BuildHelper.isUserDebugBuild()); 210 211 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 212 mCarPropertySimulationManager.stopRecordingVehicleProperties(); 213 assertThat(mCarPropertySimulationManager.isRecordingVehicleProperties()).isFalse(); 214 } 215 216 private static final class CarRecordingListener 217 implements CarPropertySimulationManager.CarRecorderListener { 218 219 private final CountDownLatch mCarPropertyEventsLatch; 220 private final CountDownLatch mCarPropertyFinishedLatch; 221 CarRecordingListener( CountDownLatch carPropertyEventsLatch, CountDownLatch onRecordingFinishedLatch)222 private CarRecordingListener( 223 CountDownLatch carPropertyEventsLatch, CountDownLatch onRecordingFinishedLatch) { 224 mCarPropertyEventsLatch = 225 carPropertyEventsLatch == null ? new CountDownLatch(0) : carPropertyEventsLatch; 226 mCarPropertyFinishedLatch = 227 onRecordingFinishedLatch == null 228 ? new CountDownLatch(0) 229 : onRecordingFinishedLatch; 230 } 231 232 @Override onCarPropertyEvents(@onNull List<CarPropertyValue<?>> carPropertyValues)233 public void onCarPropertyEvents(@NonNull List<CarPropertyValue<?>> carPropertyValues) { 234 mCarPropertyEventsLatch.countDown(); 235 } 236 237 @Override onRecordingFinished()238 public void onRecordingFinished() { 239 mCarPropertyFinishedLatch.countDown(); 240 } 241 } 242 243 } 244