blob: 34a8025b397bf59614007699618d081b3412e544 [file] [log] [blame]
Pinyao Ting9be1cfd2020-01-16 12:29:04 -08001/*
2 * Copyright (C) 2020 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.launcher3.model;
18
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080019import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE;
20
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080021import static com.android.launcher3.LauncherSettings.Favorites.BACKUP_TABLE_NAME;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080022import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
23import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
24import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080025import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080026import static com.android.launcher3.util.LauncherModelHelper.APP_ICON;
27import static com.android.launcher3.util.LauncherModelHelper.NO__ICON;
28import static com.android.launcher3.util.LauncherModelHelper.SHORTCUT;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080029
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080030import static org.junit.Assert.assertEquals;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080031import static org.junit.Assert.assertTrue;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080032import static org.robolectric.util.ReflectionHelpers.setField;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080033
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080034import android.app.backup.BackupManager;
35import android.content.pm.PackageInstaller;
36import android.database.Cursor;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080037import android.database.sqlite.SQLiteDatabase;
Pinyao Tinga39f45b2021-04-07 19:40:02 -070038import android.os.Process;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080039import android.os.UserHandle;
40import android.os.UserManager;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080041
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080042import com.android.launcher3.InvariantDeviceProfile;
Sunny Goyalc0e9df62020-01-16 14:54:36 -080043import com.android.launcher3.provider.RestoreDbTask;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080044import com.android.launcher3.shadows.LShadowBackupManager;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080045import com.android.launcher3.util.LauncherModelHelper;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080046
47import org.junit.Before;
48import org.junit.Test;
49import org.junit.runner.RunWith;
Sunny Goyalc57a7972020-04-08 16:27:28 -070050import org.robolectric.RobolectricTestRunner;
Sunny Goyalc0e9df62020-01-16 14:54:36 -080051import org.robolectric.RuntimeEnvironment;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080052import org.robolectric.annotation.LooperMode;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080053import org.robolectric.shadow.api.Shadow;
Sunny Goyal3751be02020-11-13 13:48:51 -080054import org.robolectric.shadows.ShadowUserManager;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080055
56/**
57 * Tests to verify backup and restore flow.
58 */
Sunny Goyalc57a7972020-04-08 16:27:28 -070059@RunWith(RobolectricTestRunner.class)
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080060@LooperMode(LooperMode.Mode.PAUSED)
61public class BackupRestoreTest {
62
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080063 private static final long MY_OLD_PROFILE_ID = 1;
64 private static final long MY_PROFILE_ID = 0;
65 private static final long OLD_WORK_PROFILE_ID = 11;
66 private static final int WORK_PROFILE_ID = 10;
67
Sunny Goyal3751be02020-11-13 13:48:51 -080068 private ShadowUserManager mUserManager;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080069 private BackupManager mBackupManager;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080070 private LauncherModelHelper mModelHelper;
71 private SQLiteDatabase mDb;
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080072 private InvariantDeviceProfile mIdp;
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080073
74 @Before
75 public void setUp() {
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080076 setupUserManager();
77 setupBackupManager();
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080078 mModelHelper = new LauncherModelHelper();
Sunny Goyalc0e9df62020-01-16 14:54:36 -080079 RestoreDbTask.setPending(RuntimeEnvironment.application, true);
80 mDb = mModelHelper.provider.getDb();
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080081 mIdp = InvariantDeviceProfile.INSTANCE.get(RuntimeEnvironment.application);
82 }
83
84 private void setupUserManager() {
85 final UserManager userManager = RuntimeEnvironment.application.getSystemService(
86 UserManager.class);
87 mUserManager = Shadow.extract(userManager);
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080088 // sign in to work profile
Pinyao Tinga39f45b2021-04-07 19:40:02 -070089 mUserManager.addUser(WORK_PROFILE_ID, "work", ShadowUserManager.FLAG_MANAGED_PROFILE);
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -080090 }
91
92 private void setupBackupManager() {
93 mBackupManager = new BackupManager(RuntimeEnvironment.application);
94 final LShadowBackupManager bm = Shadow.extract(mBackupManager);
Pinyao Tinga39f45b2021-04-07 19:40:02 -070095 bm.addProfile(MY_OLD_PROFILE_ID, Process.myUserHandle());
96 bm.addProfile(OLD_WORK_PROFILE_ID, UserHandle.of(WORK_PROFILE_ID));
Pinyao Ting9be1cfd2020-01-16 12:29:04 -080097 }
98
99 @Test
100 public void testOnCreateDbIfNotExists_CreatesBackup() {
101 assertTrue(tableExists(mDb, BACKUP_TABLE_NAME));
102 }
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -0800103
104 @Test
105 public void testOnRestoreSessionWithValidCondition_PerformsRestore() throws Exception {
106 setupBackup();
107 verifyTableIsFilled(BACKUP_TABLE_NAME, false);
108 verifyTableIsEmpty(TABLE_NAME);
109 createRestoreSession();
110 verifyTableIsFilled(TABLE_NAME, true);
111 }
112
113 private void setupBackup() {
114 createTableUsingOldProfileId();
115 // setup grid for main user on first screen
116 mModelHelper.createGrid(new int[][][]{{
117 { APP_ICON, APP_ICON, SHORTCUT, SHORTCUT},
118 { SHORTCUT, SHORTCUT, NO__ICON, NO__ICON},
119 { NO__ICON, NO__ICON, SHORTCUT, SHORTCUT},
120 { APP_ICON, SHORTCUT, SHORTCUT, APP_ICON},
121 }}, 1, MY_OLD_PROFILE_ID);
122 // setup grid for work profile on second screen
123 mModelHelper.createGrid(new int[][][]{{
124 { NO__ICON, APP_ICON, SHORTCUT, SHORTCUT},
125 { SHORTCUT, SHORTCUT, NO__ICON, NO__ICON},
126 { NO__ICON, NO__ICON, SHORTCUT, SHORTCUT},
127 { APP_ICON, SHORTCUT, SHORTCUT, NO__ICON},
128 }}, 2, OLD_WORK_PROFILE_ID);
129 // simulates the creation of backup upon restore
Tony Wickhamb87f3cd2021-04-07 15:02:37 -0700130 new GridBackupTable(RuntimeEnvironment.application, mDb, mIdp.numDatabaseHotseatIcons,
Pinyao Ting5f8a1ab2020-01-24 16:39:08 -0800131 mIdp.numColumns, mIdp.numRows).doBackup(
132 MY_OLD_PROFILE_ID, GridBackupTable.OPTION_REQUIRES_SANITIZATION);
133 // reset favorites table
134 createTableUsingOldProfileId();
135 }
136
137 private void verifyTableIsEmpty(String tableName) {
138 assertEquals(0, getCount(mDb, "SELECT * FROM " + tableName));
139 }
140
141 private void verifyTableIsFilled(String tableName, boolean sanitized) {
142 assertEquals(sanitized ? 12 : 13, getCount(mDb,
143 "SELECT * FROM " + tableName + " WHERE profileId = "
144 + (sanitized ? MY_PROFILE_ID : MY_OLD_PROFILE_ID)));
145 assertEquals(10, getCount(mDb, "SELECT * FROM " + tableName + " WHERE profileId = "
146 + (sanitized ? WORK_PROFILE_ID : OLD_WORK_PROFILE_ID)));
147 }
148
149 private void createTableUsingOldProfileId() {
150 // simulates the creation of favorites table on old device
151 dropTable(mDb, TABLE_NAME);
152 addTableToDb(mDb, MY_OLD_PROFILE_ID, false);
153 }
154
155 private void createRestoreSession() throws Exception {
156 final PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
157 PackageInstaller.SessionParams.MODE_FULL_INSTALL);
158 final PackageInstaller installer = RuntimeEnvironment.application.getPackageManager()
159 .getPackageInstaller();
160 final int sessionId = installer.createSession(params);
161 final PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId);
162 setField(info, "installReason", INSTALL_REASON_DEVICE_RESTORE);
163 // TODO: (b/148410677) we should verify the following call instead
164 // InstallSessionHelper.INSTANCE.get(getContext()).restoreDbIfApplicable(info);
165 RestoreDbTask.restoreIfPossible(RuntimeEnvironment.application,
166 mModelHelper.provider.getHelper(), mBackupManager);
167 }
168
169 private static int getCount(SQLiteDatabase db, String sql) {
170 try (Cursor c = db.rawQuery(sql, null)) {
171 return c.getCount();
172 }
173 }
Pinyao Ting9be1cfd2020-01-16 12:29:04 -0800174}