1 /* 2 * Copyright (C) 2020 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.app.time; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.StringDef; 22 import android.annotation.SystemApi; 23 import android.os.Bundle; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 import java.util.Objects; 30 31 /** 32 * User visible settings that control the behavior of the time zone detector / manual time zone 33 * entry. 34 * 35 * <p>When reading the configuration, values for all settings will be provided. In some cases, such 36 * as when the device behavior relies on optional hardware / OEM configuration, or the value of 37 * several settings, the device behavior may not be directly affected by the setting value. 38 * 39 * <p>Settings can be left absent when updating configuration via {@link 40 * TimeManager#updateTimeZoneConfiguration(TimeZoneConfiguration)} and those settings will not be 41 * changed. Not all configuration settings can be modified by all users: see {@link 42 * TimeManager#getTimeZoneCapabilitiesAndConfig()} and {@link TimeZoneCapabilities} for details. 43 * 44 * @hide 45 */ 46 @SystemApi 47 public final class TimeZoneConfiguration implements Parcelable { 48 49 public static final @NonNull Creator<TimeZoneConfiguration> CREATOR = 50 new Creator<TimeZoneConfiguration>() { 51 public TimeZoneConfiguration createFromParcel(Parcel in) { 52 return TimeZoneConfiguration.createFromParcel(in); 53 } 54 55 public TimeZoneConfiguration[] newArray(int size) { 56 return new TimeZoneConfiguration[size]; 57 } 58 }; 59 60 /** 61 * All configuration properties 62 * 63 * @hide 64 */ 65 @StringDef({ SETTING_AUTO_DETECTION_ENABLED, SETTING_GEO_DETECTION_ENABLED }) 66 @Retention(RetentionPolicy.SOURCE) 67 @interface Setting {} 68 69 /** See {@link TimeZoneConfiguration#isAutoDetectionEnabled()} for details. */ 70 @Setting 71 private static final String SETTING_AUTO_DETECTION_ENABLED = "autoDetectionEnabled"; 72 73 /** See {@link TimeZoneConfiguration#isGeoDetectionEnabled()} for details. */ 74 @Setting 75 private static final String SETTING_GEO_DETECTION_ENABLED = "geoDetectionEnabled"; 76 77 @NonNull private final Bundle mBundle; 78 TimeZoneConfiguration(Builder builder)79 private TimeZoneConfiguration(Builder builder) { 80 this.mBundle = Objects.requireNonNull(builder.mBundle); 81 } 82 createFromParcel(Parcel in)83 private static TimeZoneConfiguration createFromParcel(Parcel in) { 84 return new TimeZoneConfiguration.Builder() 85 .setPropertyBundleInternal(in.readBundle()) 86 .build(); 87 } 88 89 @Override writeToParcel(@onNull Parcel dest, int flags)90 public void writeToParcel(@NonNull Parcel dest, int flags) { 91 dest.writeBundle(mBundle); 92 } 93 94 /** 95 * Returns {@code true} if all known settings are present. 96 * 97 * @hide 98 */ isComplete()99 public boolean isComplete() { 100 return hasIsAutoDetectionEnabled() 101 && hasIsGeoDetectionEnabled(); 102 } 103 104 /** 105 * Returns the value of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. This 106 * controls whether a device will attempt to determine the time zone automatically using 107 * contextual information if the device supports auto detection. 108 * 109 * <p>See {@link TimeZoneCapabilities#getConfigureAutoDetectionEnabledCapability()} for how to 110 * tell if the setting is meaningful for the current user at this time. 111 * 112 * @throws IllegalStateException if the setting is not present 113 */ isAutoDetectionEnabled()114 public boolean isAutoDetectionEnabled() { 115 enforceSettingPresent(SETTING_AUTO_DETECTION_ENABLED); 116 return mBundle.getBoolean(SETTING_AUTO_DETECTION_ENABLED); 117 } 118 119 /** 120 * Returns {@code true} if the {@link #isAutoDetectionEnabled()} setting is present. 121 * 122 * @hide 123 */ hasIsAutoDetectionEnabled()124 public boolean hasIsAutoDetectionEnabled() { 125 return mBundle.containsKey(SETTING_AUTO_DETECTION_ENABLED); 126 } 127 128 /** 129 * Returns the value of the {@link #SETTING_GEO_DETECTION_ENABLED} setting. This 130 * controls whether the device can use geolocation to determine time zone. This value may only 131 * be used by Android under some circumstances. For example, it is not used when 132 * {@link #isGeoDetectionEnabled()} is {@code false}. 133 * 134 * <p>See {@link TimeZoneCapabilities#getConfigureGeoDetectionEnabledCapability()} for how to 135 * tell if the setting is meaningful for the current user at this time. 136 * 137 * @throws IllegalStateException if the setting is not present 138 */ isGeoDetectionEnabled()139 public boolean isGeoDetectionEnabled() { 140 enforceSettingPresent(SETTING_GEO_DETECTION_ENABLED); 141 return mBundle.getBoolean(SETTING_GEO_DETECTION_ENABLED); 142 } 143 144 /** 145 * Returns {@code true} if the {@link #isGeoDetectionEnabled()} setting is present. 146 * 147 * @hide 148 */ hasIsGeoDetectionEnabled()149 public boolean hasIsGeoDetectionEnabled() { 150 return mBundle.containsKey(SETTING_GEO_DETECTION_ENABLED); 151 } 152 153 @Override describeContents()154 public int describeContents() { 155 return 0; 156 } 157 158 @Override equals(@ullable Object o)159 public boolean equals(@Nullable Object o) { 160 if (this == o) { 161 return true; 162 } 163 if (o == null || getClass() != o.getClass()) { 164 return false; 165 } 166 TimeZoneConfiguration that = (TimeZoneConfiguration) o; 167 return mBundle.kindofEquals(that.mBundle); 168 } 169 170 @Override hashCode()171 public int hashCode() { 172 return Objects.hash(mBundle); 173 } 174 175 @Override toString()176 public String toString() { 177 return "TimeZoneConfiguration{" 178 + "mBundle=" + mBundle 179 + '}'; 180 } 181 enforceSettingPresent(@etting String setting)182 private void enforceSettingPresent(@Setting String setting) { 183 if (!mBundle.containsKey(setting)) { 184 throw new IllegalStateException(setting + " is not set"); 185 } 186 } 187 188 /** 189 * A builder for {@link TimeZoneConfiguration} objects. 190 * 191 * @hide 192 */ 193 @SystemApi 194 public static final class Builder { 195 196 private final Bundle mBundle = new Bundle(); 197 198 /** 199 * Creates a new Builder with no settings held. 200 */ Builder()201 public Builder() { 202 } 203 204 /** 205 * Creates a new Builder by copying the settings from an existing instance. 206 */ Builder(@onNull TimeZoneConfiguration toCopy)207 public Builder(@NonNull TimeZoneConfiguration toCopy) { 208 mergeProperties(toCopy); 209 } 210 211 /** 212 * Merges {@code other} settings into this instances, replacing existing values in this 213 * where the settings appear in both. 214 * 215 * @hide 216 */ 217 @NonNull mergeProperties(@onNull TimeZoneConfiguration other)218 public Builder mergeProperties(@NonNull TimeZoneConfiguration other) { 219 this.mBundle.putAll(other.mBundle); 220 return this; 221 } 222 223 @NonNull setPropertyBundleInternal(@onNull Bundle bundle)224 Builder setPropertyBundleInternal(@NonNull Bundle bundle) { 225 this.mBundle.putAll(bundle); 226 return this; 227 } 228 229 /** 230 * Sets the state of the {@link #SETTING_AUTO_DETECTION_ENABLED} setting. 231 */ 232 @NonNull setAutoDetectionEnabled(boolean enabled)233 public Builder setAutoDetectionEnabled(boolean enabled) { 234 this.mBundle.putBoolean(SETTING_AUTO_DETECTION_ENABLED, enabled); 235 return this; 236 } 237 238 /** 239 * Sets the state of the {@link #SETTING_GEO_DETECTION_ENABLED} setting. 240 */ 241 @NonNull setGeoDetectionEnabled(boolean enabled)242 public Builder setGeoDetectionEnabled(boolean enabled) { 243 this.mBundle.putBoolean(SETTING_GEO_DETECTION_ENABLED, enabled); 244 return this; 245 } 246 247 /** Returns the {@link TimeZoneConfiguration}. */ 248 @NonNull build()249 public TimeZoneConfiguration build() { 250 return new TimeZoneConfiguration(this); 251 } 252 } 253 } 254 255