1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.android.frameworks.perftests.usage.tests;
18 
19 import static junit.framework.Assert.assertEquals;
20 
21 import android.app.usage.UsageEvents;
22 import android.app.usage.UsageStatsManager;
23 import android.content.Context;
24 import android.os.SystemClock;
25 import android.perftests.utils.ManualBenchmarkState;
26 import android.perftests.utils.PerfManualStatusReporter;
27 
28 import androidx.test.InstrumentationRegistry;
29 import androidx.test.filters.LargeTest;
30 import androidx.test.runner.AndroidJUnit4;
31 
32 import com.android.server.usage.IntervalStats;
33 import com.android.server.usage.PackagesTokenData;
34 import com.android.server.usage.UsageStatsDatabase;
35 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
36 
37 import org.junit.BeforeClass;
38 import org.junit.Rule;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.io.File;
43 import java.io.IOException;
44 import java.util.List;
45 
46 @RunWith(AndroidJUnit4.class)
47 @LargeTest
48 public class UsageStatsDatabasePerfTest {
49     protected static Context sContext;
50     private static UsageStatsDatabase sUsageStatsDatabase;
51     private static File mTestDir;
52 
53     // Represents how many apps might have used in a day by a user with a few apps
54     final static int FEW_PKGS = 10;
55     // Represent how many apps might have used in a day by a user with many apps
56     final static int MANY_PKGS = 50;
57     // Represents how many usage events per app a device might have with light usage
58     final static int LIGHT_USE = 10;
59     // Represents how many usage events per app a device might have with heavy usage
60     final static int HEAVY_USE = 50;
61 
62     private static final StatCombiner<UsageEvents.Event> sUsageStatsCombiner =
63             new StatCombiner<UsageEvents.Event>() {
64                 @Override
65                 public void combine(IntervalStats stats, boolean mutable,
66                         List<UsageEvents.Event> accResult) {
67                     final int size = stats.events.size();
68                     for (int i = 0; i < size; i++) {
69                         accResult.add(stats.events.get(i));
70                     }
71                 }
72             };
73 
74 
75     @Rule
76     public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
77 
78     @BeforeClass
setUpOnce()79     public static void setUpOnce() {
80         sContext = InstrumentationRegistry.getTargetContext();
81         mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
82         sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
83         sUsageStatsDatabase.readMappingsLocked();
84         sUsageStatsDatabase.init(1);
85     }
86 
populateIntervalStats(IntervalStats intervalStats, int packageCount, int eventsPerPackage)87     private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
88             int eventsPerPackage) {
89         for (int pkg = 0; pkg < packageCount; pkg++) {
90             UsageEvents.Event event = new UsageEvents.Event();
91             event.mPackage = "fake.package.name" + pkg;
92             event.mClass = event.mPackage + ".class1";
93             event.mTimeStamp = 1;
94             event.mEventType = UsageEvents.Event.ACTIVITY_RESUMED;
95             for (int evt = 0; evt < eventsPerPackage; evt++) {
96                 intervalStats.events.insert(event);
97                 intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
98                         event.mEventType, 1);
99             }
100         }
101     }
102 
clearUsageStatsFiles()103     private static void clearUsageStatsFiles() {
104         File[] intervalDirs = mTestDir.listFiles();
105         for (File intervalDir : intervalDirs) {
106             if (intervalDir.isDirectory()) {
107                 File[] usageFiles = intervalDir.listFiles();
108                 for (File f : usageFiles) {
109                     f.delete();
110                 }
111             }
112         }
113     }
114 
runQueryUsageStatsTest(int packageCount, int eventsPerPackage)115     private void runQueryUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
116         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
117         IntervalStats intervalStats = new IntervalStats();
118         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
119         sUsageStatsDatabase.putUsageStats(0, intervalStats);
120         long elapsedTimeNs = 0;
121         while (benchmarkState.keepRunning(elapsedTimeNs)) {
122             final long startTime = SystemClock.elapsedRealtimeNanos();
123             List<UsageEvents.Event> temp = sUsageStatsDatabase.queryUsageStats(
124                     UsageStatsManager.INTERVAL_DAILY, 0, 2, sUsageStatsCombiner);
125             final long endTime = SystemClock.elapsedRealtimeNanos();
126             elapsedTimeNs = endTime - startTime;
127             assertEquals(packageCount * eventsPerPackage, temp.size());
128         }
129     }
130 
runPutUsageStatsTest(int packageCount, int eventsPerPackage)131     private void runPutUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
132         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
133         IntervalStats intervalStats = new IntervalStats();
134         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
135         long elapsedTimeNs = 0;
136         while (benchmarkState.keepRunning(elapsedTimeNs)) {
137             final long startTime = SystemClock.elapsedRealtimeNanos();
138             sUsageStatsDatabase.putUsageStats(0, intervalStats);
139             final long endTime = SystemClock.elapsedRealtimeNanos();
140             elapsedTimeNs = endTime - startTime;
141             clearUsageStatsFiles();
142         }
143     }
144 
runObfuscateStatsTest(int packageCount, int eventsPerPackage)145     private void runObfuscateStatsTest(int packageCount, int eventsPerPackage) {
146         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
147         IntervalStats intervalStats = new IntervalStats();
148         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
149         long elapsedTimeNs = 0;
150         while (benchmarkState.keepRunning(elapsedTimeNs)) {
151             final long startTime = SystemClock.elapsedRealtimeNanos();
152             PackagesTokenData packagesTokenData = new PackagesTokenData();
153             intervalStats.obfuscateData(packagesTokenData);
154             final long endTime = SystemClock.elapsedRealtimeNanos();
155             elapsedTimeNs = endTime - startTime;
156             clearUsageStatsFiles();
157         }
158     }
159 
runDeobfuscateStatsTest(int packageCount, int eventsPerPackage)160     private void runDeobfuscateStatsTest(int packageCount, int eventsPerPackage) {
161         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
162         IntervalStats intervalStats = new IntervalStats();
163         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
164         long elapsedTimeNs = 0;
165         while (benchmarkState.keepRunning(elapsedTimeNs)) {
166             PackagesTokenData packagesTokenData = new PackagesTokenData();
167             intervalStats.obfuscateData(packagesTokenData);
168             final long startTime = SystemClock.elapsedRealtimeNanos();
169             intervalStats.deobfuscateData(packagesTokenData);
170             final long endTime = SystemClock.elapsedRealtimeNanos();
171             elapsedTimeNs = endTime - startTime;
172             clearUsageStatsFiles();
173         }
174     }
175 
176     @Test
testQueryUsageStats_FewPkgsLightUse()177     public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
178         runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
179     }
180 
181     @Test
testPutUsageStats_FewPkgsLightUse()182     public void testPutUsageStats_FewPkgsLightUse() throws IOException {
183         runPutUsageStatsTest(FEW_PKGS, LIGHT_USE);
184     }
185 
186     @Test
testObfuscateStats_FewPkgsLightUse()187     public void testObfuscateStats_FewPkgsLightUse() {
188         runObfuscateStatsTest(FEW_PKGS, LIGHT_USE);
189     }
190 
191     @Test
testDeobfuscateStats_FewPkgsLightUse()192     public void testDeobfuscateStats_FewPkgsLightUse() {
193         runDeobfuscateStatsTest(FEW_PKGS, LIGHT_USE);
194     }
195 
196     @Test
testQueryUsageStats_FewPkgsHeavyUse()197     public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
198         runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
199     }
200 
201     @Test
testPutUsageStats_FewPkgsHeavyUse()202     public void testPutUsageStats_FewPkgsHeavyUse() throws IOException {
203         runPutUsageStatsTest(FEW_PKGS, HEAVY_USE);
204     }
205 
206     @Test
testObfuscateStats_FewPkgsHeavyUse()207     public void testObfuscateStats_FewPkgsHeavyUse() {
208         runObfuscateStatsTest(FEW_PKGS, HEAVY_USE);
209     }
210 
211     @Test
testDeobfuscateStats_FewPkgsHeavyUse()212     public void testDeobfuscateStats_FewPkgsHeavyUse() {
213         runDeobfuscateStatsTest(FEW_PKGS, HEAVY_USE);
214     }
215 
216     @Test
testQueryUsageStats_ManyPkgsLightUse()217     public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
218         runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
219     }
220 
221     @Test
testPutUsageStats_ManyPkgsLightUse()222     public void testPutUsageStats_ManyPkgsLightUse() throws IOException {
223         runPutUsageStatsTest(MANY_PKGS, LIGHT_USE);
224     }
225 
226     @Test
testObfuscateStats_ManyPkgsLightUse()227     public void testObfuscateStats_ManyPkgsLightUse() {
228         runObfuscateStatsTest(MANY_PKGS, LIGHT_USE);
229     }
230 
231     @Test
testDeobfuscateStats_ManyPkgsLightUse()232     public void testDeobfuscateStats_ManyPkgsLightUse() {
233         runDeobfuscateStatsTest(MANY_PKGS, LIGHT_USE);
234     }
235 
236     @Test
testQueryUsageStats_ManyPkgsHeavyUse()237     public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
238         runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
239     }
240 
241     @Test
testPutUsageStats_ManyPkgsHeavyUse()242     public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
243         runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
244     }
245 
246     @Test
testObfuscateStats_ManyPkgsHeavyUse()247     public void testObfuscateStats_ManyPkgsHeavyUse() {
248         runObfuscateStatsTest(MANY_PKGS, HEAVY_USE);
249     }
250 
251     @Test
testDeobfuscateStats_ManyPkgsHeavyUse()252     public void testDeobfuscateStats_ManyPkgsHeavyUse() {
253         runDeobfuscateStatsTest(MANY_PKGS, HEAVY_USE);
254     }
255 }
256