Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd74d764 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update SyncStorageEngine to use protos."

parents 15cc75b6 816cf63b
Loading
Loading
Loading
Loading
+52 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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
@@ -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) {
+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;
}
+475 −72

File changed.

Preview size limit exceeded, changes collapsed.

+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);
    }
}