1090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi/*
2090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * Copyright (C) 2016 The Android Open Source Project
3090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi *
4090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * Licensed under the Apache License, Version 2.0 (the "License");
5090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * you may not use this file except in compliance with the License.
6090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * You may obtain a copy of the License at
7090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi *
8090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi *      http://www.apache.org/licenses/LICENSE-2.0
9090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi *
10090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * Unless required by applicable law or agreed to in writing, software
11090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * distributed under the License is distributed on an "AS IS" BASIS,
12090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * See the License for the specific language governing permissions and
14090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi * limitations under the License.
15090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi */
16090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
17090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishipackage com.android.server.storage;
18090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
19090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport static com.google.common.truth.Truth.assertThat;
20090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
21cf76a16e660a361670745b043198b797ccd86747Daniel Nishiimport static org.mockito.Matchers.any;
22090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport static org.mockito.Matchers.anyInt;
235d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport static org.mockito.Matchers.anyLong;
245d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport static org.mockito.Matchers.anyString;
255d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport static org.mockito.Matchers.isNull;
265d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport static org.mockito.Mockito.doReturn;
273cf3b199e3e120f23f54eb7f9905c8d285cb8a28Daniel Nishiimport static org.mockito.Mockito.mock;
285d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport static org.mockito.Mockito.spy;
29090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport static org.mockito.Mockito.when;
30090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
31cf76a16e660a361670745b043198b797ccd86747Daniel Nishiimport android.app.job.JobService;
325d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.app.job.JobServiceEngine;
335d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.app.usage.ExternalStorageStats;
345d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.app.usage.StorageStatsManager;
355d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.content.Context;
365d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.content.pm.PackageManager;
37090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport android.content.pm.PackageStats;
385d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.os.BatteryManager;
395d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.os.UserHandle;
405d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.os.UserManager;
415d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.os.storage.StorageManager;
425d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.os.storage.VolumeInfo;
435d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.provider.Settings;
44090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport android.test.AndroidTestCase;
455d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport android.test.mock.MockContentResolver;
46090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
475d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport com.android.internal.util.test.FakeSettingsProvider;
48090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport com.android.server.storage.DiskStatsLoggingService.LogRunnable;
49090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
50090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport libcore.io.IoUtils;
51090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
52090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.json.JSONObject;
53090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.Before;
54090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.Rule;
55090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.Test;
56090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.rules.TemporaryFolder;
57090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.runner.RunWith;
58090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.junit.runners.JUnit4;
59090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.mockito.Mock;
60090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport org.mockito.MockitoAnnotations;
61090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
62090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport java.io.File;
63090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport java.io.PrintStream;
645d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishiimport java.lang.reflect.Field;
65090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishiimport java.util.ArrayList;
66090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
67090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi@RunWith(JUnit4.class)
68090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishipublic class DiskStatsLoggingServiceTest extends AndroidTestCase {
69090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Rule public TemporaryFolder mTemporaryFolder;
70090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Rule public TemporaryFolder mDownloads;
71090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Mock private AppCollector mCollector;
725d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    @Mock private JobService mJobService;
735d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    @Mock private StorageStatsManager mSsm;
745d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    private ExternalStorageStats mStorageStats;
75090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    private File mInputFile;
76090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
77090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
78090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Before
79090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    public void setUp() throws Exception {
80090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        super.setUp();
81090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        MockitoAnnotations.initMocks(this);
82090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        mTemporaryFolder = new TemporaryFolder();
83090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        mTemporaryFolder.create();
84090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        mInputFile = mTemporaryFolder.newFile();
85090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        mDownloads = new TemporaryFolder();
86090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        mDownloads.create();
875d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        mStorageStats = new ExternalStorageStats();
885d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(mSsm.queryExternalStatsForUser(isNull(String.class), any(UserHandle.class)))
895d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi                .thenReturn(mStorageStats);
905d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(mJobService.getSystemService(anyString())).thenReturn(mSsm);
91090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    }
92090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
93090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Test
94090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    public void testEmptyLog() throws Exception {
95090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        LogRunnable task = new LogRunnable();
96090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setAppCollector(mCollector);
97090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setDownloadsDirectory(mDownloads.getRoot());
98090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setLogOutputFile(mInputFile);
99090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setSystemSize(0L);
1005d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        task.setContext(mJobService);
101090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.run();
102090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
103090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        JSONObject json = getJsonOutput();
104090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(0L);
105090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.VIDEOS_KEY)).isEqualTo(0L);
106090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(0L);
107090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(0L);
108090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(0L);
109090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(0L);
110090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(0L);
111090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(0L);
112090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(
113090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi                json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(0L);
114090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(0L);
115090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(0L);
116090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    }
117090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
118090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    @Test
119090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    public void testPopulatedLogTask() throws Exception {
120090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        // Write data to directories.
121090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        writeDataToFile(mDownloads.newFile(), "lol");
1225d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        mStorageStats.audioBytes = 6L;
1235d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        mStorageStats.imageBytes = 4L;
1245d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        mStorageStats.videoBytes = 5L;
1255d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        mStorageStats.totalBytes = 22L;
126090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
127090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        // Write apps.
128090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        ArrayList<PackageStats> apps = new ArrayList<>();
129090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        PackageStats testApp = new PackageStats("com.test.app");
130090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        testApp.dataSize = 5L;
131090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        testApp.cacheSize = 55L;
132090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        testApp.codeSize = 10L;
1335d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        testApp.userHandle = UserHandle.USER_SYSTEM;
134090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        apps.add(testApp);
1355d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(mCollector.getPackageStats(anyLong())).thenReturn(apps);
136090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
137090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        LogRunnable task = new LogRunnable();
138090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setAppCollector(mCollector);
139090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setDownloadsDirectory(mDownloads.getRoot());
140090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setLogOutputFile(mInputFile);
141090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.setSystemSize(10L);
1425d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        task.setContext(mJobService);
143090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        task.run();
144090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
145090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        JSONObject json = getJsonOutput();
146090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(4L);
147090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.VIDEOS_KEY)).isEqualTo(5L);
148090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(6L);
149090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(3L);
150090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(10L);
151090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(7L);
152b6cc838142d2390eaec99670bb6caf6bee0ec96fDaniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(10L);
153b6cc838142d2390eaec99670bb6caf6bee0ec96fDaniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)).isEqualTo(5L);
154090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(55L);
155090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(
156090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi                json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(1L);
157090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(1L);
158b6cc838142d2390eaec99670bb6caf6bee0ec96fDaniel Nishi        assertThat(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY).length()).isEqualTo(1L);
159090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(1L);
160090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    }
161090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
162cf76a16e660a361670745b043198b797ccd86747Daniel Nishi    @Test
163cf76a16e660a361670745b043198b797ccd86747Daniel Nishi    public void testDontCrashOnPackageStatsTimeout() throws Exception {
164cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        when(mCollector.getPackageStats(anyInt())).thenReturn(null);
165cf76a16e660a361670745b043198b797ccd86747Daniel Nishi
166cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        LogRunnable task = new LogRunnable();
167cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        task.setAppCollector(mCollector);
168cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        task.setDownloadsDirectory(mDownloads.getRoot());
169cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        task.setLogOutputFile(mInputFile);
170cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        task.setSystemSize(10L);
1715d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        task.setContext(mJobService);
172cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        task.run();
173cf76a16e660a361670745b043198b797ccd86747Daniel Nishi
174cf76a16e660a361670745b043198b797ccd86747Daniel Nishi        // No exception should be thrown.
175cf76a16e660a361670745b043198b797ccd86747Daniel Nishi    }
176cf76a16e660a361670745b043198b797ccd86747Daniel Nishi
1775d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    @Test
1785d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    public void testDontCrashOnRun() throws Exception {
1795d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        DiskStatsLoggingService service = spy(new DiskStatsLoggingService());
1805d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        BatteryManager batteryManager = mock(BatteryManager.class);
1815d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(batteryManager.isCharging()).thenReturn(true);
1825d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(batteryManager).when(service).getSystemService(Context.BATTERY_SERVICE);
1835d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        UserManager userManager = mock(UserManager.class);
1845d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(userManager.getUsers()).thenReturn(new ArrayList<>());
1855d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(userManager).when(service).getSystemService(Context.USER_SERVICE);
1865d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(mSsm).when(service).getSystemService(Context.STORAGE_STATS_SERVICE);
1875d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(mock(StorageManager.class))
1885d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi                .when(service)
1895d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi                .getSystemService(Context.STORAGE_SERVICE);
1905d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
1915d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        MockContentResolver cr = new MockContentResolver();
1925d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
1935d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(cr).when(service).getContentResolver();
1945d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
1955d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        PackageManager pm = mock(PackageManager.class);
1965d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        VolumeInfo volumeInfo =
1975d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi                new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL, VolumeInfo.TYPE_PRIVATE, null, null);
1985d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        when(pm.getPrimaryStorageCurrentVolume()).thenReturn(volumeInfo);
1995d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(pm).when(service).getPackageManager();
2005d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
2015d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        doReturn(0).when(service).getUserId();
2025d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
2035d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // UGGGGGHHHHHHH! jobFinished is a final method on JobService which crashes when called if
2045d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // the JobService isn't initialized for real. ServiceTestCase doesn't let us initialize a
2055d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // service which is built into the framework without crashing, though, so we can't make a
2065d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // real initialized service.
2075d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        //
2085d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // And so, we use reflection to set the JobServiceEngine, which is used by the final method,
2095d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // to be something which won't crash when called.
2105d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        final Field field = JobService.class.getDeclaredField("mEngine");
2115d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        field.setAccessible(true);
2125d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        field.set(service, mock(JobServiceEngine.class));
2135d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
2145d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // Note: This won't clobber your on-device cache file because, technically,
2155d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // FrameworkServicesTests don't have write permission to actually overwrite the cache file.
2165d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        // We log and fail on the write silently in this case.
2175d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi        service.onStartJob(null);
2185d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi    }
2195d230dc202cb03185652e12b3024ceea1132dd4dDaniel Nishi
220090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    private void writeDataToFile(File f, String data) throws Exception{
221090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        PrintStream out = new PrintStream(f);
222090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        out.print(data);
223090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        out.close();
224090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    }
225090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi
226090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    private JSONObject getJsonOutput() throws Exception {
227090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi        return new JSONObject(IoUtils.readFileAsString(mInputFile.getAbsolutePath()));
228090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi    }
229090b2d9d6c73ad1b92fd6374aaaa26a384333239Daniel Nishi}
230