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.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assume.assumeFalse; 23 import static org.junit.Assume.assumeTrue; 24 25 import android.car.feature.Flags; 26 import android.platform.test.annotations.RequiresFlagsEnabled; 27 import android.platform.test.flag.junit.CheckFlagsRule; 28 import android.platform.test.flag.junit.host.HostFlagsValueProvider; 29 30 import com.android.car.wifi.CarWifiDumpProto; 31 import com.android.compatibility.common.util.ApiTest; 32 import com.android.compatibility.common.util.PollingCheck; 33 import com.android.compatibility.common.util.ProtoUtils; 34 import com.android.tradefed.invoker.TestInformation; 35 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 36 import com.android.tradefed.testtype.junit4.AfterClassWithInfo; 37 import com.android.tradefed.testtype.junit4.BeforeClassWithInfo; 38 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.util.concurrent.TimeUnit; 44 45 @RunWith(DeviceJUnit4ClassRunner.class) 46 public final class CarWifiHostTest extends CarHostJUnit4TestCase { 47 private static final long TIMEOUT_MS = TimeUnit.SECONDS.toMillis(15); 48 49 private static final String GET_PERSISTENT_TETHERING = 50 "settings get global android.car.ENABLE_PERSISTENT_TETHERING"; 51 private static final String ENABLE_PERSISTENT_TETHERING = 52 "settings put global android.car.ENABLE_PERSISTENT_TETHERING true"; 53 private static final String DISABLE_PERSISTENT_TETHERING = 54 "settings put global android.car.ENABLE_PERSISTENT_TETHERING false"; 55 private static final String CMD_DUMPSYS_WIFI = 56 "dumpsys car_service --services CarWifiService"; 57 private static final String CMD_DUMPSYS_WIFI_PROTO = 58 "dumpsys car_service --services CarWifiService --proto"; 59 private static final String WIFI_HOTSPOT_ON = "cmd wifi start-softap CarWifiService open"; 60 private static final String WIFI_HOTSPOT_OFF = "cmd wifi stop-softap"; 61 private static boolean sTetheringStatusBefore; 62 private static boolean sTetheringPersistingBefore; 63 64 @Rule 65 public final CheckFlagsRule mCheckFlagsRule = 66 HostFlagsValueProvider.createCheckFlagsRule(this::getDevice); 67 68 /** 69 * Prepares the device to restore back to original state post-test. 70 * 71 * @param testInfo Test Information 72 * @throws Exception if connection with device is lost and cannot be recovered. 73 */ 74 @BeforeClassWithInfo beforeClassWithDevice(TestInformation testInfo)75 public static void beforeClassWithDevice(TestInformation testInfo) throws Exception { 76 // TODO: b/324961709 - Re-factor to use proto dump 77 sTetheringStatusBefore = testInfo.getDevice().executeShellCommand(CMD_DUMPSYS_WIFI) 78 .contains("Tethering enabled: true"); 79 sTetheringPersistingBefore = testInfo.getDevice().executeShellCommand( 80 GET_PERSISTENT_TETHERING).contains("true"); 81 } 82 83 /** 84 * Restores original state to conditions before testing. 85 * 86 * @param testInfo Test Information 87 * @throws Exception if connection with device is lost and cannot be recovered. 88 */ 89 @AfterClassWithInfo afterClassWithInfo(TestInformation testInfo)90 public static void afterClassWithInfo(TestInformation testInfo) throws Exception { 91 String hotspotCommand = (sTetheringStatusBefore ? WIFI_HOTSPOT_ON : WIFI_HOTSPOT_OFF); 92 testInfo.getDevice().executeShellCommand(hotspotCommand); 93 94 String persistTetheringCommand = 95 (sTetheringPersistingBefore ? ENABLE_PERSISTENT_TETHERING 96 : DISABLE_PERSISTENT_TETHERING); 97 testInfo.getDevice().executeShellCommand(persistTetheringCommand); 98 } 99 100 @Test 101 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 102 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_enablingWithCapability_autoShutdownDisabled()103 public void testPersistTetheringCarSetting_enablingWithCapability_autoShutdownDisabled() 104 throws Exception { 105 assumeTrue("Skipping test: tethering capability disabled", 106 isPersistTetheringCapabilityEnabled()); 107 executeCommand(ENABLE_PERSISTENT_TETHERING); 108 assertThat(isAutoShutdownEnabled()).isFalse(); 109 } 110 111 @Test 112 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 113 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_disablingWithCapability_autoShutdownEnabled()114 public void testPersistTetheringCarSetting_disablingWithCapability_autoShutdownEnabled() 115 throws Exception { 116 assumeTrue("Skipping test: tethering capability disabled", 117 isPersistTetheringCapabilityEnabled()); 118 executeCommand(DISABLE_PERSISTENT_TETHERING); 119 assertThat(isAutoShutdownEnabled()).isTrue(); 120 } 121 122 @Test 123 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 124 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_enablingNoCapability_autoShutdownUnchanged()125 public void testPersistTetheringCarSetting_enablingNoCapability_autoShutdownUnchanged() 126 throws Exception { 127 assumeFalse("Skipping test: tethering capability enabled", 128 isPersistTetheringCapabilityEnabled()); 129 boolean autoShutdownEnabledBefore = isAutoShutdownEnabled(); 130 executeCommand(ENABLE_PERSISTENT_TETHERING); 131 assertThat(isAutoShutdownEnabled()).isEqualTo(autoShutdownEnabledBefore); 132 } 133 134 @Test 135 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 136 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_disablingNoCapability_autoShutdownUnchanged()137 public void testPersistTetheringCarSetting_disablingNoCapability_autoShutdownUnchanged() 138 throws Exception { 139 assumeFalse("Skipping test: tethering capability enabled", 140 isPersistTetheringCapabilityEnabled()); 141 boolean autoShutdownEnabledBefore = isAutoShutdownEnabled(); 142 executeCommand(DISABLE_PERSISTENT_TETHERING); 143 assertThat(isAutoShutdownEnabled()).isEqualTo(autoShutdownEnabledBefore); 144 } 145 146 @Test 147 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 148 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_withCapabilityTetheringEnabled_tetheringOnReboot()149 public void testPersistTetheringCarSetting_withCapabilityTetheringEnabled_tetheringOnReboot() 150 throws Exception { 151 assumeTrue("Skipping test: tethering capability disabled", 152 isPersistTetheringCapabilityEnabled()); 153 154 enablePersistTetheringAndReboot(/* enableTethering= */ true); 155 156 PollingCheck.check("Tethering NOT enabled", TIMEOUT_MS, this::isTetheringEnabled); 157 assertThat(isAutoShutdownEnabled()).isFalse(); 158 } 159 160 @Test 161 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 162 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_withCapabilityTetheringDisabled_noTetheringOnReboot()163 public void testPersistTetheringCarSetting_withCapabilityTetheringDisabled_noTetheringOnReboot() 164 throws Exception { 165 assumeTrue("Skipping test: tethering capability disabled", 166 isPersistTetheringCapabilityEnabled()); 167 168 enablePersistTetheringAndReboot(/* enableTethering= */ false); 169 170 assertThrows(AssertionError.class, 171 () -> PollingCheck.check("Tethering NOT enabled", TIMEOUT_MS, 172 this::isTetheringEnabled)); 173 } 174 175 @Test 176 @RequiresFlagsEnabled({Flags.FLAG_PERSIST_AP_SETTINGS, Flags.FLAG_CAR_DUMP_TO_PROTO}) 177 @ApiTest(apis = {"android.car.settings.CarSettings#ENABLE_PERSISTENT_TETHERING"}) testPersistTetheringCarSetting_noCapabilityTetheringEnabled_noTetheringOnReboot()178 public void testPersistTetheringCarSetting_noCapabilityTetheringEnabled_noTetheringOnReboot() 179 throws Exception { 180 assumeFalse("Skipping test: tethering capability enabled", 181 isPersistTetheringCapabilityEnabled()); 182 183 enablePersistTetheringAndReboot(/* enableTethering= */ true); 184 185 assertThrows(AssertionError.class, 186 () -> PollingCheck.check("Tethering NOT enabled", TIMEOUT_MS, 187 this::isTetheringEnabled)); 188 } 189 isTetheringEnabled()190 private boolean isTetheringEnabled() throws Exception { 191 CarWifiDumpProto carWifiDump = ProtoUtils.getProto(getDevice(), 192 CarWifiDumpProto.parser(), CMD_DUMPSYS_WIFI_PROTO); 193 return carWifiDump.getTetheringEnabled(); 194 } 195 isAutoShutdownEnabled()196 private boolean isAutoShutdownEnabled() throws Exception { 197 CarWifiDumpProto carWifiDump = ProtoUtils.getProto(getDevice(), 198 CarWifiDumpProto.parser(), CMD_DUMPSYS_WIFI_PROTO); 199 return carWifiDump.getAutoShutdownEnabled(); 200 } 201 isPersistTetheringCapabilityEnabled()202 private boolean isPersistTetheringCapabilityEnabled() throws Exception { 203 CarWifiDumpProto carWifiDump = ProtoUtils.getProto(getDevice(), 204 CarWifiDumpProto.parser(), CMD_DUMPSYS_WIFI_PROTO); 205 return carWifiDump.getPersistTetheringCapabilitiesEnabled(); 206 } 207 enablePersistTetheringAndReboot(boolean enableTethering)208 private void enablePersistTetheringAndReboot(boolean enableTethering) throws Exception { 209 String hotspotCommand = (enableTethering ? WIFI_HOTSPOT_ON : WIFI_HOTSPOT_OFF); 210 executeCommand(hotspotCommand); 211 212 executeCommand(ENABLE_PERSISTENT_TETHERING); 213 214 reboot(); 215 waitForCarServiceReady(); 216 waitForUserInitialized(/* userId= */ 0); 217 } 218 } 219