Merge "Initial UsageStatsDatabase Perf tests"

This commit is contained in:
TreeHugger Robot
2018-07-03 21:15:15 +00:00
committed by Android (Google) Code Review
6 changed files with 284 additions and 4 deletions

View File

@@ -27,7 +27,9 @@ import android.util.ArraySet;
import java.util.List;
class IntervalStats {
import com.android.internal.annotations.VisibleForTesting;
public class IntervalStats {
public long beginTime;
public long endTime;
public long lastTimeSaved;
@@ -149,7 +151,11 @@ class IntervalStats {
&& eventType != UsageEvents.Event.STANDBY_BUCKET_CHANGED;
}
void update(String packageName, long timeStamp, int eventType) {
/**
* @hide
*/
@VisibleForTesting
public void update(String packageName, long timeStamp, int eventType) {
UsageStats usageStats = getOrCreateUsageStats(packageName);
// TODO(adamlesinski): Ensure that we recover from incorrect event sequences

View File

@@ -42,7 +42,7 @@ import java.util.List;
/**
* Provides an interface to query for UsageStat data from an XML database.
*/
class UsageStatsDatabase {
public class UsageStatsDatabase {
private static final int CURRENT_VERSION = 3;
// Current version of the backup schema
@@ -369,7 +369,7 @@ class UsageStatsDatabase {
/**
* Figures out what to extract from the given IntervalStats object.
*/
interface StatCombiner<T> {
public interface StatCombiner<T> {
/**
* Implementations should extract interesting from <code>stats</code> and add it

View File

@@ -0,0 +1,34 @@
# Copyright (C) 2018 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.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
apct-perftests-utils \
services.usage
LOCAL_PACKAGE_NAME := UsageStatsPerfTests
LOCAL_PRIVATE_PLATFORM_APIS := true
# For android.permission.FORCE_STOP_PACKAGES permission
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworks.perftests.usage">
<uses-sdk
android:minSdkVersion="21" />
<uses-permission android:name="android.permission.DUMP" />
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.frameworks.perftests.usage"/>
</manifest>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->
<configuration description="Runs UsageStats Performance Tests">
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="UsageStatsPerfTests.apk"/>
<option name="cleanup-apks" value="true"/>
</target_preparer>
<option name="test-suite-tag" value="apct"/>
<option name="test-tag" value="UsageStatsPerfTests"/>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.frameworks.perftests.usage"/>
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>
</configuration>

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2018 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.frameworks.perftests.usage.tests;
import static junit.framework.Assert.assertEquals;
import com.android.server.usage.UsageStatsDatabase;
import com.android.server.usage.UsageStatsDatabase.StatCombiner;
import com.android.server.usage.IntervalStats;
import android.app.usage.EventList;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.os.SystemClock;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.PerfManualStatusReporter;
import android.support.test.filters.LargeTest;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.io.IOException;
import java.util.List;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class UsageStatsDatabasePerfTest {
protected static Context sContext;
private static UsageStatsDatabase sUsageStatsDatabase;
private static File mTestDir;
// Represents how many apps might have used in a day by a user with a few apps
final static int FEW_PKGS = 10;
// Represent how many apps might have used in a day by a user with many apps
final static int MANY_PKGS = 50;
// Represents how many usage events per app a device might have with light usage
final static int LIGHT_USE = 10;
// Represents how many usage events per app a device might have with heavy usage
final static int HEAVY_USE = 50;
private static final StatCombiner<UsageEvents.Event> sUsageStatsCombiner =
new StatCombiner<UsageEvents.Event>() {
@Override
public void combine(IntervalStats stats, boolean mutable,
List<UsageEvents.Event> accResult) {
final int size = stats.events.size();
for (int i = 0; i < size; i++) {
accResult.add(stats.events.get(i));
}
}
};
@Rule
public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
@BeforeClass
public static void setUpOnce() {
sContext = InstrumentationRegistry.getTargetContext();
mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
sUsageStatsDatabase.init(1);
}
private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
int eventsPerPackage) {
if (intervalStats.events == null) {
intervalStats.events = new EventList();
}
for (int pkg = 0; pkg < packageCount; pkg++) {
UsageEvents.Event event = new UsageEvents.Event();
event.mPackage = "fake.package.name" + pkg;
event.mTimeStamp = 1;
event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
for (int evt = 0; evt < eventsPerPackage; evt++) {
intervalStats.events.insert(event);
intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
}
}
}
private static void clearUsageStatsFiles() {
File[] intervalDirs = mTestDir.listFiles();
for (File intervalDir : intervalDirs) {
if (intervalDir.isDirectory()) {
File[] usageFiles = intervalDir.listFiles();
for (File f : usageFiles) {
f.delete();
}
}
}
}
private void runQueryUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
IntervalStats intervalStats = new IntervalStats();
populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
sUsageStatsDatabase.putUsageStats(0, intervalStats);
long elapsedTimeNs = 0;
while (benchmarkState.keepRunning(elapsedTimeNs)) {
final long startTime = SystemClock.elapsedRealtimeNanos();
List<UsageEvents.Event> temp = sUsageStatsDatabase.queryUsageStats(
UsageStatsManager.INTERVAL_DAILY, 0, 2, sUsageStatsCombiner);
final long endTime = SystemClock.elapsedRealtimeNanos();
elapsedTimeNs = endTime - startTime;
assertEquals(packageCount * eventsPerPackage, temp.size());
}
}
private void runPutUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
IntervalStats intervalStats = new IntervalStats();
populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
long elapsedTimeNs = 0;
while (benchmarkState.keepRunning(elapsedTimeNs)) {
final long startTime = SystemClock.elapsedRealtimeNanos();
sUsageStatsDatabase.putUsageStats(0, intervalStats);
final long endTime = SystemClock.elapsedRealtimeNanos();
elapsedTimeNs = endTime - startTime;
clearUsageStatsFiles();
}
}
@Test
public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
}
@Test
public void testPutUsageStats_FewPkgsLightUse() throws IOException {
runPutUsageStatsTest(FEW_PKGS, LIGHT_USE);
}
@Test
public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
}
@Test
public void testPutUsageStats_FewPkgsHeavyUse() throws IOException {
runPutUsageStatsTest(FEW_PKGS, HEAVY_USE);
}
@Test
public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
}
@Test
public void testPutUsageStats_ManyPkgsLightUse() throws IOException {
runPutUsageStatsTest(MANY_PKGS, LIGHT_USE);
}
@Test
public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
}
@Test
public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
}
}