blob: b72eb040ea9279f5c9a22f524f26982e72e3428b [file] [log] [blame]
Dianne Hackborn231cc602009-04-27 17:10:36 -07001/*
2 * Copyright (C) 2009 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.content;
18
Artur Satayeve23a0eb2019-12-10 17:47:52 +000019import android.compat.annotation.UnsupportedAppUsage;
Dianne Hackborn231cc602009-04-27 17:10:36 -070020import android.os.Parcel;
21import android.os.Parcelable;
22import android.util.Log;
Varun Shah816cf632019-10-30 17:40:15 -070023import android.util.Pair;
24
25import com.android.internal.util.ArrayUtils;
Dianne Hackborn231cc602009-04-27 17:10:36 -070026
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080027import java.util.ArrayList;
Makoto Onuki94986212018-04-11 16:24:46 -070028import java.util.Calendar;
29import java.util.GregorianCalendar;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080030
Dianne Hackborn231cc602009-04-27 17:10:36 -070031/** @hide */
32public class SyncStatusInfo implements Parcelable {
Makoto Onuki15e7a252017-06-08 17:12:05 -070033 private static final String TAG = "Sync";
34
Makoto Onukif74cf942018-04-16 17:04:58 -070035 static final int VERSION = 6;
Makoto Onuki15e7a252017-06-08 17:12:05 -070036
37 private static final int MAX_EVENT_COUNT = 10;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080038
Makoto Onukif74cf942018-04-16 17:04:58 -070039 /**
40 * Number of sync sources. KEEP THIS AND SyncStorageEngine.SOURCES IN SYNC.
41 */
42 private static final int SOURCE_COUNT = 6;
43
Mathew Inwood5c0d3542018-08-14 13:54:31 +010044 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -070045 public final int authorityId;
Makoto Onuki94986212018-04-11 16:24:46 -070046
47 /**
48 * # of syncs for each sync source, etc.
49 */
50 public static class Stats {
51 public long totalElapsedTime;
52 public int numSyncs;
53 public int numSourcePoll;
54 public int numSourceOther;
55 public int numSourceLocal;
56 public int numSourceUser;
57 public int numSourcePeriodic;
58 public int numSourceFeed;
59 public int numFailures;
60 public int numCancels;
61
62 /** Copy all the stats to another instance. */
63 public void copyTo(Stats to) {
64 to.totalElapsedTime = totalElapsedTime;
65 to.numSyncs = numSyncs;
66 to.numSourcePoll = numSourcePoll;
67 to.numSourceOther = numSourceOther;
68 to.numSourceLocal = numSourceLocal;
69 to.numSourceUser = numSourceUser;
70 to.numSourcePeriodic = numSourcePeriodic;
71 to.numSourceFeed = numSourceFeed;
72 to.numFailures = numFailures;
73 to.numCancels = numCancels;
74 }
75
76 /** Clear all the stats. */
77 public void clear() {
78 totalElapsedTime = 0;
79 numSyncs = 0;
80 numSourcePoll = 0;
81 numSourceOther = 0;
82 numSourceLocal = 0;
83 numSourceUser = 0;
84 numSourcePeriodic = 0;
85 numSourceFeed = 0;
86 numFailures = 0;
87 numCancels = 0;
88 }
89
90 /** Write all the stats to a parcel. */
91 public void writeToParcel(Parcel parcel) {
92 parcel.writeLong(totalElapsedTime);
93 parcel.writeInt(numSyncs);
94 parcel.writeInt(numSourcePoll);
95 parcel.writeInt(numSourceOther);
96 parcel.writeInt(numSourceLocal);
97 parcel.writeInt(numSourceUser);
98 parcel.writeInt(numSourcePeriodic);
99 parcel.writeInt(numSourceFeed);
100 parcel.writeInt(numFailures);
101 parcel.writeInt(numCancels);
102 }
103
104 /** Read all the stats from a parcel. */
105 public void readFromParcel(Parcel parcel) {
106 totalElapsedTime = parcel.readLong();
107 numSyncs = parcel.readInt();
108 numSourcePoll = parcel.readInt();
109 numSourceOther = parcel.readInt();
110 numSourceLocal = parcel.readInt();
111 numSourceUser = parcel.readInt();
112 numSourcePeriodic = parcel.readInt();
113 numSourceFeed = parcel.readInt();
114 numFailures = parcel.readInt();
115 numCancels = parcel.readInt();
116 }
117 }
118
119 public long lastTodayResetTime;
120
121 public final Stats totalStats = new Stats();
122 public final Stats todayStats = new Stats();
123 public final Stats yesterdayStats = new Stats();
124
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100125 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700126 public long lastSuccessTime;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100127 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700128 public int lastSuccessSource;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100129 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700130 public long lastFailureTime;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100131 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700132 public int lastFailureSource;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100133 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700134 public String lastFailureMesg;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100135 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700136 public long initialFailureTime;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100137 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700138 public boolean pending;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100139 @UnsupportedAppUsage
Costin Manolache5ed64cd2009-09-22 14:41:46 -0700140 public boolean initialize;
Makoto Onukif74cf942018-04-16 17:04:58 -0700141
142 public final long[] perSourceLastSuccessTimes = new long[SOURCE_COUNT];
143 public final long[] perSourceLastFailureTimes = new long[SOURCE_COUNT];
144
Varun Shah816cf632019-10-30 17:40:15 -0700145 // Warning: It is up to the external caller to ensure there are
146 // no race conditions when accessing this list
147 @UnsupportedAppUsage
148 private ArrayList<Long> periodicSyncTimes;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800149
Makoto Onuki15e7a252017-06-08 17:12:05 -0700150 private final ArrayList<Long> mLastEventTimes = new ArrayList<>();
151 private final ArrayList<String> mLastEvents = new ArrayList<>();
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800152
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100153 @UnsupportedAppUsage
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800154 public SyncStatusInfo(int authorityId) {
Dianne Hackborn231cc602009-04-27 17:10:36 -0700155 this.authorityId = authorityId;
156 }
157
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100158 @UnsupportedAppUsage
Dianne Hackborn231cc602009-04-27 17:10:36 -0700159 public int getLastFailureMesgAsInt(int def) {
Alon Albert5c113fa2013-02-07 08:07:32 -0800160 final int i = ContentResolver.syncErrorStringToInt(lastFailureMesg);
161 if (i > 0) {
162 return i;
163 } else {
164 Log.d(TAG, "Unknown lastFailureMesg:" + lastFailureMesg);
165 return def;
Dianne Hackborn231cc602009-04-27 17:10:36 -0700166 }
Dianne Hackborn231cc602009-04-27 17:10:36 -0700167 }
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800168
Dianne Hackborn231cc602009-04-27 17:10:36 -0700169 public int describeContents() {
170 return 0;
171 }
172
173 public void writeToParcel(Parcel parcel, int flags) {
174 parcel.writeInt(VERSION);
175 parcel.writeInt(authorityId);
Makoto Onuki94986212018-04-11 16:24:46 -0700176
177 // Note we can't use Stats.writeToParcel() here; see the below constructor for the reason.
178 parcel.writeLong(totalStats.totalElapsedTime);
179 parcel.writeInt(totalStats.numSyncs);
180 parcel.writeInt(totalStats.numSourcePoll);
181 parcel.writeInt(totalStats.numSourceOther);
182 parcel.writeInt(totalStats.numSourceLocal);
183 parcel.writeInt(totalStats.numSourceUser);
184
Dianne Hackborn231cc602009-04-27 17:10:36 -0700185 parcel.writeLong(lastSuccessTime);
186 parcel.writeInt(lastSuccessSource);
187 parcel.writeLong(lastFailureTime);
188 parcel.writeInt(lastFailureSource);
189 parcel.writeString(lastFailureMesg);
190 parcel.writeLong(initialFailureTime);
191 parcel.writeInt(pending ? 1 : 0);
Costin Manolache5ed64cd2009-09-22 14:41:46 -0700192 parcel.writeInt(initialize ? 1 : 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800193 if (periodicSyncTimes != null) {
194 parcel.writeInt(periodicSyncTimes.size());
195 for (long periodicSyncTime : periodicSyncTimes) {
196 parcel.writeLong(periodicSyncTime);
197 }
198 } else {
199 parcel.writeInt(-1);
200 }
Makoto Onuki15e7a252017-06-08 17:12:05 -0700201 parcel.writeInt(mLastEventTimes.size());
202 for (int i = 0; i < mLastEventTimes.size(); i++) {
203 parcel.writeLong(mLastEventTimes.get(i));
204 parcel.writeString(mLastEvents.get(i));
205 }
Makoto Onuki94986212018-04-11 16:24:46 -0700206 // Version 4
207 parcel.writeInt(totalStats.numSourcePeriodic);
208
209 // Version 5
210 parcel.writeInt(totalStats.numSourceFeed);
211 parcel.writeInt(totalStats.numFailures);
212 parcel.writeInt(totalStats.numCancels);
213
214 parcel.writeLong(lastTodayResetTime);
215
216 todayStats.writeToParcel(parcel);
217 yesterdayStats.writeToParcel(parcel);
Makoto Onukif74cf942018-04-16 17:04:58 -0700218
219 // Version 6.
220 parcel.writeLongArray(perSourceLastSuccessTimes);
221 parcel.writeLongArray(perSourceLastFailureTimes);
Dianne Hackborn231cc602009-04-27 17:10:36 -0700222 }
223
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100224 @UnsupportedAppUsage
Jeff Sharkey7a96c392012-11-15 14:01:46 -0800225 public SyncStatusInfo(Parcel parcel) {
Dianne Hackborn231cc602009-04-27 17:10:36 -0700226 int version = parcel.readInt();
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800227 if (version != VERSION && version != 1) {
Dianne Hackborn231cc602009-04-27 17:10:36 -0700228 Log.w("SyncStatusInfo", "Unknown version: " + version);
229 }
230 authorityId = parcel.readInt();
Makoto Onuki94986212018-04-11 16:24:46 -0700231
232 // Note we can't use Stats.writeToParcel() here because the data is persisted and we need
233 // to be able to read from the old format too.
234 totalStats.totalElapsedTime = parcel.readLong();
235 totalStats.numSyncs = parcel.readInt();
236 totalStats.numSourcePoll = parcel.readInt();
237 totalStats.numSourceOther = parcel.readInt();
238 totalStats.numSourceLocal = parcel.readInt();
239 totalStats.numSourceUser = parcel.readInt();
Dianne Hackborn231cc602009-04-27 17:10:36 -0700240 lastSuccessTime = parcel.readLong();
241 lastSuccessSource = parcel.readInt();
242 lastFailureTime = parcel.readLong();
243 lastFailureSource = parcel.readInt();
244 lastFailureMesg = parcel.readString();
245 initialFailureTime = parcel.readLong();
246 pending = parcel.readInt() != 0;
Costin Manolache5ed64cd2009-09-22 14:41:46 -0700247 initialize = parcel.readInt() != 0;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800248 if (version == 1) {
249 periodicSyncTimes = null;
250 } else {
Makoto Onuki15e7a252017-06-08 17:12:05 -0700251 final int count = parcel.readInt();
252 if (count < 0) {
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800253 periodicSyncTimes = null;
254 } else {
255 periodicSyncTimes = new ArrayList<Long>();
Makoto Onuki15e7a252017-06-08 17:12:05 -0700256 for (int i = 0; i < count; i++) {
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800257 periodicSyncTimes.add(parcel.readLong());
258 }
259 }
Makoto Onuki15e7a252017-06-08 17:12:05 -0700260 if (version >= 3) {
261 mLastEventTimes.clear();
262 mLastEvents.clear();
263 final int nEvents = parcel.readInt();
264 for (int i = 0; i < nEvents; i++) {
265 mLastEventTimes.add(parcel.readLong());
266 mLastEvents.add(parcel.readString());
267 }
268 }
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800269 }
Makoto Onukifdc57232017-07-21 15:30:35 -0700270 if (version < 4) {
271 // Before version 4, numSourcePeriodic wasn't persisted.
Makoto Onuki94986212018-04-11 16:24:46 -0700272 totalStats.numSourcePeriodic =
273 totalStats.numSyncs - totalStats.numSourceLocal - totalStats.numSourcePoll
274 - totalStats.numSourceOther
275 - totalStats.numSourceUser;
276 if (totalStats.numSourcePeriodic < 0) { // Sanity check.
277 totalStats.numSourcePeriodic = 0;
Makoto Onukifdc57232017-07-21 15:30:35 -0700278 }
279 } else {
Makoto Onuki94986212018-04-11 16:24:46 -0700280 totalStats.numSourcePeriodic = parcel.readInt();
281 }
282 if (version >= 5) {
283 totalStats.numSourceFeed = parcel.readInt();
284 totalStats.numFailures = parcel.readInt();
285 totalStats.numCancels = parcel.readInt();
286
287 lastTodayResetTime = parcel.readLong();
288
289 todayStats.readFromParcel(parcel);
290 yesterdayStats.readFromParcel(parcel);
Makoto Onukifdc57232017-07-21 15:30:35 -0700291 }
Makoto Onukif74cf942018-04-16 17:04:58 -0700292 if (version >= 6) {
293 parcel.readLongArray(perSourceLastSuccessTimes);
294 parcel.readLongArray(perSourceLastFailureTimes);
295 }
Dianne Hackborn231cc602009-04-27 17:10:36 -0700296 }
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800297
Varun Shah816cf632019-10-30 17:40:15 -0700298 /**
299 * Copies all data from the given SyncStatusInfo object.
300 *
301 * @param other the SyncStatusInfo object to copy data from
302 */
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700303 public SyncStatusInfo(SyncStatusInfo other) {
304 authorityId = other.authorityId;
Varun Shah816cf632019-10-30 17:40:15 -0700305 copyFrom(other);
306 }
Makoto Onuki94986212018-04-11 16:24:46 -0700307
Varun Shah816cf632019-10-30 17:40:15 -0700308 /**
309 * Copies all data from the given SyncStatusInfo object except for its authority id.
310 *
311 * @param authorityId the new authority id
312 * @param other the SyncStatusInfo object to copy data from
313 */
314 public SyncStatusInfo(int authorityId, SyncStatusInfo other) {
315 this.authorityId = authorityId;
316 copyFrom(other);
317 }
318
319 private void copyFrom(SyncStatusInfo other) {
Makoto Onuki94986212018-04-11 16:24:46 -0700320 other.totalStats.copyTo(totalStats);
321 other.todayStats.copyTo(todayStats);
322 other.yesterdayStats.copyTo(yesterdayStats);
323
324 lastTodayResetTime = other.lastTodayResetTime;
325
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700326 lastSuccessTime = other.lastSuccessTime;
327 lastSuccessSource = other.lastSuccessSource;
328 lastFailureTime = other.lastFailureTime;
329 lastFailureSource = other.lastFailureSource;
330 lastFailureMesg = other.lastFailureMesg;
331 initialFailureTime = other.initialFailureTime;
332 pending = other.pending;
333 initialize = other.initialize;
334 if (other.periodicSyncTimes != null) {
335 periodicSyncTimes = new ArrayList<Long>(other.periodicSyncTimes);
336 }
Makoto Onuki15e7a252017-06-08 17:12:05 -0700337 mLastEventTimes.addAll(other.mLastEventTimes);
338 mLastEvents.addAll(other.mLastEvents);
Makoto Onukif74cf942018-04-16 17:04:58 -0700339
340 copy(perSourceLastSuccessTimes, other.perSourceLastSuccessTimes);
341 copy(perSourceLastFailureTimes, other.perSourceLastFailureTimes);
342 }
343
344 private static void copy(long[] to, long[] from) {
345 System.arraycopy(from, 0, to, 0, to.length);
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700346 }
347
Varun Shah816cf632019-10-30 17:40:15 -0700348 public int getPeriodicSyncTimesSize() {
349 return periodicSyncTimes == null ? 0 : periodicSyncTimes.size();
350 }
351
352 public void addPeriodicSyncTime(long time) {
353 periodicSyncTimes = ArrayUtils.add(periodicSyncTimes, time);
354 }
355
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100356 @UnsupportedAppUsage
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800357 public void setPeriodicSyncTime(int index, long when) {
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700358 // The list is initialized lazily when scheduling occurs so we need to make sure
359 // we initialize elements < index to zero (zero is ignore for scheduling purposes)
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800360 ensurePeriodicSyncTimeSize(index);
361 periodicSyncTimes.set(index, when);
362 }
363
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100364 @UnsupportedAppUsage
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700365 public long getPeriodicSyncTime(int index) {
366 if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
367 return periodicSyncTimes.get(index);
368 } else {
369 return 0;
370 }
371 }
372
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100373 @UnsupportedAppUsage
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700374 public void removePeriodicSyncTime(int index) {
375 if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
376 periodicSyncTimes.remove(index);
377 }
378 }
379
Varun Shah816cf632019-10-30 17:40:15 -0700380 /**
381 * Populates {@code mLastEventTimes} and {@code mLastEvents} with the given list. <br>
382 * <i>Note: This method is mainly used to repopulate the event info from disk and it will clear
383 * both {@code mLastEventTimes} and {@code mLastEvents} before populating.</i>
384 *
385 * @param lastEventInformation the list to populate with
386 */
387 public void populateLastEventsInformation(ArrayList<Pair<Long, String>> lastEventInformation) {
388 mLastEventTimes.clear();
389 mLastEvents.clear();
390 final int size = lastEventInformation.size();
391 for (int i = 0; i < size; i++) {
392 final Pair<Long, String> lastEventInfo = lastEventInformation.get(i);
393 mLastEventTimes.add(lastEventInfo.first);
394 mLastEvents.add(lastEventInfo.second);
395 }
396 }
397
Makoto Onuki15e7a252017-06-08 17:12:05 -0700398 /** */
399 public void addEvent(String message) {
400 if (mLastEventTimes.size() >= MAX_EVENT_COUNT) {
401 mLastEventTimes.remove(MAX_EVENT_COUNT - 1);
402 mLastEvents.remove(MAX_EVENT_COUNT - 1);
403 }
404 mLastEventTimes.add(0, System.currentTimeMillis());
405 mLastEvents.add(0, message);
406 }
407
408 /** */
409 public int getEventCount() {
410 return mLastEventTimes.size();
411 }
412
413 /** */
414 public long getEventTime(int i) {
415 return mLastEventTimes.get(i);
416 }
417
418 /** */
419 public String getEvent(int i) {
420 return mLastEvents.get(i);
421 }
422
Makoto Onukif74cf942018-04-16 17:04:58 -0700423 /** Call this when a sync has succeeded. */
424 public void setLastSuccess(int source, long lastSyncTime) {
425 lastSuccessTime = lastSyncTime;
426 lastSuccessSource = source;
427 lastFailureTime = 0;
428 lastFailureSource = -1;
429 lastFailureMesg = null;
430 initialFailureTime = 0;
431
432 if (0 <= source && source < perSourceLastSuccessTimes.length) {
433 perSourceLastSuccessTimes[source] = lastSyncTime;
434 }
435 }
436
437 /** Call this when a sync has failed. */
438 public void setLastFailure(int source, long lastSyncTime, String failureMessage) {
439 lastFailureTime = lastSyncTime;
440 lastFailureSource = source;
441 lastFailureMesg = failureMessage;
442 if (initialFailureTime == 0) {
443 initialFailureTime = lastSyncTime;
444 }
445
446 if (0 <= source && source < perSourceLastFailureTimes.length) {
447 perSourceLastFailureTimes[source] = lastSyncTime;
448 }
449 }
450
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100451 @UnsupportedAppUsage
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700452 public static final @android.annotation.NonNull Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
Georgi Nikolovdbe846b2013-06-25 14:09:56 -0700453 public SyncStatusInfo createFromParcel(Parcel in) {
454 return new SyncStatusInfo(in);
455 }
456
457 public SyncStatusInfo[] newArray(int size) {
458 return new SyncStatusInfo[size];
459 }
460 };
461
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100462 @UnsupportedAppUsage
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800463 private void ensurePeriodicSyncTimeSize(int index) {
464 if (periodicSyncTimes == null) {
465 periodicSyncTimes = new ArrayList<Long>(0);
466 }
467
468 final int requiredSize = index + 1;
469 if (periodicSyncTimes.size() < requiredSize) {
470 for (int i = periodicSyncTimes.size(); i < requiredSize; i++) {
471 periodicSyncTimes.add((long) 0);
472 }
473 }
474 }
Makoto Onuki94986212018-04-11 16:24:46 -0700475
476 /**
Makoto Onukif74cf942018-04-16 17:04:58 -0700477 * If the last reset was not today, move today's stats to yesterday's and clear today's.
Makoto Onuki94986212018-04-11 16:24:46 -0700478 */
479 public void maybeResetTodayStats(boolean clockValid, boolean force) {
480 final long now = System.currentTimeMillis();
481
482 if (!force) {
483 // Last reset was the same day, nothing to do.
484 if (areSameDates(now, lastTodayResetTime)) {
485 return;
486 }
487
488 // Hack -- on devices with no RTC, until the NTP kicks in, the device won't have the
489 // correct time. So if the time goes back, don't reset, unless we're sure the current
490 // time is correct.
491 if (now < lastTodayResetTime && !clockValid) {
492 return;
493 }
494 }
495
496 lastTodayResetTime = now;
497
498 todayStats.copyTo(yesterdayStats);
499 todayStats.clear();
500 }
501
502 private static boolean areSameDates(long time1, long time2) {
503 final Calendar c1 = new GregorianCalendar();
504 final Calendar c2 = new GregorianCalendar();
505
506 c1.setTimeInMillis(time1);
507 c2.setTimeInMillis(time2);
508
509 return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)
510 && c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
511 }
Makoto Onukif74cf942018-04-16 17:04:58 -0700512}