1 /* 2 * Copyright (C) 2021 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 package android.app.time.cts.shell; 17 18 import static android.app.time.cts.shell.DeviceConfigKeys.LocationTimeZoneManager.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE; 19 import static android.app.time.cts.shell.DeviceConfigKeys.LocationTimeZoneManager.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE; 20 import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME; 21 22 import static org.junit.Assume.assumeTrue; 23 24 import java.io.BufferedReader; 25 import java.io.StringReader; 26 import java.util.Objects; 27 28 /** 29 * A class for interacting with the {@code location_time_zone_manager} service via the shell "cmd" 30 * command-line interface. 31 */ 32 public class LocationTimeZoneManagerShellHelper { 33 /** 34 * The index of the primary location time zone provider, used for shell commands. 35 */ 36 public static final int PRIMARY_PROVIDER_INDEX = 0; 37 38 /** 39 * The index of the secondary location time zone provider, used for shell commands. 40 */ 41 public static final int SECONDARY_PROVIDER_INDEX = 1; 42 43 /** 44 * The "disabled" provider mode (equivalent to there being no provider configured). 45 */ 46 public static final String PROVIDER_MODE_DISABLED = 47 DeviceConfigKeys.LocationTimeZoneManager.PROVIDER_MODE_DISABLED; 48 49 /** 50 * The "simulated" provider mode. 51 */ 52 public static final String PROVIDER_MODE_SIMULATED = 53 DeviceConfigKeys.LocationTimeZoneManager.PROVIDER_MODE_SIMULATED; 54 55 /** 56 * Simulated provider test command that simulates the bind succeeding. 57 */ 58 public static final String SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND = "on_bind"; 59 60 /** 61 * Simulated provider test command that simulates the provider reporting uncertainty. 62 */ 63 public static final String SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN = "uncertain"; 64 65 /** 66 * Simulated provider test command that simulates a successful time zone detection. 67 */ 68 public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS = "success"; 69 70 /** 71 * Argument for {@link #SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS} to specify TZDB time zone IDs. 72 */ 73 public static final String SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ = "tz"; 74 75 /** 76 * The name of the service for shell commands. 77 */ 78 private static final String SERVICE_NAME = "location_time_zone_manager"; 79 80 /** 81 * A shell command that starts the service (after stop). 82 */ 83 private static final String SHELL_COMMAND_START = "start"; 84 85 /** 86 * A shell command that stops the service. 87 */ 88 private static final String SHELL_COMMAND_STOP = "stop"; 89 90 /** 91 * A shell command that tells the service to record state information during tests. The next 92 * argument value is "true" or "false". 93 */ 94 private static final String SHELL_COMMAND_RECORD_PROVIDER_STATES = "record_provider_states"; 95 96 /** 97 * A shell command that tells the service to dump its current state. 98 */ 99 private static final String SHELL_COMMAND_DUMP_STATE = "dump_state"; 100 101 /** 102 * Option for {@link #SHELL_COMMAND_DUMP_STATE} that tells it to dump state as a binary proto. 103 */ 104 private static final String DUMP_STATE_OPTION_PROTO = "proto"; 105 106 /** 107 * A shell command that sends test commands to a provider 108 */ 109 private static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND = 110 "send_provider_test_command"; 111 112 private static final String SHELL_CMD_PREFIX = "cmd " + SERVICE_NAME + " "; 113 114 private final DeviceShellCommandExecutor mShellCommandExecutor; 115 private final DeviceConfigShellHelper mDeviceConfigShellHelper; 116 LocationTimeZoneManagerShellHelper(DeviceShellCommandExecutor shellCommandExecutor)117 public LocationTimeZoneManagerShellHelper(DeviceShellCommandExecutor shellCommandExecutor) { 118 mShellCommandExecutor = Objects.requireNonNull(shellCommandExecutor); 119 mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor); 120 } 121 122 /** 123 * Throws an {@link org.junit.AssumptionViolatedException} if the location_time_zone_manager 124 * service is not found. The service can be turned off in config, so this can be used to prevent 125 * CTS tests that need it from running. 126 */ assumeLocationTimeZoneManagerIsPresent()127 public void assumeLocationTimeZoneManagerIsPresent() throws Exception { 128 assumeTrue(isLocationTimeZoneManagerPresent()); 129 } 130 131 /** 132 * Returns {@code false} if the location_time_zone_manager service is not found. 133 */ isLocationTimeZoneManagerPresent()134 public boolean isLocationTimeZoneManagerPresent() throws Exception { 135 // Look for the service name in "cmd -l". 136 String serviceList = mShellCommandExecutor.executeToString("cmd -l"); 137 try (BufferedReader reader = new BufferedReader(new StringReader(serviceList))) { 138 String serviceName; 139 while ((serviceName = reader.readLine()) != null) { 140 serviceName = serviceName.trim(); 141 if (SERVICE_NAME.equals(serviceName)) { 142 return true; 143 } 144 } 145 return false; 146 } 147 } 148 149 /** Executes "start". Starts the service. */ start()150 public void start() throws Exception { 151 mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_START); 152 } 153 154 /** Executes "stop". Stops the service. */ stop()155 public void stop() throws Exception { 156 mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + SHELL_COMMAND_STOP); 157 } 158 159 /** Executes "record_provider_states". */ recordProviderStates(boolean enabled)160 public void recordProviderStates(boolean enabled) throws Exception { 161 String cmd = String.format("%s %s", SHELL_COMMAND_RECORD_PROVIDER_STATES, enabled); 162 mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd); 163 } 164 165 /** Executes "dump_state". */ dumpState()166 public byte[] dumpState() throws Exception { 167 String cmd = String.format("%s --%s", SHELL_COMMAND_DUMP_STATE, DUMP_STATE_OPTION_PROTO); 168 return mShellCommandExecutor.executeToBytes(SHELL_CMD_PREFIX + cmd); 169 } 170 171 /** Modifies a provider's mode using "device_config" commands. */ setProviderModeOverride(int providerIndex, String mode)172 public void setProviderModeOverride(int providerIndex, String mode) throws Exception { 173 String deviceConfigKey; 174 if (providerIndex == PRIMARY_PROVIDER_INDEX) { 175 deviceConfigKey = KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE; 176 } else { 177 deviceConfigKey = KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_MODE_OVERRIDE; 178 } 179 180 if (mode == null) { 181 mDeviceConfigShellHelper.delete(NAMESPACE_SYSTEM_TIME, deviceConfigKey); 182 } else { 183 mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME, deviceConfigKey, mode); 184 } 185 } 186 187 /** 188 * Simulates a provider successfully binding using the "send_provider_test_command" command. 189 */ simulateProviderBind(int providerIndex)190 public void simulateProviderBind(int providerIndex) throws Exception { 191 sendProviderTestCommand(providerIndex, SIMULATED_PROVIDER_TEST_COMMAND_ON_BIND); 192 } 193 194 /** 195 * Simulates a provider generating an uncertain report using the "send_provider_test_command" 196 * command. 197 */ simulateProviderUncertain(int providerIndex)198 public void simulateProviderUncertain(int providerIndex) throws Exception { 199 sendProviderTestCommand(providerIndex, SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN); 200 } 201 202 /** 203 * Simulates a provider generating a suggestion using the "send_provider_test_command" command. 204 */ simulateProviderSuggestion(int providerIndex, String... zoneIds)205 public void simulateProviderSuggestion(int providerIndex, String... zoneIds) 206 throws Exception { 207 String timeZoneIds = String.join("&", zoneIds); 208 String testCommand = String.format("%s %s=string_array:%s", 209 SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS, 210 SIMULATED_PROVIDER_TEST_COMMAND_SUCCESS_ARG_KEY_TZ, 211 timeZoneIds); 212 sendProviderTestCommand(providerIndex, testCommand); 213 } 214 215 /** Executes "send_provider_test_command". */ sendProviderTestCommand(int providerIndex, String testCommand)216 private void sendProviderTestCommand(int providerIndex, String testCommand) throws Exception { 217 String cmd = String.format("%s %s %s", 218 SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND, providerIndex, testCommand); 219 mShellCommandExecutor.executeToTrimmedString(SHELL_CMD_PREFIX + cmd); 220 } 221 } 222