Update SyncStorageEngine to use protos.
Status and Statistics info within SyncStorageEngine was being stored
using Parcels, which is not recommended. Updating both of them to use
protos now. Additionally, because of protos, storage space on disk
consumed by these files are reduced by more than 50%.
Also added unit tests for SyncStorageEngine.
Bug: 38177679
Test: atest com.android.server.content.SyncStorageEngineTest
Test: build and flash - no errors in logs
Change-Id: I187cb6c271333f366f5c7f651f75b4161fee90d4
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 3f64515..0eea47a 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -20,6 +20,9 @@
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;
@@ -139,10 +142,10 @@
public final long[] perSourceLastSuccessTimes = new long[SOURCE_COUNT];
public final long[] perSourceLastFailureTimes = new long[SOURCE_COUNT];
- // Warning: It is up to the external caller to ensure there are
- // no race conditions when accessing this list
- @UnsupportedAppUsage
- private ArrayList<Long> periodicSyncTimes;
+ // Warning: It is up to the external caller to ensure there are
+ // no race conditions when accessing this list
+ @UnsupportedAppUsage
+ private ArrayList<Long> periodicSyncTimes;
private final ArrayList<Long> mLastEventTimes = new ArrayList<>();
private final ArrayList<String> mLastEvents = new ArrayList<>();
@@ -292,9 +295,28 @@
}
}
+ /**
+ * 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);
@@ -323,6 +345,14 @@
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
@@ -347,6 +377,24 @@
}
}
+ /**
+ * 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) {
diff --git a/core/proto/android/server/syncstorageengine.proto b/core/proto/android/server/syncstorageengine.proto
new file mode 100644
index 0000000..87eb1b3
--- /dev/null
+++ b/core/proto/android/server/syncstorageengine.proto
@@ -0,0 +1,86 @@
+/*
+ * 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;
+}