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 com.android.server.timedetector; 17 18 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME; 19 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME; 20 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_TIME; 21 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_NETWORK_TIME; 22 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE; 23 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED; 24 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME; 25 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED; 26 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME; 27 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_TIME_STATE; 28 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME; 29 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME; 30 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_MANUAL_TIME; 31 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_NETWORK_TIME; 32 import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_TELEPHONY_TIME; 33 import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME; 34 35 import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE; 36 import static com.android.server.timedetector.ServerFlags.KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE; 37 38 import android.app.time.ExternalTimeSuggestion; 39 import android.app.time.TimeConfiguration; 40 import android.app.time.TimeState; 41 import android.app.time.UnixEpochTime; 42 import android.app.timedetector.ManualTimeSuggestion; 43 import android.app.timedetector.TelephonyTimeSuggestion; 44 import android.os.ShellCommand; 45 import android.os.UserHandle; 46 47 import java.io.PrintWriter; 48 import java.util.function.Consumer; 49 import java.util.function.Supplier; 50 51 /** Implements the shell command interface for {@link TimeDetectorService}. */ 52 class TimeDetectorShellCommand extends ShellCommand { 53 54 private final TimeDetectorService mInterface; 55 TimeDetectorShellCommand(TimeDetectorService timeDetectorService)56 TimeDetectorShellCommand(TimeDetectorService timeDetectorService) { 57 mInterface = timeDetectorService; 58 } 59 60 @Override onCommand(String cmd)61 public int onCommand(String cmd) { 62 if (cmd == null) { 63 return handleDefaultCommands(cmd); 64 } 65 66 switch (cmd) { 67 case SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED: 68 return runIsAutoDetectionEnabled(); 69 case SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED: 70 return runSetAutoDetectionEnabled(); 71 case SHELL_COMMAND_SUGGEST_MANUAL_TIME: 72 return runSuggestManualTime(); 73 case SHELL_COMMAND_SUGGEST_TELEPHONY_TIME: 74 return runSuggestTelephonyTime(); 75 case SHELL_COMMAND_SUGGEST_NETWORK_TIME: 76 return runSuggestNetworkTime(); 77 case SHELL_COMMAND_GET_NETWORK_TIME: 78 return runGetLatestNetworkTime(); 79 case SHELL_COMMAND_CLEAR_NETWORK_TIME: 80 return runClearLatestNetworkTime(); 81 case SHELL_COMMAND_SUGGEST_GNSS_TIME: 82 return runSuggestGnssTime(); 83 case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME: 84 return runSuggestExternalTime(); 85 case SHELL_COMMAND_GET_TIME_STATE: 86 return runGetTimeState(); 87 case SHELL_COMMAND_SET_TIME_STATE: 88 return runSetTimeState(); 89 case SHELL_COMMAND_CONFIRM_TIME: 90 return runConfirmTime(); 91 case SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME: 92 return runClearSystemClockNetworkTime(); 93 case SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME: 94 return runSetSystemClockNetworkTime(); 95 default: { 96 return handleDefaultCommands(cmd); 97 } 98 } 99 } 100 runIsAutoDetectionEnabled()101 private int runIsAutoDetectionEnabled() { 102 final PrintWriter pw = getOutPrintWriter(); 103 boolean enabled = mInterface.getCapabilitiesAndConfig() 104 .getConfiguration() 105 .isAutoDetectionEnabled(); 106 pw.println(enabled); 107 return 0; 108 } 109 runSetAutoDetectionEnabled()110 private int runSetAutoDetectionEnabled() { 111 boolean enabled = Boolean.parseBoolean(getNextArgRequired()); 112 int userId = UserHandle.USER_CURRENT; 113 TimeConfiguration configuration = new TimeConfiguration.Builder() 114 .setAutoDetectionEnabled(enabled) 115 .build(); 116 return mInterface.updateConfiguration(userId, configuration) ? 0 : 1; 117 } 118 runSuggestManualTime()119 private int runSuggestManualTime() { 120 return runSuggestTime( 121 () -> ManualTimeSuggestion.parseCommandLineArg(this), 122 mInterface::suggestManualTime); 123 } 124 runSuggestTelephonyTime()125 private int runSuggestTelephonyTime() { 126 return runSuggestTime( 127 () -> TelephonyTimeSuggestion.parseCommandLineArg(this), 128 mInterface::suggestTelephonyTime); 129 } 130 runSuggestNetworkTime()131 private int runSuggestNetworkTime() { 132 return runSuggestTime( 133 () -> NetworkTimeSuggestion.parseCommandLineArg(this), 134 mInterface::suggestNetworkTime); 135 } 136 runGetLatestNetworkTime()137 private int runGetLatestNetworkTime() { 138 NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion(); 139 final PrintWriter pw = getOutPrintWriter(); 140 pw.println(networkTimeSuggestion); 141 return 0; 142 } 143 runClearLatestNetworkTime()144 private int runClearLatestNetworkTime() { 145 mInterface.clearLatestNetworkTime(); 146 return 0; 147 } 148 runSuggestGnssTime()149 private int runSuggestGnssTime() { 150 return runSuggestTime( 151 () -> GnssTimeSuggestion.parseCommandLineArg(this), 152 mInterface::suggestGnssTime); 153 } 154 runSuggestExternalTime()155 private int runSuggestExternalTime() { 156 return runSuggestTime( 157 () -> ExternalTimeSuggestion.parseCommandLineArg(this), 158 mInterface::suggestExternalTime); 159 } 160 runSuggestTime(Supplier<T> suggestionParser, Consumer<T> invoker)161 private <T> int runSuggestTime(Supplier<T> suggestionParser, Consumer<T> invoker) { 162 final PrintWriter pw = getOutPrintWriter(); 163 try { 164 T suggestion = suggestionParser.get(); 165 if (suggestion == null) { 166 pw.println("Error: suggestion not specified"); 167 return 1; 168 } 169 invoker.accept(suggestion); 170 pw.println("Suggestion " + suggestion + " injected."); 171 return 0; 172 } catch (RuntimeException e) { 173 pw.println(e); 174 return 1; 175 } 176 } 177 runGetTimeState()178 private int runGetTimeState() { 179 TimeState timeState = mInterface.getTimeState(); 180 getOutPrintWriter().println(timeState); 181 return 0; 182 } 183 runSetTimeState()184 private int runSetTimeState() { 185 TimeState timeState = TimeState.parseCommandLineArgs(this); 186 mInterface.setTimeState(timeState); 187 return 0; 188 } 189 runConfirmTime()190 private int runConfirmTime() { 191 UnixEpochTime unixEpochTime = UnixEpochTime.parseCommandLineArgs(this); 192 getOutPrintWriter().println(mInterface.confirmTime(unixEpochTime)); 193 return 0; 194 } 195 runClearSystemClockNetworkTime()196 private int runClearSystemClockNetworkTime() { 197 mInterface.clearNetworkTimeForSystemClockForTests(); 198 return 0; 199 } 200 runSetSystemClockNetworkTime()201 private int runSetSystemClockNetworkTime() { 202 NetworkTimeSuggestion networkTimeSuggestion = 203 NetworkTimeSuggestion.parseCommandLineArg(this); 204 mInterface.setNetworkTimeForSystemClockForTests( 205 networkTimeSuggestion.getUnixEpochTime(), 206 networkTimeSuggestion.getUncertaintyMillis()); 207 return 0; 208 } 209 210 @Override onHelp()211 public void onHelp() { 212 final PrintWriter pw = getOutPrintWriter(); 213 pw.printf("Time Detector (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME); 214 pw.printf(" help\n"); 215 pw.printf(" Print this help text.\n"); 216 pw.printf(" %s\n", SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED); 217 pw.printf(" Prints true/false according to the automatic time detection setting.\n"); 218 pw.printf(" %s true|false\n", SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED); 219 pw.printf(" Sets the automatic time detection setting.\n"); 220 pw.println(); 221 pw.printf(" %s <manual suggestion opts>\n", SHELL_COMMAND_SUGGEST_MANUAL_TIME); 222 pw.printf(" Suggests a time as if via the \"manual\" origin.\n"); 223 pw.printf(" %s <telephony suggestion opts>\n", SHELL_COMMAND_SUGGEST_TELEPHONY_TIME); 224 pw.printf(" Suggests a time as if via the \"telephony\" origin.\n"); 225 pw.printf(" %s <network suggestion opts>\n", SHELL_COMMAND_SUGGEST_NETWORK_TIME); 226 pw.printf(" Suggests a time as if via the \"network\" origin.\n"); 227 pw.printf(" %s <gnss suggestion opts>\n", SHELL_COMMAND_SUGGEST_GNSS_TIME); 228 pw.printf(" Suggests a time as if via the \"gnss\" origin.\n"); 229 pw.printf(" %s <external suggestion opts>\n", SHELL_COMMAND_SUGGEST_EXTERNAL_TIME); 230 pw.printf(" Suggests a time as if via the \"external\" origin.\n"); 231 pw.printf(" %s\n", SHELL_COMMAND_GET_TIME_STATE); 232 pw.printf(" Returns the current time setting state.\n"); 233 pw.printf(" %s <time state options>\n", SHELL_COMMAND_SET_TIME_STATE); 234 pw.printf(" Sets the current time state for tests.\n"); 235 pw.printf(" %s <unix epoch time options>\n", SHELL_COMMAND_CONFIRM_TIME); 236 pw.printf(" Tries to confirms the time, raising the confidence.\n"); 237 pw.printf(" %s\n", SHELL_COMMAND_GET_NETWORK_TIME); 238 pw.printf(" Prints the network time information held by the detector.\n"); 239 pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME); 240 pw.printf(" Clears the network time information held by the detector.\n"); 241 // TODO(b/222295093) Remove these "system_clock" commands when 242 // SystemClock.currentNetworkTimeClock() is guaranteed to use the latest network 243 // suggestion. Then, commands above can be used instead. 244 pw.printf(" %s <network suggestion opts>\n", 245 SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME); 246 pw.printf(" Sets the network time information used for" 247 + " SystemClock.currentNetworkTimeClock().\n"); 248 pw.printf(" %s\n", SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME); 249 pw.printf(" Clears the network time information used for" 250 + " SystemClock.currentNetworkTimeClock().\n"); 251 pw.println(); 252 ManualTimeSuggestion.printCommandLineOpts(pw); 253 pw.println(); 254 TelephonyTimeSuggestion.printCommandLineOpts(pw); 255 pw.println(); 256 NetworkTimeSuggestion.printCommandLineOpts(pw); 257 pw.println(); 258 GnssTimeSuggestion.printCommandLineOpts(pw); 259 pw.println(); 260 ExternalTimeSuggestion.printCommandLineOpts(pw); 261 pw.println(); 262 TimeState.printCommandLineOpts(pw); 263 pw.println(); 264 UnixEpochTime.printCommandLineOpts(pw); 265 pw.println(); 266 pw.printf("This service is also affected by the following device_config flags in the" 267 + " %s namespace:\n", NAMESPACE_SYSTEM_TIME); 268 pw.printf(" %s\n", KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE); 269 pw.printf(" The lower bound used to validate time suggestions when they are received." 270 + "\n"); 271 pw.printf(" Specified in milliseconds since the start of the Unix epoch.\n"); 272 pw.printf(" %s\n", KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE); 273 pw.printf(" A comma separated list of origins. See TimeDetectorStrategy for details.\n"); 274 pw.println(); 275 pw.printf("See \"adb shell cmd device_config\" for more information on setting flags.\n"); 276 pw.println(); 277 } 278 } 279