Loading core/java/android/content/SyncStatusInfo.java +52 −4 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import android.util.Pair; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.Calendar; Loading Loading @@ -292,9 +295,28 @@ public class SyncStatusInfo implements Parcelable { } } /** * Copies all data from the given SyncStatusInfo object. * * @param other the SyncStatusInfo object to copy data from */ public SyncStatusInfo(SyncStatusInfo other) { authorityId = other.authorityId; copyFrom(other); } /** * Copies all data from the given SyncStatusInfo object except for its authority id. * * @param authorityId the new authority id * @param other the SyncStatusInfo object to copy data from */ public SyncStatusInfo(int authorityId, SyncStatusInfo other) { this.authorityId = authorityId; copyFrom(other); } private void copyFrom(SyncStatusInfo other) { other.totalStats.copyTo(totalStats); other.todayStats.copyTo(todayStats); other.yesterdayStats.copyTo(yesterdayStats); Loading Loading @@ -323,6 +345,14 @@ public class SyncStatusInfo implements Parcelable { System.arraycopy(from, 0, to, 0, to.length); } public int getPeriodicSyncTimesSize() { return periodicSyncTimes == null ? 0 : periodicSyncTimes.size(); } public void addPeriodicSyncTime(long time) { periodicSyncTimes = ArrayUtils.add(periodicSyncTimes, time); } @UnsupportedAppUsage public void setPeriodicSyncTime(int index, long when) { // The list is initialized lazily when scheduling occurs so we need to make sure Loading @@ -347,6 +377,24 @@ public class SyncStatusInfo implements Parcelable { } } /** * Populates {@code mLastEventTimes} and {@code mLastEvents} with the given list. <br> * <i>Note: This method is mainly used to repopulate the event info from disk and it will clear * both {@code mLastEventTimes} and {@code mLastEvents} before populating.</i> * * @param lastEventInformation the list to populate with */ public void populateLastEventsInformation(ArrayList<Pair<Long, String>> lastEventInformation) { mLastEventTimes.clear(); mLastEvents.clear(); final int size = lastEventInformation.size(); for (int i = 0; i < size; i++) { final Pair<Long, String> lastEventInfo = lastEventInformation.get(i); mLastEventTimes.add(lastEventInfo.first); mLastEvents.add(lastEventInfo.second); } } /** */ public void addEvent(String message) { if (mLastEventTimes.size() >= MAX_EVENT_COUNT) { Loading core/proto/android/server/syncstorageengine.proto 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ syntax = "proto2"; package com.android.server.content; import "frameworks/base/core/proto/android/privacy.proto"; option java_multiple_files = true; /** * Stores relevant information from a DayStats object in SyncStorageEngine. */ message SyncStatisticsProto { message DayStats { optional int32 day = 1; // day of the year - defined by SyncStorageEngine#getCurrentDayLocked() optional int32 success_count = 2; optional int64 success_time = 3; // time since epoch optional int32 failure_count = 4; optional int64 failure_time = 5; // time since epoch } repeated DayStats stats = 1; } /** * Stores relevant information from a SyncStatusInfo object. */ message SyncStatusProto { message StatusInfo { message Stats { optional int64 total_elapsed_time = 1; // time since epoch optional int32 num_syncs = 2; optional int32 num_failures = 3; optional int32 num_cancels = 4; optional int32 num_source_other = 5; optional int32 num_source_local = 6; optional int32 num_source_poll = 7; optional int32 num_source_user = 8; optional int32 num_source_periodic = 9; optional int32 num_source_feed = 10; } message LastEventInfo { optional int64 last_event_time = 1; // time since epoch optional string last_event = 2; } // Note: version doesn't need to be stored in proto because of how protos store information but // leaving field number 1 open in case we find a usage for it in the future. optional int32 authority_id = 2; optional int64 last_success_time = 3; // time since epoch optional int32 last_success_source = 4; optional int64 last_failure_time = 5; // time since epoch optional int32 last_failure_source = 6; optional string last_failure_message = 7; optional int64 initial_failure_time = 8; // time since epoch optional bool pending = 9; optional bool initialize = 10; repeated int64 periodic_sync_times = 11; // times since epoch repeated LastEventInfo last_event_info = 12; optional int64 last_today_reset_time = 13; // time since epoch optional Stats total_stats = 14; optional Stats today_stats = 15; optional Stats yesterday_stats = 16; repeated int64 per_source_last_success_times = 17; // times since epoch repeated int64 per_source_last_failure_times = 18; // times since epoch } repeated StatusInfo status = 1; } services/core/java/com/android/server/content/SyncStorageEngine.java +475 −72 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java 0 → 100644 +200 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.content; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import android.content.Context; import android.content.SyncStatusInfo; import android.util.Pair; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Random; /** * Tests for {@link SyncStorageEngine}. */ @RunWith(AndroidJUnit4.class) public class SyncStorageEngineTest { private Context mContext; private SyncStorageEngine mSyncStorageEngine; private static final int NUM_SYNC_STATUS = 100; private static final int NUM_PERIODIC_SYNC_TIMES = 20; private static final int NUM_EVENTS = 10; private static final int NUM_SOURCES = 6; @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext(); mSyncStorageEngine = SyncStorageEngine.newTestInstance(mContext); } @Test public void testStatisticsReadWrite() { populateDayStats(mSyncStorageEngine.mDayStats); mSyncStorageEngine.writeStatisticsLocked(); final SyncStorageEngine other = SyncStorageEngine.newTestInstance(mContext); verifyDayStats(mSyncStorageEngine.mDayStats, other.getDayStatistics()); } @Test public void testStatusReadWrite() { populateStatus(mSyncStorageEngine.mSyncStatus); mSyncStorageEngine.writeStatusLocked(); final SyncStorageEngine other = SyncStorageEngine.newTestInstance(mContext); for (int i = 0; i < NUM_SYNC_STATUS; i++) { other.mAuthorities.put(i, null); } other.readStatusLocked(); verifyStatus(mSyncStorageEngine.mSyncStatus, other.mSyncStatus); } private void populateDayStats(SyncStorageEngine.DayStats[] dayStats) { final Random r = new Random(1); for (int i = 0; i < dayStats.length; i++) { final SyncStorageEngine.DayStats ds = new SyncStorageEngine.DayStats(i); ds.successCount = r.nextInt(); ds.successTime = r.nextLong(); ds.failureCount = r.nextInt(); ds.failureTime = r.nextLong(); dayStats[i] = ds; } } private void verifyDayStats(SyncStorageEngine.DayStats[] dayStats, SyncStorageEngine.DayStats[] dayStatsOther) { assertEquals(dayStatsOther.length, dayStats.length); for (int i = 0; i < dayStatsOther.length; i++) { final SyncStorageEngine.DayStats ds = dayStats[i]; final SyncStorageEngine.DayStats dsOther = dayStatsOther[i]; assertEquals(dsOther.day, ds.day); assertEquals(dsOther.successCount, ds.successCount); assertEquals(dsOther.successTime, ds.successTime); assertEquals(dsOther.failureCount, ds.failureCount); assertEquals(dsOther.failureTime, ds.failureTime); } } private void populateStatus(SparseArray<SyncStatusInfo> syncStatus) { final Random r = new Random(1); for (int i = 0; i < NUM_SYNC_STATUS; i++) { final SyncStatusInfo ss = new SyncStatusInfo(i); ss.lastSuccessTime = r.nextLong(); ss.lastSuccessSource = r.nextInt(); ss.lastFailureTime = r.nextLong(); ss.lastFailureSource = r.nextInt(); ss.lastFailureMesg = "fail_msg_" + r.nextInt(); ss.initialFailureTime = r.nextLong(); ss.initialize = r.nextBoolean(); for (int j = 0; j < NUM_PERIODIC_SYNC_TIMES; j++) { ss.addPeriodicSyncTime(r.nextLong()); } final ArrayList<Pair<Long, String>> lastEventInfos = new ArrayList<>(); for (int j = 0; j < NUM_EVENTS; j++) { lastEventInfos.add(new Pair<>(r.nextLong(), "event_" + r.nextInt())); } ss.populateLastEventsInformation(lastEventInfos); ss.lastTodayResetTime = r.nextLong(); populateStats(ss.totalStats, r); populateStats(ss.todayStats, r); populateStats(ss.yesterdayStats, r); for (int j = 0; j < NUM_SOURCES; j++) { ss.perSourceLastSuccessTimes[j] = r.nextLong(); } for (int j = 0; j < NUM_SOURCES; j++) { ss.perSourceLastFailureTimes[j] = r.nextLong(); } syncStatus.put(i, ss); } } private void populateStats(SyncStatusInfo.Stats stats, Random r) { stats.totalElapsedTime = r.nextLong(); stats.numSyncs = r.nextInt(); stats.numFailures = r.nextInt(); stats.numCancels = r.nextInt(); stats.numSourceOther = r.nextInt(); stats.numSourceLocal = r.nextInt(); stats.numSourcePoll = r.nextInt(); stats.numSourceUser = r.nextInt(); stats.numSourcePeriodic = r.nextInt(); stats.numSourceFeed = r.nextInt(); } private void verifyStatus(SparseArray<SyncStatusInfo> syncStatus, SparseArray<SyncStatusInfo> syncStatusOther) { assertEquals(syncStatusOther.size(), syncStatus.size()); for (int i = 0; i < NUM_SYNC_STATUS; i++) { final SyncStatusInfo ss = syncStatus.valueAt(i); final SyncStatusInfo ssOther = syncStatusOther.valueAt(i); assertEquals(ssOther.authorityId, ss.authorityId); assertEquals(ssOther.lastSuccessTime, ss.lastSuccessTime); assertEquals(ssOther.lastSuccessSource, ss.lastSuccessSource); assertEquals(ssOther.lastFailureTime, ss.lastFailureTime); assertEquals(ssOther.lastFailureSource, ss.lastFailureSource); assertEquals(ssOther.lastFailureMesg, ss.lastFailureMesg); assertFalse(ssOther.pending); // pending is always set to false when read assertEquals(ssOther.initialize, ss.initialize); assertEquals(ssOther.getPeriodicSyncTimesSize(), NUM_PERIODIC_SYNC_TIMES); for (int j = 0; j < NUM_PERIODIC_SYNC_TIMES; j++) { assertEquals(ssOther.getPeriodicSyncTime(j), ss.getPeriodicSyncTime(j)); } assertEquals(ssOther.getEventCount(), NUM_EVENTS); for (int j = 0; j < NUM_EVENTS; j++) { assertEquals(ssOther.getEventTime(j), ss.getEventTime(j)); assertEquals(ssOther.getEvent(j), ss.getEvent(j)); } assertEquals(ssOther.lastTodayResetTime, ss.lastTodayResetTime); verifyStats(ss.totalStats, ssOther.totalStats); verifyStats(ss.todayStats, ssOther.todayStats); verifyStats(ss.yesterdayStats, ssOther.yesterdayStats); assertEquals(ssOther.perSourceLastSuccessTimes.length, NUM_SOURCES); for (int j = 0; j < NUM_SOURCES; j++) { assertEquals(ssOther.perSourceLastSuccessTimes[j], ss.perSourceLastSuccessTimes[j]); } assertEquals(ssOther.perSourceLastFailureTimes.length, NUM_SOURCES); for (int j = 0; j < NUM_SOURCES; j++) { assertEquals(ssOther.perSourceLastFailureTimes[j], ss.perSourceLastFailureTimes[j]); } } } private void verifyStats(SyncStatusInfo.Stats stats, SyncStatusInfo.Stats statsOther) { assertEquals(statsOther.totalElapsedTime, stats.totalElapsedTime); assertEquals(statsOther.numSyncs, stats.numSyncs); assertEquals(statsOther.numFailures, stats.numFailures); assertEquals(statsOther.numCancels, stats.numCancels); assertEquals(statsOther.numSourceOther, stats.numSourceOther); assertEquals(statsOther.numSourceLocal, stats.numSourceLocal); assertEquals(statsOther.numSourcePoll, stats.numSourcePoll); assertEquals(statsOther.numSourceUser, stats.numSourceUser); assertEquals(statsOther.numSourcePeriodic, stats.numSourcePeriodic); assertEquals(statsOther.numSourceFeed, stats.numSourceFeed); } } Loading
core/java/android/content/SyncStatusInfo.java +52 −4 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import android.util.Pair; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.Calendar; Loading Loading @@ -292,9 +295,28 @@ public class SyncStatusInfo implements Parcelable { } } /** * Copies all data from the given SyncStatusInfo object. * * @param other the SyncStatusInfo object to copy data from */ public SyncStatusInfo(SyncStatusInfo other) { authorityId = other.authorityId; copyFrom(other); } /** * Copies all data from the given SyncStatusInfo object except for its authority id. * * @param authorityId the new authority id * @param other the SyncStatusInfo object to copy data from */ public SyncStatusInfo(int authorityId, SyncStatusInfo other) { this.authorityId = authorityId; copyFrom(other); } private void copyFrom(SyncStatusInfo other) { other.totalStats.copyTo(totalStats); other.todayStats.copyTo(todayStats); other.yesterdayStats.copyTo(yesterdayStats); Loading Loading @@ -323,6 +345,14 @@ public class SyncStatusInfo implements Parcelable { System.arraycopy(from, 0, to, 0, to.length); } public int getPeriodicSyncTimesSize() { return periodicSyncTimes == null ? 0 : periodicSyncTimes.size(); } public void addPeriodicSyncTime(long time) { periodicSyncTimes = ArrayUtils.add(periodicSyncTimes, time); } @UnsupportedAppUsage public void setPeriodicSyncTime(int index, long when) { // The list is initialized lazily when scheduling occurs so we need to make sure Loading @@ -347,6 +377,24 @@ public class SyncStatusInfo implements Parcelable { } } /** * Populates {@code mLastEventTimes} and {@code mLastEvents} with the given list. <br> * <i>Note: This method is mainly used to repopulate the event info from disk and it will clear * both {@code mLastEventTimes} and {@code mLastEvents} before populating.</i> * * @param lastEventInformation the list to populate with */ public void populateLastEventsInformation(ArrayList<Pair<Long, String>> lastEventInformation) { mLastEventTimes.clear(); mLastEvents.clear(); final int size = lastEventInformation.size(); for (int i = 0; i < size; i++) { final Pair<Long, String> lastEventInfo = lastEventInformation.get(i); mLastEventTimes.add(lastEventInfo.first); mLastEvents.add(lastEventInfo.second); } } /** */ public void addEvent(String message) { if (mLastEventTimes.size() >= MAX_EVENT_COUNT) { Loading
core/proto/android/server/syncstorageengine.proto 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ syntax = "proto2"; package com.android.server.content; import "frameworks/base/core/proto/android/privacy.proto"; option java_multiple_files = true; /** * Stores relevant information from a DayStats object in SyncStorageEngine. */ message SyncStatisticsProto { message DayStats { optional int32 day = 1; // day of the year - defined by SyncStorageEngine#getCurrentDayLocked() optional int32 success_count = 2; optional int64 success_time = 3; // time since epoch optional int32 failure_count = 4; optional int64 failure_time = 5; // time since epoch } repeated DayStats stats = 1; } /** * Stores relevant information from a SyncStatusInfo object. */ message SyncStatusProto { message StatusInfo { message Stats { optional int64 total_elapsed_time = 1; // time since epoch optional int32 num_syncs = 2; optional int32 num_failures = 3; optional int32 num_cancels = 4; optional int32 num_source_other = 5; optional int32 num_source_local = 6; optional int32 num_source_poll = 7; optional int32 num_source_user = 8; optional int32 num_source_periodic = 9; optional int32 num_source_feed = 10; } message LastEventInfo { optional int64 last_event_time = 1; // time since epoch optional string last_event = 2; } // Note: version doesn't need to be stored in proto because of how protos store information but // leaving field number 1 open in case we find a usage for it in the future. optional int32 authority_id = 2; optional int64 last_success_time = 3; // time since epoch optional int32 last_success_source = 4; optional int64 last_failure_time = 5; // time since epoch optional int32 last_failure_source = 6; optional string last_failure_message = 7; optional int64 initial_failure_time = 8; // time since epoch optional bool pending = 9; optional bool initialize = 10; repeated int64 periodic_sync_times = 11; // times since epoch repeated LastEventInfo last_event_info = 12; optional int64 last_today_reset_time = 13; // time since epoch optional Stats total_stats = 14; optional Stats today_stats = 15; optional Stats yesterday_stats = 16; repeated int64 per_source_last_success_times = 17; // times since epoch repeated int64 per_source_last_failure_times = 18; // times since epoch } repeated StatusInfo status = 1; }
services/core/java/com/android/server/content/SyncStorageEngine.java +475 −72 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java 0 → 100644 +200 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.content; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import android.content.Context; import android.content.SyncStatusInfo; import android.util.Pair; import android.util.SparseArray; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Random; /** * Tests for {@link SyncStorageEngine}. */ @RunWith(AndroidJUnit4.class) public class SyncStorageEngineTest { private Context mContext; private SyncStorageEngine mSyncStorageEngine; private static final int NUM_SYNC_STATUS = 100; private static final int NUM_PERIODIC_SYNC_TIMES = 20; private static final int NUM_EVENTS = 10; private static final int NUM_SOURCES = 6; @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext(); mSyncStorageEngine = SyncStorageEngine.newTestInstance(mContext); } @Test public void testStatisticsReadWrite() { populateDayStats(mSyncStorageEngine.mDayStats); mSyncStorageEngine.writeStatisticsLocked(); final SyncStorageEngine other = SyncStorageEngine.newTestInstance(mContext); verifyDayStats(mSyncStorageEngine.mDayStats, other.getDayStatistics()); } @Test public void testStatusReadWrite() { populateStatus(mSyncStorageEngine.mSyncStatus); mSyncStorageEngine.writeStatusLocked(); final SyncStorageEngine other = SyncStorageEngine.newTestInstance(mContext); for (int i = 0; i < NUM_SYNC_STATUS; i++) { other.mAuthorities.put(i, null); } other.readStatusLocked(); verifyStatus(mSyncStorageEngine.mSyncStatus, other.mSyncStatus); } private void populateDayStats(SyncStorageEngine.DayStats[] dayStats) { final Random r = new Random(1); for (int i = 0; i < dayStats.length; i++) { final SyncStorageEngine.DayStats ds = new SyncStorageEngine.DayStats(i); ds.successCount = r.nextInt(); ds.successTime = r.nextLong(); ds.failureCount = r.nextInt(); ds.failureTime = r.nextLong(); dayStats[i] = ds; } } private void verifyDayStats(SyncStorageEngine.DayStats[] dayStats, SyncStorageEngine.DayStats[] dayStatsOther) { assertEquals(dayStatsOther.length, dayStats.length); for (int i = 0; i < dayStatsOther.length; i++) { final SyncStorageEngine.DayStats ds = dayStats[i]; final SyncStorageEngine.DayStats dsOther = dayStatsOther[i]; assertEquals(dsOther.day, ds.day); assertEquals(dsOther.successCount, ds.successCount); assertEquals(dsOther.successTime, ds.successTime); assertEquals(dsOther.failureCount, ds.failureCount); assertEquals(dsOther.failureTime, ds.failureTime); } } private void populateStatus(SparseArray<SyncStatusInfo> syncStatus) { final Random r = new Random(1); for (int i = 0; i < NUM_SYNC_STATUS; i++) { final SyncStatusInfo ss = new SyncStatusInfo(i); ss.lastSuccessTime = r.nextLong(); ss.lastSuccessSource = r.nextInt(); ss.lastFailureTime = r.nextLong(); ss.lastFailureSource = r.nextInt(); ss.lastFailureMesg = "fail_msg_" + r.nextInt(); ss.initialFailureTime = r.nextLong(); ss.initialize = r.nextBoolean(); for (int j = 0; j < NUM_PERIODIC_SYNC_TIMES; j++) { ss.addPeriodicSyncTime(r.nextLong()); } final ArrayList<Pair<Long, String>> lastEventInfos = new ArrayList<>(); for (int j = 0; j < NUM_EVENTS; j++) { lastEventInfos.add(new Pair<>(r.nextLong(), "event_" + r.nextInt())); } ss.populateLastEventsInformation(lastEventInfos); ss.lastTodayResetTime = r.nextLong(); populateStats(ss.totalStats, r); populateStats(ss.todayStats, r); populateStats(ss.yesterdayStats, r); for (int j = 0; j < NUM_SOURCES; j++) { ss.perSourceLastSuccessTimes[j] = r.nextLong(); } for (int j = 0; j < NUM_SOURCES; j++) { ss.perSourceLastFailureTimes[j] = r.nextLong(); } syncStatus.put(i, ss); } } private void populateStats(SyncStatusInfo.Stats stats, Random r) { stats.totalElapsedTime = r.nextLong(); stats.numSyncs = r.nextInt(); stats.numFailures = r.nextInt(); stats.numCancels = r.nextInt(); stats.numSourceOther = r.nextInt(); stats.numSourceLocal = r.nextInt(); stats.numSourcePoll = r.nextInt(); stats.numSourceUser = r.nextInt(); stats.numSourcePeriodic = r.nextInt(); stats.numSourceFeed = r.nextInt(); } private void verifyStatus(SparseArray<SyncStatusInfo> syncStatus, SparseArray<SyncStatusInfo> syncStatusOther) { assertEquals(syncStatusOther.size(), syncStatus.size()); for (int i = 0; i < NUM_SYNC_STATUS; i++) { final SyncStatusInfo ss = syncStatus.valueAt(i); final SyncStatusInfo ssOther = syncStatusOther.valueAt(i); assertEquals(ssOther.authorityId, ss.authorityId); assertEquals(ssOther.lastSuccessTime, ss.lastSuccessTime); assertEquals(ssOther.lastSuccessSource, ss.lastSuccessSource); assertEquals(ssOther.lastFailureTime, ss.lastFailureTime); assertEquals(ssOther.lastFailureSource, ss.lastFailureSource); assertEquals(ssOther.lastFailureMesg, ss.lastFailureMesg); assertFalse(ssOther.pending); // pending is always set to false when read assertEquals(ssOther.initialize, ss.initialize); assertEquals(ssOther.getPeriodicSyncTimesSize(), NUM_PERIODIC_SYNC_TIMES); for (int j = 0; j < NUM_PERIODIC_SYNC_TIMES; j++) { assertEquals(ssOther.getPeriodicSyncTime(j), ss.getPeriodicSyncTime(j)); } assertEquals(ssOther.getEventCount(), NUM_EVENTS); for (int j = 0; j < NUM_EVENTS; j++) { assertEquals(ssOther.getEventTime(j), ss.getEventTime(j)); assertEquals(ssOther.getEvent(j), ss.getEvent(j)); } assertEquals(ssOther.lastTodayResetTime, ss.lastTodayResetTime); verifyStats(ss.totalStats, ssOther.totalStats); verifyStats(ss.todayStats, ssOther.todayStats); verifyStats(ss.yesterdayStats, ssOther.yesterdayStats); assertEquals(ssOther.perSourceLastSuccessTimes.length, NUM_SOURCES); for (int j = 0; j < NUM_SOURCES; j++) { assertEquals(ssOther.perSourceLastSuccessTimes[j], ss.perSourceLastSuccessTimes[j]); } assertEquals(ssOther.perSourceLastFailureTimes.length, NUM_SOURCES); for (int j = 0; j < NUM_SOURCES; j++) { assertEquals(ssOther.perSourceLastFailureTimes[j], ss.perSourceLastFailureTimes[j]); } } } private void verifyStats(SyncStatusInfo.Stats stats, SyncStatusInfo.Stats statsOther) { assertEquals(statsOther.totalElapsedTime, stats.totalElapsedTime); assertEquals(statsOther.numSyncs, stats.numSyncs); assertEquals(statsOther.numFailures, stats.numFailures); assertEquals(statsOther.numCancels, stats.numCancels); assertEquals(statsOther.numSourceOther, stats.numSourceOther); assertEquals(statsOther.numSourceLocal, stats.numSourceLocal); assertEquals(statsOther.numSourcePoll, stats.numSourcePoll); assertEquals(statsOther.numSourceUser, stats.numSourceUser); assertEquals(statsOther.numSourcePeriodic, stats.numSourcePeriodic); assertEquals(statsOther.numSourceFeed, stats.numSourceFeed); } }