1/*
2 * Copyright (C) 2017 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.pm;
18
19import android.content.Context;
20import android.content.pm.UserInfo;
21import android.os.FileUtils;
22import android.os.storage.StorageManager;
23import android.os.storage.VolumeInfo;
24import android.platform.test.annotations.Presubmit;
25import android.support.test.InstrumentationRegistry;
26import android.support.test.filters.SmallTest;
27import android.support.test.runner.AndroidJUnit4;
28
29import org.junit.Before;
30import org.junit.Test;
31import org.junit.runner.RunWith;
32import org.mockito.Mock;
33import org.mockito.MockitoAnnotations;
34
35import java.io.File;
36import java.io.FileOutputStream;
37import java.io.IOException;
38import java.nio.charset.Charset;
39import java.util.Arrays;
40import java.util.Collections;
41
42import static org.junit.Assert.assertEquals;
43import static org.mockito.Matchers.eq;
44import static org.mockito.Matchers.isNull;
45import static org.mockito.Mockito.verify;
46import static org.mockito.Mockito.when;
47
48/**
49 * <p>Run with:<pre>
50 * m FrameworksServicesTests &&
51 * adb install \
52 * -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
53 * adb shell am instrument -e class com.android.server.pm.UserDataPreparerTest \
54 * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
55 * </pre>
56 */
57@RunWith(AndroidJUnit4.class)
58@Presubmit
59@SmallTest
60public class UserDataPreparerTest {
61
62    private static final int TEST_USER_SERIAL = 1000;
63    private static final int TEST_USER_ID = 10;
64
65    private TestUserDataPreparer mUserDataPreparer;
66
67    @Mock
68    private StorageManager mStorageManagerMock;
69
70    @Mock
71    private Context mContextMock;
72
73    @Mock
74    private Installer mInstaller;
75
76    private Object mInstallLock;
77
78    @Before
79    public void setup() {
80        Context ctx = InstrumentationRegistry.getContext();
81        FileUtils.deleteContents(ctx.getCacheDir());
82        mInstallLock = new Object();
83        MockitoAnnotations.initMocks(this);
84        mUserDataPreparer = new TestUserDataPreparer(mInstaller, mInstallLock, mContextMock, false,
85                ctx.getCacheDir());
86        when(mContextMock.getSystemServiceName(StorageManager.class))
87                .thenReturn(Context.STORAGE_SERVICE);
88        when(mContextMock.getSystemService(eq(Context.STORAGE_SERVICE)))
89                .thenReturn(mStorageManagerMock);
90        VolumeInfo testVolume = new VolumeInfo("testuuid", VolumeInfo.TYPE_PRIVATE, null, null);
91        when(mStorageManagerMock.getWritablePrivateVolumes()).thenReturn(Arrays.asList(testVolume));
92    }
93
94    @Test
95    public void testPrepareUserData_De() throws Exception {
96        File userDeDir = mUserDataPreparer.getDataUserDeDirectory(null, TEST_USER_ID);
97        userDeDir.mkdirs();
98        File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
99        systemDeDir.mkdirs();
100        mUserDataPreparer
101                .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_DE);
102        verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
103                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
104        verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
105                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_DE));
106        int serialNumber = UserDataPreparer.getSerialNumber(userDeDir);
107        assertEquals(TEST_USER_SERIAL, serialNumber);
108        serialNumber = UserDataPreparer.getSerialNumber(systemDeDir);
109        assertEquals(TEST_USER_SERIAL, serialNumber);
110    }
111
112    @Test
113    public void testPrepareUserData_Ce() throws Exception {
114        File userCeDir = mUserDataPreparer.getDataUserCeDirectory(null, TEST_USER_ID);
115        userCeDir.mkdirs();
116        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
117        systemCeDir.mkdirs();
118        mUserDataPreparer
119                .prepareUserData(TEST_USER_ID, TEST_USER_SERIAL, StorageManager.FLAG_STORAGE_CE);
120        verify(mStorageManagerMock).prepareUserStorage(isNull(String.class), eq(TEST_USER_ID),
121                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
122        verify(mInstaller).createUserData(isNull(String.class), eq(TEST_USER_ID),
123                eq(TEST_USER_SERIAL), eq(StorageManager.FLAG_STORAGE_CE));
124        int serialNumber = UserDataPreparer.getSerialNumber(userCeDir);
125        assertEquals(TEST_USER_SERIAL, serialNumber);
126        serialNumber = UserDataPreparer.getSerialNumber(systemCeDir);
127        assertEquals(TEST_USER_SERIAL, serialNumber);
128    }
129
130    @Test
131    public void testDestroyUserData() throws Exception {
132        // Add file in CE
133        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
134        systemCeDir.mkdirs();
135        File ceFile = new File(systemCeDir, "file");
136        writeFile(ceFile, "-----" );
137        testDestroyUserData_De();
138        // CE directory should be preserved
139        assertEquals(Collections.singletonList(ceFile), Arrays.asList(FileUtils.listFilesOrEmpty(
140                systemCeDir)));
141
142        testDestroyUserData_Ce();
143
144        // Verify that testDir is empty
145        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
146                mUserDataPreparer.testDir)));
147    }
148
149    @Test
150    public void testDestroyUserData_De() throws Exception {
151        File systemDir = mUserDataPreparer.getUserSystemDirectory(TEST_USER_ID);
152        systemDir.mkdirs();
153        writeFile(new File(systemDir, "file"), "-----" );
154        File systemDeDir = mUserDataPreparer.getDataSystemDeDirectory(TEST_USER_ID);
155        systemDeDir.mkdirs();
156        writeFile(new File(systemDeDir, "file"), "-----" );
157        File miscDeDir = mUserDataPreparer.getDataMiscDeDirectory(TEST_USER_ID);
158        miscDeDir.mkdirs();
159        writeFile(new File(miscDeDir, "file"), "-----" );
160
161        mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_DE);
162
163        verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
164                        eq(StorageManager.FLAG_STORAGE_DE));
165        verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
166                        eq(StorageManager.FLAG_STORAGE_DE));
167
168        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(systemDir)));
169        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
170                systemDeDir)));
171        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
172                miscDeDir)));
173    }
174
175    @Test
176    public void testDestroyUserData_Ce() throws Exception {
177        File systemCeDir = mUserDataPreparer.getDataSystemCeDirectory(TEST_USER_ID);
178        systemCeDir.mkdirs();
179        writeFile(new File(systemCeDir, "file"), "-----" );
180        File miscCeDir = mUserDataPreparer.getDataMiscCeDirectory(TEST_USER_ID);
181        miscCeDir.mkdirs();
182        writeFile(new File(miscCeDir, "file"), "-----" );
183
184        mUserDataPreparer.destroyUserData(TEST_USER_ID, StorageManager.FLAG_STORAGE_CE);
185
186        verify(mInstaller).destroyUserData(isNull(String.class), eq(TEST_USER_ID),
187                eq(StorageManager.FLAG_STORAGE_CE));
188        verify(mStorageManagerMock).destroyUserStorage(isNull(String.class), eq(TEST_USER_ID),
189                eq(StorageManager.FLAG_STORAGE_CE));
190
191        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
192                systemCeDir)));
193        assertEquals(Collections.emptyList(), Arrays.asList(FileUtils.listFilesOrEmpty(
194                miscCeDir)));
195    }
196
197    @Test
198    public void testReconcileUsers() throws Exception {
199        UserInfo u1 = new UserInfo(1, "u1", 0);
200        UserInfo u2 = new UserInfo(2, "u2", 0);
201        File testDir = mUserDataPreparer.testDir;
202        File dir1 = new File(testDir, "1");
203        dir1.mkdirs();
204        File dir2 = new File(testDir, "2");
205        dir2.mkdirs();
206        File dir3 = new File(testDir, "3");
207        dir3.mkdirs();
208
209        mUserDataPreparer
210                .reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL, Arrays.asList(u1, u2),
211                        Arrays.asList(dir1, dir2, dir3));
212        // Verify that user 3 data is removed
213        verify(mInstaller).destroyUserData(isNull(String.class), eq(3),
214                eq(StorageManager.FLAG_STORAGE_DE|StorageManager.FLAG_STORAGE_CE));
215    }
216
217    private static void writeFile(File file, String content) throws IOException {
218        try (FileOutputStream os = new FileOutputStream(file)) {
219            os.write(content.getBytes(Charset.defaultCharset()));
220        }
221    }
222
223    private static class TestUserDataPreparer extends UserDataPreparer {
224        File testDir;
225
226        TestUserDataPreparer(Installer installer, Object installLock, Context context,
227                boolean onlyCore, File testDir) {
228            super(installer, installLock, context, onlyCore);
229            this.testDir = testDir;
230        }
231
232        @Override
233        protected File getDataMiscCeDirectory(int userId) {
234            return new File(testDir, "misc_ce_" + userId);
235        }
236
237        @Override
238        protected File getDataSystemCeDirectory(int userId) {
239            return new File(testDir, "system_ce_" + userId);
240        }
241
242        @Override
243        protected File getDataMiscDeDirectory(int userId) {
244            return new File(testDir, "misc_de_" + userId);
245        }
246
247        @Override
248        protected File getUserSystemDirectory(int userId) {
249            return new File(testDir, "user_system_" + userId);
250        }
251
252        @Override
253        protected File getDataUserCeDirectory(String volumeUuid, int userId) {
254            return new File(testDir, "user_ce_" + userId);
255        }
256
257        @Override
258        protected File getDataSystemDeDirectory(int userId) {
259            return new File(testDir, "system_de_" + userId);
260        }
261
262        @Override
263        protected File getDataUserDeDirectory(String volumeUuid, int userId) {
264            return new File(testDir, "user_de_" + userId);
265        }
266
267        @Override
268        protected boolean isFileEncryptedEmulatedOnly() {
269            return false;
270        }
271    }
272
273}
274