blob: f871203728c046de65202631de5d066b8c3b413e [file] [log] [blame]
Narayan Kamathc034fe92019-01-23 10:48:17 +00001/*
2 * Copyright (C) 2019 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.rollback;
18
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000019import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertNull;
22import static org.junit.Assert.assertTrue;
Narayan Kamathc034fe92019-01-23 10:48:17 +000023import static org.mockito.ArgumentMatchers.eq;
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000024import static org.mockito.Matchers.anyInt;
25import static org.mockito.Matchers.anyString;
Narayan Kamathc034fe92019-01-23 10:48:17 +000026import static org.mockito.Mockito.doReturn;
27import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.spy;
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000029import static org.mockito.Mockito.when;
Narayan Kamathc034fe92019-01-23 10:48:17 +000030
31import android.content.pm.VersionedPackage;
32import android.content.rollback.PackageRollbackInfo;
33import android.content.rollback.PackageRollbackInfo.RestoreInfo;
34import android.util.IntArray;
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000035import android.util.SparseLongArray;
Narayan Kamathc034fe92019-01-23 10:48:17 +000036
37import com.android.server.pm.Installer;
38
39import org.junit.Test;
40import org.junit.runner.RunWith;
41import org.junit.runners.JUnit4;
42import org.mockito.InOrder;
43import org.mockito.Mockito;
44
45import java.io.File;
46import java.util.ArrayList;
47
48@RunWith(JUnit4.class)
49public class AppDataRollbackHelperTest {
50
51 @Test
52 public void testSnapshotAppData() throws Exception {
53 Installer installer = mock(Installer.class);
54 AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
55
56 // All users are unlocked so we should snapshot data for them.
57 doReturn(true).when(helper).isUserCredentialLocked(eq(10));
58 doReturn(true).when(helper).isUserCredentialLocked(eq(11));
Oli Lan48f3cf42019-08-09 10:25:49 +010059 PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
60 helper.snapshotAppData(5, info, new int[]{10, 11});
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000061
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000062 assertEquals(2, info.getPendingBackups().size());
63 assertEquals(10, info.getPendingBackups().get(0));
64 assertEquals(11, info.getPendingBackups().get(1));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000065
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000066 assertEquals(0, info.getCeSnapshotInodes().size());
Narayan Kamathc034fe92019-01-23 10:48:17 +000067
68 InOrder inOrder = Mockito.inOrder(installer);
69 inOrder.verify(installer).snapshotAppData(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000070 eq("com.foo.bar"), eq(10), eq(5), eq(Installer.FLAG_STORAGE_DE));
Narayan Kamathc034fe92019-01-23 10:48:17 +000071 inOrder.verify(installer).snapshotAppData(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000072 eq("com.foo.bar"), eq(11), eq(5), eq(Installer.FLAG_STORAGE_DE));
Narayan Kamathc034fe92019-01-23 10:48:17 +000073 inOrder.verifyNoMoreInteractions();
74
75 // One of the users is unlocked but the other isn't
76 doReturn(false).when(helper).isUserCredentialLocked(eq(10));
77 doReturn(true).when(helper).isUserCredentialLocked(eq(11));
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000078 when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(239L);
Narayan Kamathc034fe92019-01-23 10:48:17 +000079
Oli Lan48f3cf42019-08-09 10:25:49 +010080 PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar");
81 helper.snapshotAppData(7, info2, new int[]{10, 11});
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000082 assertEquals(1, info2.getPendingBackups().size());
83 assertEquals(11, info2.getPendingBackups().get(0));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +000084
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000085 assertEquals(1, info2.getCeSnapshotInodes().size());
86 assertEquals(239L, info2.getCeSnapshotInodes().get(10));
Narayan Kamathc034fe92019-01-23 10:48:17 +000087
88 inOrder = Mockito.inOrder(installer);
89 inOrder.verify(installer).snapshotAppData(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000090 eq("com.foo.bar"), eq(10), eq(7),
Narayan Kamathc034fe92019-01-23 10:48:17 +000091 eq(Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE));
92 inOrder.verify(installer).snapshotAppData(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000093 eq("com.foo.bar"), eq(11), eq(7), eq(Installer.FLAG_STORAGE_DE));
Narayan Kamathc034fe92019-01-23 10:48:17 +000094 inOrder.verifyNoMoreInteractions();
95 }
96
Nikita Ioffe5dcd17972019-02-04 11:08:13 +000097 private static PackageRollbackInfo createPackageRollbackInfo(String packageName,
98 final int[] installedUsers) {
99 return new PackageRollbackInfo(
100 new VersionedPackage(packageName, 2), new VersionedPackage(packageName, 1),
Mohammad Samiul Islam3fcecfc2019-12-20 17:46:01 +0000101 new IntArray(), new ArrayList<>(), false, false, IntArray.wrap(installedUsers),
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000102 new SparseLongArray());
Narayan Kamathc034fe92019-01-23 10:48:17 +0000103 }
104
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000105 private static PackageRollbackInfo createPackageRollbackInfo(String packageName) {
106 return createPackageRollbackInfo(packageName, new int[] {});
Narayan Kamathc034fe92019-01-23 10:48:17 +0000107 }
108
Gavin Corkery0987cb02019-10-07 10:46:55 +0100109 private static Rollback createRollbackForId(int rollbackId) {
110 return new Rollback(rollbackId, new File("/does/not/exist"), -1,
111 0, "com.xyz");
112 }
113
Narayan Kamathc034fe92019-01-23 10:48:17 +0000114 @Test
115 public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception {
116 Installer installer = mock(Installer.class);
117 AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
118
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000119 PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
120 IntArray pendingBackups = info.getPendingBackups();
Narayan Kamathc034fe92019-01-23 10:48:17 +0000121 pendingBackups.add(10);
122 pendingBackups.add(11);
123
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000124 assertTrue(helper.restoreAppData(13 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
125 "seinfo"));
Narayan Kamathc034fe92019-01-23 10:48:17 +0000126
127 // Should only require FLAG_STORAGE_DE here because we have a pending backup that we
128 // didn't manage to execute.
129 InOrder inOrder = Mockito.inOrder(installer);
130 inOrder.verify(installer).restoreAppDataSnapshot(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000131 eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
132 eq(13) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
Narayan Kamathc034fe92019-01-23 10:48:17 +0000133 inOrder.verifyNoMoreInteractions();
134
135 assertEquals(1, pendingBackups.size());
136 assertEquals(11, pendingBackups.get(0));
137 }
138
139 @Test
140 public void testRestoreAppDataSnapshot_availableBackupForLockedUser() throws Exception {
141 Installer installer = mock(Installer.class);
142 AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
143 doReturn(true).when(helper).isUserCredentialLocked(eq(10));
144
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000145 PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
Narayan Kamathc034fe92019-01-23 10:48:17 +0000146
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000147 assertTrue(helper.restoreAppData(73 /* rollbackId */, info, 10 /* userId */, 1 /* appId */,
148 "seinfo"));
Narayan Kamathc034fe92019-01-23 10:48:17 +0000149
150 InOrder inOrder = Mockito.inOrder(installer);
151 inOrder.verify(installer).restoreAppDataSnapshot(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000152 eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
153 eq(73) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
Narayan Kamathc034fe92019-01-23 10:48:17 +0000154 inOrder.verifyNoMoreInteractions();
155
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000156 ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
Narayan Kamathc034fe92019-01-23 10:48:17 +0000157 assertEquals(1, pendingRestores.size());
158 assertEquals(10, pendingRestores.get(0).userId);
159 assertEquals(1, pendingRestores.get(0).appId);
160 assertEquals("seinfo", pendingRestores.get(0).seInfo);
161 }
162
163 @Test
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000164 public void testRestoreAppDataSnapshot_availableBackupForUnlockedUser() throws Exception {
Narayan Kamathc034fe92019-01-23 10:48:17 +0000165 Installer installer = mock(Installer.class);
166 AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
167 doReturn(false).when(helper).isUserCredentialLocked(eq(10));
168
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000169 PackageRollbackInfo info = createPackageRollbackInfo("com.foo");
170 assertFalse(helper.restoreAppData(101 /* rollbackId */, info, 10 /* userId */,
171 1 /* appId */, "seinfo"));
Narayan Kamathc034fe92019-01-23 10:48:17 +0000172
173 InOrder inOrder = Mockito.inOrder(installer);
174 inOrder.verify(installer).restoreAppDataSnapshot(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000175 eq("com.foo"), eq(1) /* appId */, eq("seinfo"), eq(10) /* userId */,
176 eq(101) /* rollbackId */,
Narayan Kamathc034fe92019-01-23 10:48:17 +0000177 eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
178 inOrder.verifyNoMoreInteractions();
179
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000180 ArrayList<RestoreInfo> pendingRestores = info.getPendingRestores();
Narayan Kamathc034fe92019-01-23 10:48:17 +0000181 assertEquals(0, pendingRestores.size());
182 }
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000183
184 @Test
185 public void destroyAppData() throws Exception {
186 Installer installer = mock(Installer.class);
187 AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000188
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000189 PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
190 info.putCeSnapshotInode(11, 239L);
191 helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 10 /* userId */);
192 helper.destroyAppDataSnapshot(5 /* rollbackId */, info, 11 /* userId */);
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000193
194 InOrder inOrder = Mockito.inOrder(installer);
195 inOrder.verify(installer).destroyAppDataSnapshot(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000196 eq("com.foo.bar"), eq(10) /* userId */, eq(0L) /* ceSnapshotInode */,
197 eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000198 inOrder.verify(installer).destroyAppDataSnapshot(
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000199 eq("com.foo.bar"), eq(11) /* userId */, eq(239L) /* ceSnapshotInode */,
200 eq(5) /* rollbackId */, eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000201 inOrder.verifyNoMoreInteractions();
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000202
203 assertEquals(0, info.getCeSnapshotInodes().size());
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000204 }
205
206 @Test
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000207 public void commitPendingBackupAndRestoreForUser() throws Exception {
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000208 Installer installer = mock(Installer.class);
209 AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
210
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000211 when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(53L);
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000212
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000213 // This one should be backed up.
214 PackageRollbackInfo pendingBackup = createPackageRollbackInfo("com.foo", new int[]{37, 73});
215 pendingBackup.addPendingBackup(37);
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000216
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000217 // Nothing should be done for this one.
218 PackageRollbackInfo wasRecentlyRestored = createPackageRollbackInfo("com.bar",
219 new int[]{37, 73});
220 wasRecentlyRestored.addPendingBackup(37);
221 wasRecentlyRestored.getPendingRestores().add(
222 new RestoreInfo(37 /* userId */, 239 /* appId*/, "seInfo"));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000223
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000224 // This one should be restored
225 PackageRollbackInfo pendingRestore = createPackageRollbackInfo("com.abc",
226 new int[]{37, 73});
227 pendingRestore.putCeSnapshotInode(37, 1543L);
228 pendingRestore.getPendingRestores().add(
229 new RestoreInfo(37 /* userId */, 57 /* appId*/, "seInfo"));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000230
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000231 // This one shouldn't be processed, because it hasn't pending backups/restores for userId
232 // 37.
233 PackageRollbackInfo ignoredInfo = createPackageRollbackInfo("com.bar",
234 new int[]{3, 73});
235 wasRecentlyRestored.addPendingBackup(3);
236 wasRecentlyRestored.addPendingBackup(73);
237 wasRecentlyRestored.getPendingRestores().add(
238 new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000239
Gavin Corkery0987cb02019-10-07 10:46:55 +0100240 Rollback dataWithPendingBackup = createRollbackForId(101);
Richard Uhlercca637a2019-02-27 11:50:48 +0000241 dataWithPendingBackup.info.getPackages().add(pendingBackup);
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000242
Gavin Corkery0987cb02019-10-07 10:46:55 +0100243 Rollback dataWithRecentRestore = createRollbackForId(17239);
Richard Uhlercca637a2019-02-27 11:50:48 +0000244 dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000245
Gavin Corkery0987cb02019-10-07 10:46:55 +0100246 Rollback dataForDifferentUser = createRollbackForId(17239);
Richard Uhlercca637a2019-02-27 11:50:48 +0000247 dataForDifferentUser.info.getPackages().add(ignoredInfo);
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000248
Gavin Corkery0987cb02019-10-07 10:46:55 +0100249 Rollback dataForRestore = createRollbackForId(17239);
Richard Uhler6f8a33b2019-02-26 10:40:36 +0000250 dataForRestore.info.getPackages().add(pendingRestore);
251 dataForRestore.info.getPackages().add(wasRecentlyRestored);
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000252
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000253 InOrder inOrder = Mockito.inOrder(installer);
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000254
255 // Check that pending backup and restore for the same package mutually destroyed each other.
Oli Lan31f453f2019-09-11 09:58:39 +0100256 assertTrue(helper.commitPendingBackupAndRestoreForUser(37, dataWithRecentRestore));
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000257 assertEquals(-1, wasRecentlyRestored.getPendingBackups().indexOf(37));
258 assertNull(wasRecentlyRestored.getRestoreInfo(37));
259
260 // Check that backup was performed.
Oli Lan31f453f2019-09-11 09:58:39 +0100261 assertTrue(helper.commitPendingBackupAndRestoreForUser(37, dataWithPendingBackup));
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000262 inOrder.verify(installer).snapshotAppData(eq("com.foo"), eq(37), eq(101),
263 eq(Installer.FLAG_STORAGE_CE));
264 assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
265 assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));
266
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000267 // Check that restore was performed.
Oli Lan31f453f2019-09-11 09:58:39 +0100268 assertTrue(helper.commitPendingBackupAndRestoreForUser(37, dataForRestore));
Nikita Ioffe5dcd17972019-02-04 11:08:13 +0000269 inOrder.verify(installer).restoreAppDataSnapshot(
270 eq("com.abc"), eq(57) /* appId */, eq("seInfo"), eq(37) /* userId */,
271 eq(17239) /* rollbackId */, eq(Installer.FLAG_STORAGE_CE));
272 assertNull(pendingRestore.getRestoreInfo(37));
273
Nikita Ioffe952aa7b2019-01-28 19:49:56 +0000274 inOrder.verifyNoMoreInteractions();
275 }
Narayan Kamathc034fe92019-01-23 10:48:17 +0000276}