blob: 375edf3cb5aeb2e1e73fc658ed1dd80ce030d3d0 [file] [log] [blame]
Daniel Nishi090b2d92016-12-13 10:38:42 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.storage;
18
19import static com.google.common.truth.Truth.assertThat;
20
Daniel Nishicf76a162016-12-22 11:06:51 -080021import static org.mockito.Matchers.any;
Daniel Nishi090b2d92016-12-13 10:38:42 -080022import static org.mockito.Matchers.anyInt;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070023import static org.mockito.Matchers.anyLong;
24import static org.mockito.Matchers.anyString;
25import static org.mockito.Matchers.isNull;
26import static org.mockito.Mockito.doReturn;
Daniel Nishi3cf3b192017-04-13 20:04:43 +000027import static org.mockito.Mockito.mock;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070028import static org.mockito.Mockito.spy;
Daniel Nishi090b2d92016-12-13 10:38:42 -080029import static org.mockito.Mockito.when;
30
Daniel Nishicf76a162016-12-22 11:06:51 -080031import android.app.job.JobService;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070032import android.app.job.JobServiceEngine;
33import android.app.usage.ExternalStorageStats;
34import android.app.usage.StorageStatsManager;
35import android.content.Context;
36import android.content.pm.PackageManager;
Daniel Nishi090b2d92016-12-13 10:38:42 -080037import android.content.pm.PackageStats;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070038import android.os.BatteryManager;
39import android.os.UserHandle;
40import android.os.UserManager;
41import android.os.storage.StorageManager;
42import android.os.storage.VolumeInfo;
43import android.provider.Settings;
Daniel Nishi090b2d92016-12-13 10:38:42 -080044import android.test.AndroidTestCase;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070045import android.test.mock.MockContentResolver;
Daniel Nishi090b2d92016-12-13 10:38:42 -080046
Daniel Nishi5d230dc2017-04-10 11:21:26 -070047import com.android.internal.util.test.FakeSettingsProvider;
Daniel Nishi090b2d92016-12-13 10:38:42 -080048import com.android.server.storage.DiskStatsLoggingService.LogRunnable;
49
50import libcore.io.IoUtils;
51
52import org.json.JSONObject;
53import org.junit.Before;
54import org.junit.Rule;
55import org.junit.Test;
56import org.junit.rules.TemporaryFolder;
57import org.junit.runner.RunWith;
58import org.junit.runners.JUnit4;
59import org.mockito.Mock;
60import org.mockito.MockitoAnnotations;
61
62import java.io.File;
63import java.io.PrintStream;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070064import java.lang.reflect.Field;
Daniel Nishi090b2d92016-12-13 10:38:42 -080065import java.util.ArrayList;
66
67@RunWith(JUnit4.class)
68public class DiskStatsLoggingServiceTest extends AndroidTestCase {
69 @Rule public TemporaryFolder mTemporaryFolder;
70 @Rule public TemporaryFolder mDownloads;
Daniel Nishi090b2d92016-12-13 10:38:42 -080071 @Mock private AppCollector mCollector;
Daniel Nishi5d230dc2017-04-10 11:21:26 -070072 @Mock private JobService mJobService;
73 @Mock private StorageStatsManager mSsm;
74 private ExternalStorageStats mStorageStats;
Daniel Nishi090b2d92016-12-13 10:38:42 -080075 private File mInputFile;
76
77
78 @Before
79 public void setUp() throws Exception {
80 super.setUp();
81 MockitoAnnotations.initMocks(this);
82 mTemporaryFolder = new TemporaryFolder();
83 mTemporaryFolder.create();
84 mInputFile = mTemporaryFolder.newFile();
85 mDownloads = new TemporaryFolder();
86 mDownloads.create();
Daniel Nishi5d230dc2017-04-10 11:21:26 -070087 mStorageStats = new ExternalStorageStats();
88 when(mSsm.queryExternalStatsForUser(isNull(String.class), any(UserHandle.class)))
89 .thenReturn(mStorageStats);
90 when(mJobService.getSystemService(anyString())).thenReturn(mSsm);
Daniel Nishi090b2d92016-12-13 10:38:42 -080091 }
92
93 @Test
94 public void testEmptyLog() throws Exception {
95 LogRunnable task = new LogRunnable();
96 task.setAppCollector(mCollector);
97 task.setDownloadsDirectory(mDownloads.getRoot());
Daniel Nishi090b2d92016-12-13 10:38:42 -080098 task.setLogOutputFile(mInputFile);
99 task.setSystemSize(0L);
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700100 task.setContext(mJobService);
Daniel Nishi090b2d92016-12-13 10:38:42 -0800101 task.run();
102
103 JSONObject json = getJsonOutput();
104 assertThat(json.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(0L);
105 assertThat(json.getLong(DiskStatsFileLogger.VIDEOS_KEY)).isEqualTo(0L);
106 assertThat(json.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(0L);
107 assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(0L);
108 assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(0L);
109 assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(0L);
110 assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(0L);
111 assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(0L);
112 assertThat(
113 json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(0L);
114 assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(0L);
115 assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(0L);
116 }
117
118 @Test
119 public void testPopulatedLogTask() throws Exception {
120 // Write data to directories.
121 writeDataToFile(mDownloads.newFile(), "lol");
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700122 mStorageStats.audioBytes = 6L;
123 mStorageStats.imageBytes = 4L;
124 mStorageStats.videoBytes = 5L;
125 mStorageStats.totalBytes = 22L;
Daniel Nishi090b2d92016-12-13 10:38:42 -0800126
127 // Write apps.
128 ArrayList<PackageStats> apps = new ArrayList<>();
129 PackageStats testApp = new PackageStats("com.test.app");
130 testApp.dataSize = 5L;
131 testApp.cacheSize = 55L;
132 testApp.codeSize = 10L;
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700133 testApp.userHandle = UserHandle.USER_SYSTEM;
Daniel Nishi090b2d92016-12-13 10:38:42 -0800134 apps.add(testApp);
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700135 when(mCollector.getPackageStats(anyLong())).thenReturn(apps);
Daniel Nishi090b2d92016-12-13 10:38:42 -0800136
137 LogRunnable task = new LogRunnable();
138 task.setAppCollector(mCollector);
139 task.setDownloadsDirectory(mDownloads.getRoot());
Daniel Nishi090b2d92016-12-13 10:38:42 -0800140 task.setLogOutputFile(mInputFile);
141 task.setSystemSize(10L);
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700142 task.setContext(mJobService);
Daniel Nishi090b2d92016-12-13 10:38:42 -0800143 task.run();
144
145 JSONObject json = getJsonOutput();
146 assertThat(json.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(4L);
147 assertThat(json.getLong(DiskStatsFileLogger.VIDEOS_KEY)).isEqualTo(5L);
148 assertThat(json.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(6L);
149 assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(3L);
150 assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(10L);
151 assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(7L);
152 assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(15L);
153 assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(55L);
154 assertThat(
155 json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(1L);
156 assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(1L);
157 assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(1L);
158 }
159
Daniel Nishicf76a162016-12-22 11:06:51 -0800160 @Test
161 public void testDontCrashOnPackageStatsTimeout() throws Exception {
162 when(mCollector.getPackageStats(anyInt())).thenReturn(null);
163
164 LogRunnable task = new LogRunnable();
165 task.setAppCollector(mCollector);
166 task.setDownloadsDirectory(mDownloads.getRoot());
Daniel Nishicf76a162016-12-22 11:06:51 -0800167 task.setLogOutputFile(mInputFile);
168 task.setSystemSize(10L);
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700169 task.setContext(mJobService);
Daniel Nishicf76a162016-12-22 11:06:51 -0800170 task.run();
171
172 // No exception should be thrown.
173 }
174
Daniel Nishi5d230dc2017-04-10 11:21:26 -0700175 @Test
176 public void testDontCrashOnRun() throws Exception {
177 DiskStatsLoggingService service = spy(new DiskStatsLoggingService());
178 BatteryManager batteryManager = mock(BatteryManager.class);
179 when(batteryManager.isCharging()).thenReturn(true);
180 doReturn(batteryManager).when(service).getSystemService(Context.BATTERY_SERVICE);
181 UserManager userManager = mock(UserManager.class);
182 when(userManager.getUsers()).thenReturn(new ArrayList<>());
183 doReturn(userManager).when(service).getSystemService(Context.USER_SERVICE);
184 doReturn(mSsm).when(service).getSystemService(Context.STORAGE_STATS_SERVICE);
185 doReturn(mock(StorageManager.class))
186 .when(service)
187 .getSystemService(Context.STORAGE_SERVICE);
188
189 MockContentResolver cr = new MockContentResolver();
190 cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
191 doReturn(cr).when(service).getContentResolver();
192
193 PackageManager pm = mock(PackageManager.class);
194 VolumeInfo volumeInfo =
195 new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, VolumeInfo.TYPE_PRIVATE, null, null);
196 when(pm.getPrimaryStorageCurrentVolume()).thenReturn(volumeInfo);
197 doReturn(pm).when(service).getPackageManager();
198
199 doReturn(0).when(service).getUserId();
200
201 // UGGGGGHHHHHHH! jobFinished is a final method on JobService which crashes when called if
202 // the JobService isn't initialized for real. ServiceTestCase doesn't let us initialize a
203 // service which is built into the framework without crashing, though, so we can't make a
204 // real initialized service.
205 //
206 // And so, we use reflection to set the JobServiceEngine, which is used by the final method,
207 // to be something which won't crash when called.
208 final Field field = JobService.class.getDeclaredField("mEngine");
209 field.setAccessible(true);
210 field.set(service, mock(JobServiceEngine.class));
211
212 // Note: This won't clobber your on-device cache file because, technically,
213 // FrameworkServicesTests don't have write permission to actually overwrite the cache file.
214 // We log and fail on the write silently in this case.
215 service.onStartJob(null);
216 }
217
Daniel Nishi090b2d92016-12-13 10:38:42 -0800218 private void writeDataToFile(File f, String data) throws Exception{
219 PrintStream out = new PrintStream(f);
220 out.print(data);
221 out.close();
222 }
223
224 private JSONObject getJsonOutput() throws Exception {
225 return new JSONObject(IoUtils.readFileAsString(mInputFile.getAbsolutePath()));
226 }
227}