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 boolean 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                     return true;
72                 }
73             };
74 
75 
76     @Rule
77     public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
78 
79     @BeforeClass
setUpOnce()80     public static void setUpOnce() {
81         sContext = InstrumentationRegistry.getTargetContext();
82         mTestDir = new File(sContext.getFilesDir(), "UsageStatsDatabasePerfTest");
83         sUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
84         sUsageStatsDatabase.readMappingsLocked();
85         sUsageStatsDatabase.init(1);
86     }
87 
populateIntervalStats(IntervalStats intervalStats, int packageCount, int eventsPerPackage)88     private static void populateIntervalStats(IntervalStats intervalStats, int packageCount,
89             int eventsPerPackage) {
90         for (int pkg = 0; pkg < packageCount; pkg++) {
91             UsageEvents.Event event = new UsageEvents.Event();
92             event.mPackage = "fake.package.name" + pkg;
93             event.mClass = event.mPackage + ".class1";
94             event.mTimeStamp = 1;
95             event.mEventType = UsageEvents.Event.ACTIVITY_RESUMED;
96             for (int evt = 0; evt < eventsPerPackage; evt++) {
97                 intervalStats.events.insert(event);
98                 intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
99                         event.mEventType, 1);
100             }
101         }
102     }
103 
clearUsageStatsFiles()104     private static void clearUsageStatsFiles() {
105         File[] intervalDirs = mTestDir.listFiles();
106         for (File intervalDir : intervalDirs) {
107             if (intervalDir.isDirectory()) {
108                 File[] usageFiles = intervalDir.listFiles();
109                 for (File f : usageFiles) {
110                     f.delete();
111                 }
112             }
113         }
114     }
115 
runQueryUsageStatsTest(int packageCount, int eventsPerPackage)116     private void runQueryUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
117         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
118         IntervalStats intervalStats = new IntervalStats();
119         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
120         sUsageStatsDatabase.putUsageStats(0, intervalStats);
121         long elapsedTimeNs = 0;
122         while (benchmarkState.keepRunning(elapsedTimeNs)) {
123             final long startTime = SystemClock.elapsedRealtimeNanos();
124             List<UsageEvents.Event> temp = sUsageStatsDatabase.queryUsageStats(
125                     UsageStatsManager.INTERVAL_DAILY, 0, 2, sUsageStatsCombiner);
126             final long endTime = SystemClock.elapsedRealtimeNanos();
127             elapsedTimeNs = endTime - startTime;
128             assertEquals(packageCount * eventsPerPackage, temp.size());
129         }
130     }
131 
runPutUsageStatsTest(int packageCount, int eventsPerPackage)132     private void runPutUsageStatsTest(int packageCount, int eventsPerPackage) throws IOException {
133         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
134         IntervalStats intervalStats = new IntervalStats();
135         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
136         long elapsedTimeNs = 0;
137         while (benchmarkState.keepRunning(elapsedTimeNs)) {
138             final long startTime = SystemClock.elapsedRealtimeNanos();
139             sUsageStatsDatabase.putUsageStats(0, intervalStats);
140             final long endTime = SystemClock.elapsedRealtimeNanos();
141             elapsedTimeNs = endTime - startTime;
142             clearUsageStatsFiles();
143         }
144     }
145 
runObfuscateStatsTest(int packageCount, int eventsPerPackage)146     private void runObfuscateStatsTest(int packageCount, int eventsPerPackage) {
147         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
148         IntervalStats intervalStats = new IntervalStats();
149         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
150         long elapsedTimeNs = 0;
151         while (benchmarkState.keepRunning(elapsedTimeNs)) {
152             final long startTime = SystemClock.elapsedRealtimeNanos();
153             PackagesTokenData packagesTokenData = new PackagesTokenData();
154             intervalStats.obfuscateData(packagesTokenData);
155             final long endTime = SystemClock.elapsedRealtimeNanos();
156             elapsedTimeNs = endTime - startTime;
157             clearUsageStatsFiles();
158         }
159     }
160 
runDeobfuscateStatsTest(int packageCount, int eventsPerPackage)161     private void runDeobfuscateStatsTest(int packageCount, int eventsPerPackage) {
162         final ManualBenchmarkState benchmarkState = mPerfManualStatusReporter.getBenchmarkState();
163         IntervalStats intervalStats = new IntervalStats();
164         populateIntervalStats(intervalStats, packageCount, eventsPerPackage);
165         long elapsedTimeNs = 0;
166         while (benchmarkState.keepRunning(elapsedTimeNs)) {
167             PackagesTokenData packagesTokenData = new PackagesTokenData();
168             intervalStats.obfuscateData(packagesTokenData);
169             final long startTime = SystemClock.elapsedRealtimeNanos();
170             intervalStats.deobfuscateData(packagesTokenData);
171             final long endTime = SystemClock.elapsedRealtimeNanos();
172             elapsedTimeNs = endTime - startTime;
173             clearUsageStatsFiles();
174         }
175     }
176 
177     @Test
testQueryUsageStats_FewPkgsLightUse()178     public void testQueryUsageStats_FewPkgsLightUse() throws IOException {
179         runQueryUsageStatsTest(FEW_PKGS, LIGHT_USE);
180     }
181 
182     @Test
testPutUsageStats_FewPkgsLightUse()183     public void testPutUsageStats_FewPkgsLightUse() throws IOException {
184         runPutUsageStatsTest(FEW_PKGS, LIGHT_USE);
185     }
186 
187     @Test
testObfuscateStats_FewPkgsLightUse()188     public void testObfuscateStats_FewPkgsLightUse() {
189         runObfuscateStatsTest(FEW_PKGS, LIGHT_USE);
190     }
191 
192     @Test
testDeobfuscateStats_FewPkgsLightUse()193     public void testDeobfuscateStats_FewPkgsLightUse() {
194         runDeobfuscateStatsTest(FEW_PKGS, LIGHT_USE);
195     }
196 
197     @Test
testQueryUsageStats_FewPkgsHeavyUse()198     public void testQueryUsageStats_FewPkgsHeavyUse() throws IOException {
199         runQueryUsageStatsTest(FEW_PKGS, HEAVY_USE);
200     }
201 
202     @Test
testPutUsageStats_FewPkgsHeavyUse()203     public void testPutUsageStats_FewPkgsHeavyUse() throws IOException {
204         runPutUsageStatsTest(FEW_PKGS, HEAVY_USE);
205     }
206 
207     @Test
testObfuscateStats_FewPkgsHeavyUse()208     public void testObfuscateStats_FewPkgsHeavyUse() {
209         runObfuscateStatsTest(FEW_PKGS, HEAVY_USE);
210     }
211 
212     @Test
testDeobfuscateStats_FewPkgsHeavyUse()213     public void testDeobfuscateStats_FewPkgsHeavyUse() {
214         runDeobfuscateStatsTest(FEW_PKGS, HEAVY_USE);
215     }
216 
217     @Test
testQueryUsageStats_ManyPkgsLightUse()218     public void testQueryUsageStats_ManyPkgsLightUse() throws IOException {
219         runQueryUsageStatsTest(MANY_PKGS, LIGHT_USE);
220     }
221 
222     @Test
testPutUsageStats_ManyPkgsLightUse()223     public void testPutUsageStats_ManyPkgsLightUse() throws IOException {
224         runPutUsageStatsTest(MANY_PKGS, LIGHT_USE);
225     }
226 
227     @Test
testObfuscateStats_ManyPkgsLightUse()228     public void testObfuscateStats_ManyPkgsLightUse() {
229         runObfuscateStatsTest(MANY_PKGS, LIGHT_USE);
230     }
231 
232     @Test
testDeobfuscateStats_ManyPkgsLightUse()233     public void testDeobfuscateStats_ManyPkgsLightUse() {
234         runDeobfuscateStatsTest(MANY_PKGS, LIGHT_USE);
235     }
236 
237     @Test
testQueryUsageStats_ManyPkgsHeavyUse()238     public void testQueryUsageStats_ManyPkgsHeavyUse() throws IOException {
239         runQueryUsageStatsTest(MANY_PKGS, HEAVY_USE);
240     }
241 
242     @Test
testPutUsageStats_ManyPkgsHeavyUse()243     public void testPutUsageStats_ManyPkgsHeavyUse() throws IOException {
244         runPutUsageStatsTest(MANY_PKGS, HEAVY_USE);
245     }
246 
247     @Test
testObfuscateStats_ManyPkgsHeavyUse()248     public void testObfuscateStats_ManyPkgsHeavyUse() {
249         runObfuscateStatsTest(MANY_PKGS, HEAVY_USE);
250     }
251 
252     @Test
testDeobfuscateStats_ManyPkgsHeavyUse()253     public void testDeobfuscateStats_ManyPkgsHeavyUse() {
254         runDeobfuscateStatsTest(MANY_PKGS, HEAVY_USE);
255     }
256 }
257