blob: d35967df3416b120ac19aa0836a79017eed441cc [file] [log] [blame]
Neil Fullerbede17c2017-03-16 18:29:36 +00001/*
2 * Copyright (C) 2017 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
17package android.app.timezone;
18
19import static android.app.timezone.Utils.validateConditionalNull;
20import static android.app.timezone.Utils.validateNotNull;
21import static android.app.timezone.Utils.validateRulesVersion;
22
23import android.annotation.IntDef;
24import android.annotation.Nullable;
25import android.os.Parcel;
26import android.os.Parcelable;
27
28import java.lang.annotation.Retention;
29import java.lang.annotation.RetentionPolicy;
30
31/**
32 * Description of the state of time zone rules on a device.
33 *
34 * <p>The following properties are included:
35 * <dl>
Neil Fullera1ae0252019-02-18 10:49:15 +000036 * <dt>baseRulesVersion</dt>
Neil Fullerbede17c2017-03-16 18:29:36 +000037 * <dd>the IANA rules version that shipped with the OS. Always present. e.g. "2017a".</dd>
38 * <dt>distroFormatVersionSupported</dt>
39 * <dd>the distro format version supported by this device. Always present.</dd>
40 * <dt>operationInProgress</dt>
41 * <dd>{@code true} if there is an install / uninstall operation currently happening.</dd>
42 * <dt>stagedOperationType</dt>
43 * <dd>one of {@link #STAGED_OPERATION_UNKNOWN}, {@link #STAGED_OPERATION_NONE},
44 * {@link #STAGED_OPERATION_UNINSTALL} and {@link #STAGED_OPERATION_INSTALL} indicating whether
45 * there is a currently staged time zone distro operation. {@link #STAGED_OPERATION_UNKNOWN} is
46 * used when {@link #isOperationInProgress()} is {@code true}. Staged operations currently
47 * require a reboot to become active.</dd>
48 * <dt>stagedDistroRulesVersion</dt>
49 * <dd>[present if distroStagedState == STAGED_STATE_INSTALL], the rules version of the distro
50 * currently staged for installation.</dd>
51 * <dt>distroStatus</dt>
52 * <dd>{@link #DISTRO_STATUS_INSTALLED} if there is a time zone distro installed and active,
53 * {@link #DISTRO_STATUS_NONE} if there is no active installed distro.
54 * {@link #DISTRO_STATUS_UNKNOWN} is used when {@link #isOperationInProgress()} is {@code true}.
55 * </dd>
56 * <dt>installedDistroRulesVersion</dt>
57 * <dd>[present if distroStatus == {@link #DISTRO_STATUS_INSTALLED}], the rules version of the
58 * installed and active distro.</dd>
59 * </dl>
60 *
61 * @hide
62 */
Neil Fullerbede17c2017-03-16 18:29:36 +000063public final class RulesState implements Parcelable {
64
65 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -070066 @IntDef(prefix = { "STAGED_OPERATION_" }, value = {
Neil Fullerbede17c2017-03-16 18:29:36 +000067 STAGED_OPERATION_UNKNOWN,
68 STAGED_OPERATION_NONE,
69 STAGED_OPERATION_UNINSTALL,
Jeff Sharkeyce8db992017-12-13 20:05:05 -070070 STAGED_OPERATION_INSTALL
71 })
Neil Fullerbede17c2017-03-16 18:29:36 +000072 private @interface StagedOperationType {}
73
74 /** Staged state could not be determined. */
75 public static final int STAGED_OPERATION_UNKNOWN = 0;
76 /** Nothing is staged. */
77 public static final int STAGED_OPERATION_NONE = 1;
78 /** An uninstall is staged. */
79 public static final int STAGED_OPERATION_UNINSTALL = 2;
80 /** An install is staged. */
81 public static final int STAGED_OPERATION_INSTALL = 3;
82
83 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -070084 @IntDef(prefix = { "DISTRO_STATUS_" }, value = {
Neil Fullerbede17c2017-03-16 18:29:36 +000085 DISTRO_STATUS_UNKNOWN,
86 DISTRO_STATUS_NONE,
Jeff Sharkeyce8db992017-12-13 20:05:05 -070087 DISTRO_STATUS_INSTALLED
88 })
Neil Fullerbede17c2017-03-16 18:29:36 +000089 private @interface DistroStatus {}
90
91 /** The current distro status could not be determined. */
92 public static final int DISTRO_STATUS_UNKNOWN = 0;
93 /** There is no active installed time zone distro. */
94 public static final int DISTRO_STATUS_NONE = 1;
95 /** The is an active, installed time zone distro. */
96 public static final int DISTRO_STATUS_INSTALLED = 2;
97
98 private static final byte BYTE_FALSE = 0;
99 private static final byte BYTE_TRUE = 1;
100
Neil Fullera1ae0252019-02-18 10:49:15 +0000101 private final String mBaseRulesVersion;
Neil Fullerbede17c2017-03-16 18:29:36 +0000102 private final DistroFormatVersion mDistroFormatVersionSupported;
103 private final boolean mOperationInProgress;
104 @StagedOperationType private final int mStagedOperationType;
105 @Nullable private final DistroRulesVersion mStagedDistroRulesVersion;
106 @DistroStatus private final int mDistroStatus;
107 @Nullable private final DistroRulesVersion mInstalledDistroRulesVersion;
108
Neil Fullera1ae0252019-02-18 10:49:15 +0000109 public RulesState(String baseRulesVersion, DistroFormatVersion distroFormatVersionSupported,
Neil Fullerbede17c2017-03-16 18:29:36 +0000110 boolean operationInProgress,
111 @StagedOperationType int stagedOperationType,
112 @Nullable DistroRulesVersion stagedDistroRulesVersion,
113 @DistroStatus int distroStatus,
114 @Nullable DistroRulesVersion installedDistroRulesVersion) {
Neil Fullera1ae0252019-02-18 10:49:15 +0000115 this.mBaseRulesVersion = validateRulesVersion("baseRulesVersion", baseRulesVersion);
Neil Fullerbede17c2017-03-16 18:29:36 +0000116 this.mDistroFormatVersionSupported =
117 validateNotNull("distroFormatVersionSupported", distroFormatVersionSupported);
118 this.mOperationInProgress = operationInProgress;
119
120 if (operationInProgress && stagedOperationType != STAGED_OPERATION_UNKNOWN) {
121 throw new IllegalArgumentException(
122 "stagedOperationType != STAGED_OPERATION_UNKNOWN");
123 }
124 this.mStagedOperationType = validateStagedOperation(stagedOperationType);
125 this.mStagedDistroRulesVersion = validateConditionalNull(
126 mStagedOperationType == STAGED_OPERATION_INSTALL /* requireNotNull */,
127 "stagedDistroRulesVersion", stagedDistroRulesVersion);
128
Neil Fullerbede17c2017-03-16 18:29:36 +0000129 this.mDistroStatus = validateDistroStatus(distroStatus);
130 this.mInstalledDistroRulesVersion = validateConditionalNull(
131 mDistroStatus == DISTRO_STATUS_INSTALLED/* requireNotNull */,
132 "installedDistroRulesVersion", installedDistroRulesVersion);
133 }
134
Neil Fullera1ae0252019-02-18 10:49:15 +0000135 public String getBaseRulesVersion() {
136 return mBaseRulesVersion;
Neil Fullerbede17c2017-03-16 18:29:36 +0000137 }
138
139 public boolean isOperationInProgress() {
140 return mOperationInProgress;
141 }
142
143 public @StagedOperationType int getStagedOperationType() {
144 return mStagedOperationType;
145 }
146
147 /**
148 * Returns the staged rules version when {@link #getStagedOperationType()} is
149 * {@link #STAGED_OPERATION_INSTALL}.
150 */
151 public @Nullable DistroRulesVersion getStagedDistroRulesVersion() {
152 return mStagedDistroRulesVersion;
153 }
154
155 public @DistroStatus int getDistroStatus() {
156 return mDistroStatus;
157 }
158
159 /**
160 * Returns the installed rules version when {@link #getDistroStatus()} is
161 * {@link #DISTRO_STATUS_INSTALLED}.
162 */
163 public @Nullable DistroRulesVersion getInstalledDistroRulesVersion() {
164 return mInstalledDistroRulesVersion;
165 }
166
167 /**
168 * Returns true if a distro in the specified format is supported on this device.
169 */
170 public boolean isDistroFormatVersionSupported(DistroFormatVersion distroFormatVersion) {
171 return mDistroFormatVersionSupported.supports(distroFormatVersion);
172 }
173
174 /**
Neil Fullera1ae0252019-02-18 10:49:15 +0000175 * Returns true if the base data files contain IANA rules data that are newer than the
Neil Fuller01534812017-06-22 17:58:02 +0100176 * distro IANA rules version supplied, i.e. true when the version specified would be "worse"
Neil Fullera1ae0252019-02-18 10:49:15 +0000177 * than the one that is in the base data. Returns false if the base version is the
Neil Fuller01534812017-06-22 17:58:02 +0100178 * same or older, i.e. false when the version specified would be "better" than the one that is
Neil Fullera1ae0252019-02-18 10:49:15 +0000179 * in the base set.
Neil Fullerbede17c2017-03-16 18:29:36 +0000180 */
Neil Fullera1ae0252019-02-18 10:49:15 +0000181 public boolean isBaseVersionNewerThan(DistroRulesVersion distroRulesVersion) {
182 return mBaseRulesVersion.compareTo(distroRulesVersion.getRulesVersion()) > 0;
Neil Fullerbede17c2017-03-16 18:29:36 +0000183 }
184
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700185 public static final @android.annotation.NonNull Parcelable.Creator<RulesState> CREATOR =
Neil Fullerbede17c2017-03-16 18:29:36 +0000186 new Parcelable.Creator<RulesState>() {
187 public RulesState createFromParcel(Parcel in) {
188 return RulesState.createFromParcel(in);
189 }
190
191 public RulesState[] newArray(int size) {
192 return new RulesState[size];
193 }
194 };
195
196 private static RulesState createFromParcel(Parcel in) {
Neil Fullera1ae0252019-02-18 10:49:15 +0000197 String baseRulesVersion = in.readString();
Neil Fullerbede17c2017-03-16 18:29:36 +0000198 DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null);
199 boolean operationInProgress = in.readByte() == BYTE_TRUE;
200 int distroStagedState = in.readByte();
201 DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null);
202 int installedDistroStatus = in.readByte();
203 DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null);
Neil Fullera1ae0252019-02-18 10:49:15 +0000204 return new RulesState(baseRulesVersion, distroFormatVersionSupported, operationInProgress,
Neil Fullerbede17c2017-03-16 18:29:36 +0000205 distroStagedState, stagedDistroRulesVersion,
206 installedDistroStatus, installedDistroRulesVersion);
207 }
208
209 @Override
210 public int describeContents() {
211 return 0;
212 }
213
214 @Override
215 public void writeToParcel(Parcel out, int flags) {
Neil Fullera1ae0252019-02-18 10:49:15 +0000216 out.writeString(mBaseRulesVersion);
Neil Fullerbede17c2017-03-16 18:29:36 +0000217 out.writeParcelable(mDistroFormatVersionSupported, 0);
218 out.writeByte(mOperationInProgress ? BYTE_TRUE : BYTE_FALSE);
219 out.writeByte((byte) mStagedOperationType);
220 out.writeParcelable(mStagedDistroRulesVersion, 0);
221 out.writeByte((byte) mDistroStatus);
222 out.writeParcelable(mInstalledDistroRulesVersion, 0);
223 }
224
225 @Override
226 public boolean equals(Object o) {
227 if (this == o) {
228 return true;
229 }
230 if (o == null || getClass() != o.getClass()) {
231 return false;
232 }
233
234 RulesState that = (RulesState) o;
235
236 if (mOperationInProgress != that.mOperationInProgress) {
237 return false;
238 }
239 if (mStagedOperationType != that.mStagedOperationType) {
240 return false;
241 }
242 if (mDistroStatus != that.mDistroStatus) {
243 return false;
244 }
Neil Fullera1ae0252019-02-18 10:49:15 +0000245 if (!mBaseRulesVersion.equals(that.mBaseRulesVersion)) {
Neil Fullerbede17c2017-03-16 18:29:36 +0000246 return false;
247 }
248 if (!mDistroFormatVersionSupported.equals(that.mDistroFormatVersionSupported)) {
249 return false;
250 }
251 if (mStagedDistroRulesVersion != null ? !mStagedDistroRulesVersion
252 .equals(that.mStagedDistroRulesVersion) : that.mStagedDistroRulesVersion != null) {
253 return false;
254 }
255 return mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
256 .equals(that.mInstalledDistroRulesVersion)
257 : that.mInstalledDistroRulesVersion == null;
258 }
259
260 @Override
261 public int hashCode() {
Neil Fullera1ae0252019-02-18 10:49:15 +0000262 int result = mBaseRulesVersion.hashCode();
Neil Fullerbede17c2017-03-16 18:29:36 +0000263 result = 31 * result + mDistroFormatVersionSupported.hashCode();
264 result = 31 * result + (mOperationInProgress ? 1 : 0);
265 result = 31 * result + mStagedOperationType;
266 result = 31 * result + (mStagedDistroRulesVersion != null ? mStagedDistroRulesVersion
267 .hashCode()
268 : 0);
269 result = 31 * result + mDistroStatus;
270 result = 31 * result + (mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
271 .hashCode() : 0);
272 return result;
273 }
274
275 @Override
276 public String toString() {
277 return "RulesState{"
Neil Fullera1ae0252019-02-18 10:49:15 +0000278 + "mBaseRulesVersion='" + mBaseRulesVersion + '\''
Neil Fullerbede17c2017-03-16 18:29:36 +0000279 + ", mDistroFormatVersionSupported=" + mDistroFormatVersionSupported
280 + ", mOperationInProgress=" + mOperationInProgress
281 + ", mStagedOperationType=" + mStagedOperationType
282 + ", mStagedDistroRulesVersion=" + mStagedDistroRulesVersion
283 + ", mDistroStatus=" + mDistroStatus
284 + ", mInstalledDistroRulesVersion=" + mInstalledDistroRulesVersion
285 + '}';
286 }
287
288 private static int validateStagedOperation(int stagedOperationType) {
289 if (stagedOperationType < STAGED_OPERATION_UNKNOWN
290 || stagedOperationType > STAGED_OPERATION_INSTALL) {
291 throw new IllegalArgumentException("Unknown operation type=" + stagedOperationType);
292 }
293 return stagedOperationType;
294 }
295
296 private static int validateDistroStatus(int distroStatus) {
297 if (distroStatus < DISTRO_STATUS_UNKNOWN || distroStatus > DISTRO_STATUS_INSTALLED) {
298 throw new IllegalArgumentException("Unknown distro status=" + distroStatus);
299 }
300 return distroStatus;
301 }
302}