1 /* 2 * Copyright (C) 2018 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 com.android.server.timedetector; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.UserIdInt; 23 import android.app.time.ExternalTimeSuggestion; 24 import android.app.time.TimeCapabilitiesAndConfig; 25 import android.app.time.TimeConfiguration; 26 import android.app.time.TimeState; 27 import android.app.time.UnixEpochTime; 28 import android.app.timedetector.ManualTimeSuggestion; 29 import android.app.timedetector.TelephonyTimeSuggestion; 30 import android.util.IndentingPrintWriter; 31 32 import com.android.internal.util.Preconditions; 33 import com.android.server.timezonedetector.Dumpable; 34 import com.android.server.timezonedetector.StateChangeListener; 35 36 import java.lang.annotation.ElementType; 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.lang.annotation.Target; 40 41 /** 42 * The interface for the class that implements the time detection algorithm used by the 43 * {@link TimeDetectorService}. 44 * 45 * <p>Most calls will be handled by a single thread but that is not true for all calls. For example 46 * {@link #dump(IndentingPrintWriter, String[])}) may be called on a different thread so 47 * implementations must handle thread safety. 48 * 49 * @hide 50 */ 51 public interface TimeDetectorStrategy extends Dumpable { 52 53 @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK, ORIGIN_GNSS, ORIGIN_EXTERNAL }) 54 @Retention(RetentionPolicy.SOURCE) 55 @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER }) 56 @interface Origin {} 57 58 /** Used when a time value originated from a telephony signal. */ 59 @Origin int ORIGIN_TELEPHONY = 1; 60 61 /** Used when a time value originated from a user / manual settings. */ 62 @Origin int ORIGIN_MANUAL = 2; 63 64 /** Used when a time value originated from a network signal. */ 65 @Origin int ORIGIN_NETWORK = 3; 66 67 /** Used when a time value originated from a gnss signal. */ 68 @Origin int ORIGIN_GNSS = 4; 69 70 /** Used when a time value originated from an externally specified signal. */ 71 @Origin int ORIGIN_EXTERNAL = 5; 72 73 /** Returns a snapshot of the system clock's state. See {@link TimeState} for details. */ 74 @NonNull getTimeState()75 TimeState getTimeState(); 76 77 /** 78 * Sets the system time state. See {@link TimeState} for details. Intended for use during 79 * testing to force the device's state, this bypasses the time detection logic. 80 */ setTimeState(@onNull TimeState timeState)81 void setTimeState(@NonNull TimeState timeState); 82 83 /** 84 * Signals that a user has confirmed the supplied time. If the {@code confirmationTime}, 85 * adjusted for elapsed time since it was created (expected to be with {@link 86 * #getTimeState()}), is very close to the clock's current state, then this can be used to 87 * raise the system's confidence in that time. Returns {@code true} if confirmation was 88 * successful (i.e. the time matched), {@code false} otherwise. 89 */ confirmTime(@onNull UnixEpochTime confirmationTime)90 boolean confirmTime(@NonNull UnixEpochTime confirmationTime); 91 92 /** 93 * Adds a listener that will be triggered when something changes that could affect the result 94 * of the {@link #getCapabilitiesAndConfig} call for the <em>current user only</em>. This 95 * includes the current user changing. This is exposed so that (indirect) users like SettingsUI 96 * can monitor for changes to data derived from {@link TimeCapabilitiesAndConfig} and update 97 * the UI accordingly. 98 */ addChangeListener(@onNull StateChangeListener listener)99 void addChangeListener(@NonNull StateChangeListener listener); 100 101 /** 102 * Returns a {@link TimeCapabilitiesAndConfig} object for the specified user. 103 * 104 * <p>The strategy is dependent on device state like current user, settings and device config. 105 * These updates are usually handled asynchronously, so callers should expect some delay between 106 * a change being made directly to services like settings and the strategy becoming aware of 107 * them. Changes made via {@link #updateConfiguration} will be visible immediately. 108 * 109 * @param userId the user ID to retrieve the information for 110 * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device 111 * policy restrictions that should apply to actual users can be ignored 112 */ getCapabilitiesAndConfig( @serIdInt int userId, boolean bypassUserPolicyChecks)113 TimeCapabilitiesAndConfig getCapabilitiesAndConfig( 114 @UserIdInt int userId, boolean bypassUserPolicyChecks); 115 116 /** 117 * Updates the configuration properties that control a device's time behavior. 118 * 119 * <p>This method returns {@code true} if the configuration was changed, {@code false} 120 * otherwise. 121 * 122 * <p>See {@link #getCapabilitiesAndConfig} for guarantees about visibility of updates to 123 * subsequent calls. 124 * 125 * @param userId the current user ID, supplied to make sure that the asynchronous process 126 * that happens when users switch is completed when the call is made 127 * @param configuration the configuration changes 128 * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device 129 * policy restrictions that should apply to actual users can be ignored 130 */ updateConfiguration(@serIdInt int userId, @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks)131 boolean updateConfiguration(@UserIdInt int userId, 132 @NonNull TimeConfiguration configuration, boolean bypassUserPolicyChecks); 133 134 /** Processes the suggested time from telephony sources. */ suggestTelephonyTime(@onNull TelephonyTimeSuggestion suggestion)135 void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion suggestion); 136 137 /** 138 * Processes the suggested manually entered time. Returns {@code false} if the suggestion was 139 * invalid, or the device configuration prevented the suggestion being used, {@code true} if the 140 * suggestion was accepted. A suggestion that is valid but does not change the time because it 141 * matches the current device time is considered accepted. 142 * 143 * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device 144 * policy restrictions that should apply to actual users can be ignored 145 */ suggestManualTime(@serIdInt int userId, @NonNull ManualTimeSuggestion suggestion, boolean bypassUserPolicyChecks)146 boolean suggestManualTime(@UserIdInt int userId, @NonNull ManualTimeSuggestion suggestion, 147 boolean bypassUserPolicyChecks); 148 149 /** 150 * Processes the suggested network time. The suggestion may not be used to set the device's time 151 * depending on device configuration and user settings, but can replace previous network 152 * suggestions received. See also 153 * {@link #addNetworkTimeUpdateListener(StateChangeListener)} and 154 * {@link #getLatestNetworkSuggestion()}. 155 */ suggestNetworkTime(@onNull NetworkTimeSuggestion suggestion)156 void suggestNetworkTime(@NonNull NetworkTimeSuggestion suggestion); 157 158 /** 159 * Adds a listener that will be notified when a new network time is available. See {@link 160 * #getLatestNetworkSuggestion()}. 161 */ addNetworkTimeUpdateListener(@onNull StateChangeListener networkSuggestionUpdateListener)162 void addNetworkTimeUpdateListener(@NonNull StateChangeListener networkSuggestionUpdateListener); 163 164 /** 165 * Returns the latest (accepted) network time suggestion. Returns {@code null} if there isn't 166 * one. 167 */ 168 @Nullable getLatestNetworkSuggestion()169 NetworkTimeSuggestion getLatestNetworkSuggestion(); 170 171 /** 172 * Clears the latest network time suggestion, leaving none. The remaining time signals from 173 * other sources will be reassessed causing the device's time to be updated if config and 174 * settings allow. 175 */ clearLatestNetworkSuggestion()176 void clearLatestNetworkSuggestion(); 177 178 /** Processes the suggested time from gnss sources. */ suggestGnssTime(@onNull GnssTimeSuggestion suggestion)179 void suggestGnssTime(@NonNull GnssTimeSuggestion suggestion); 180 181 /** Processes the suggested time from external sources. */ suggestExternalTime(@onNull ExternalTimeSuggestion suggestion)182 void suggestExternalTime(@NonNull ExternalTimeSuggestion suggestion); 183 184 // Utility methods below are to be moved to a better home when one becomes more obvious. 185 186 /** 187 * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config 188 * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized. 189 */ 190 @NonNull originToString(@rigin int origin)191 static String originToString(@Origin int origin) { 192 switch (origin) { 193 case ORIGIN_MANUAL: 194 return "manual"; 195 case ORIGIN_NETWORK: 196 return "network"; 197 case ORIGIN_TELEPHONY: 198 return "telephony"; 199 case ORIGIN_GNSS: 200 return "gnss"; 201 case ORIGIN_EXTERNAL: 202 return "external"; 203 default: 204 throw new IllegalArgumentException("origin=" + origin); 205 } 206 } 207 208 /** 209 * Converts a human readable config string to one of the {@code ORIGIN_} constants. 210 * Throws an {@link IllegalArgumentException} if the value is unrecognized or {@code null}. 211 */ stringToOrigin(String originString)212 static @Origin int stringToOrigin(String originString) { 213 Preconditions.checkArgument(originString != null); 214 215 switch (originString) { 216 case "manual": 217 return ORIGIN_MANUAL; 218 case "network": 219 return ORIGIN_NETWORK; 220 case "telephony": 221 return ORIGIN_TELEPHONY; 222 case "gnss": 223 return ORIGIN_GNSS; 224 case "external": 225 return ORIGIN_EXTERNAL; 226 default: 227 throw new IllegalArgumentException("originString=" + originString); 228 } 229 } 230 } 231