Home | History | Annotate | Download | only in storage
      1 /*
      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 
     17 package com.android.server.storage;
     18 
     19 import static com.google.common.truth.Truth.assertThat;
     20 
     21 import static org.mockito.Matchers.any;
     22 import static org.mockito.Matchers.anyInt;
     23 import static org.mockito.Matchers.anyLong;
     24 import static org.mockito.Matchers.anyString;
     25 import static org.mockito.Matchers.isNull;
     26 import static org.mockito.Mockito.doReturn;
     27 import static org.mockito.Mockito.mock;
     28 import static org.mockito.Mockito.spy;
     29 import static org.mockito.Mockito.when;
     30 
     31 import android.app.job.JobService;
     32 import android.app.job.JobServiceEngine;
     33 import android.app.usage.ExternalStorageStats;
     34 import android.app.usage.StorageStatsManager;
     35 import android.content.Context;
     36 import android.content.pm.PackageManager;
     37 import android.content.pm.PackageStats;
     38 import android.os.BatteryManager;
     39 import android.os.UserHandle;
     40 import android.os.UserManager;
     41 import android.os.storage.StorageManager;
     42 import android.os.storage.VolumeInfo;
     43 import android.provider.Settings;
     44 import android.test.AndroidTestCase;
     45 import android.test.mock.MockContentResolver;
     46 
     47 import com.android.internal.util.test.FakeSettingsProvider;
     48 import com.android.server.storage.DiskStatsLoggingService.LogRunnable;
     49 
     50 import libcore.io.IoUtils;
     51 
     52 import org.json.JSONObject;
     53 import org.junit.Before;
     54 import org.junit.Rule;
     55 import org.junit.Test;
     56 import org.junit.rules.TemporaryFolder;
     57 import org.junit.runner.RunWith;
     58 import org.junit.runners.JUnit4;
     59 import org.mockito.Mock;
     60 import org.mockito.MockitoAnnotations;
     61 
     62 import java.io.File;
     63 import java.io.PrintStream;
     64 import java.lang.reflect.Field;
     65 import java.util.ArrayList;
     66 
     67 @RunWith(JUnit4.class)
     68 public class DiskStatsLoggingServiceTest extends AndroidTestCase {
     69     @Rule public TemporaryFolder mTemporaryFolder;
     70     @Rule public TemporaryFolder mDownloads;
     71     @Mock private AppCollector mCollector;
     72     @Mock private JobService mJobService;
     73     @Mock private StorageStatsManager mSsm;
     74     private ExternalStorageStats mStorageStats;
     75     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();
     87         mStorageStats = new ExternalStorageStats();
     88         when(mSsm.queryExternalStatsForUser(isNull(String.class), any(UserHandle.class)))
     89                 .thenReturn(mStorageStats);
     90         when(mJobService.getSystemService(anyString())).thenReturn(mSsm);
     91     }
     92 
     93     @Test
     94     public void testEmptyLog() throws Exception {
     95         LogRunnable task = new LogRunnable();
     96         task.setAppCollector(mCollector);
     97         task.setDownloadsDirectory(mDownloads.getRoot());
     98         task.setLogOutputFile(mInputFile);
     99         task.setSystemSize(0L);
    100         task.setContext(mJobService);
    101         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");
    122         mStorageStats.audioBytes = 6L;
    123         mStorageStats.imageBytes = 4L;
    124         mStorageStats.videoBytes = 5L;
    125         mStorageStats.totalBytes = 22L;
    126 
    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;
    133         testApp.userHandle = UserHandle.USER_SYSTEM;
    134         apps.add(testApp);
    135         when(mCollector.getPackageStats(anyLong())).thenReturn(apps);
    136 
    137         LogRunnable task = new LogRunnable();
    138         task.setAppCollector(mCollector);
    139         task.setDownloadsDirectory(mDownloads.getRoot());
    140         task.setLogOutputFile(mInputFile);
    141         task.setSystemSize(10L);
    142         task.setContext(mJobService);
    143         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(10L);
    153         assertThat(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)).isEqualTo(5L);
    154         assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(55L);
    155         assertThat(
    156                 json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(1L);
    157         assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(1L);
    158         assertThat(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY).length()).isEqualTo(1L);
    159         assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(1L);
    160     }
    161 
    162     @Test
    163     public void testDontCrashOnPackageStatsTimeout() throws Exception {
    164         when(mCollector.getPackageStats(anyInt())).thenReturn(null);
    165 
    166         LogRunnable task = new LogRunnable();
    167         task.setAppCollector(mCollector);
    168         task.setDownloadsDirectory(mDownloads.getRoot());
    169         task.setLogOutputFile(mInputFile);
    170         task.setSystemSize(10L);
    171         task.setContext(mJobService);
    172         task.run();
    173 
    174         // No exception should be thrown.
    175     }
    176 
    177     @Test
    178     public void testDontCrashOnRun() throws Exception {
    179         DiskStatsLoggingService service = spy(new DiskStatsLoggingService());
    180         BatteryManager batteryManager = mock(BatteryManager.class);
    181         when(batteryManager.isCharging()).thenReturn(true);
    182         doReturn(batteryManager).when(service).getSystemService(Context.BATTERY_SERVICE);
    183         UserManager userManager = mock(UserManager.class);
    184         when(userManager.getUsers()).thenReturn(new ArrayList<>());
    185         doReturn(userManager).when(service).getSystemService(Context.USER_SERVICE);
    186         doReturn(mSsm).when(service).getSystemService(Context.STORAGE_STATS_SERVICE);
    187         doReturn(mock(StorageManager.class))
    188                 .when(service)
    189                 .getSystemService(Context.STORAGE_SERVICE);
    190 
    191         MockContentResolver cr = new MockContentResolver();
    192         cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
    193         doReturn(cr).when(service).getContentResolver();
    194 
    195         PackageManager pm = mock(PackageManager.class);
    196         VolumeInfo volumeInfo =
    197                 new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, VolumeInfo.TYPE_PRIVATE, null, null);
    198         when(pm.getPrimaryStorageCurrentVolume()).thenReturn(volumeInfo);
    199         doReturn(pm).when(service).getPackageManager();
    200 
    201         doReturn(0).when(service).getUserId();
    202 
    203         // UGGGGGHHHHHHH! jobFinished is a final method on JobService which crashes when called if
    204         // the JobService isn't initialized for real. ServiceTestCase doesn't let us initialize a
    205         // service which is built into the framework without crashing, though, so we can't make a
    206         // real initialized service.
    207         //
    208         // And so, we use reflection to set the JobServiceEngine, which is used by the final method,
    209         // to be something which won't crash when called.
    210         final Field field = JobService.class.getDeclaredField("mEngine");
    211         field.setAccessible(true);
    212         field.set(service, mock(JobServiceEngine.class));
    213 
    214         // Note: This won't clobber your on-device cache file because, technically,
    215         // FrameworkServicesTests don't have write permission to actually overwrite the cache file.
    216         // We log and fail on the write silently in this case.
    217         service.onStartJob(null);
    218     }
    219 
    220     private void writeDataToFile(File f, String data) throws Exception{
    221         PrintStream out = new PrintStream(f);
    222         out.print(data);
    223         out.close();
    224     }
    225 
    226     private JSONObject getJsonOutput() throws Exception {
    227         return new JSONObject(IoUtils.readFileAsString(mInputFile.getAbsolutePath()));
    228     }
    229 }
    230