Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 1 | package com.android.launcher3; |
| 2 | |
Stefan Andonian | 8c0a787 | 2024-10-21 14:26:27 -0700 | [diff] [blame] | 3 | import static com.android.launcher3.LauncherPrefs.NO_DB_FILES_RESTORED; |
| 4 | |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 5 | import android.app.backup.BackupAgent; |
| 6 | import android.app.backup.BackupDataInput; |
| 7 | import android.app.backup.BackupDataOutput; |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 8 | import android.os.ParcelFileDescriptor; |
| 9 | |
Sunny Goyal | 49f19f0 | 2017-01-05 14:36:02 -0800 | [diff] [blame] | 10 | import com.android.launcher3.logging.FileLog; |
Sunny Goyal | e8f7d5a | 2016-05-24 11:30:14 -0700 | [diff] [blame] | 11 | import com.android.launcher3.provider.RestoreDbTask; |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 12 | |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 13 | import java.io.File; |
| 14 | import java.io.IOException; |
Stefan Andonian | 8c0a787 | 2024-10-21 14:26:27 -0700 | [diff] [blame] | 15 | import java.util.Arrays; |
| 16 | import java.util.stream.Collectors; |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 17 | |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 18 | public class LauncherBackupAgent extends BackupAgent { |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 19 | private static final String TAG = "LauncherBackupAgent"; |
Stefan Andonian | 8c0a787 | 2024-10-21 14:26:27 -0700 | [diff] [blame] | 20 | private static final String DB_FILE_PREFIX = "launcher"; |
| 21 | private static final String DB_FILE_SUFFIX = ".db"; |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 22 | |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 23 | @Override |
Sunny Goyal | 49f19f0 | 2017-01-05 14:36:02 -0800 | [diff] [blame] | 24 | public void onCreate() { |
| 25 | super.onCreate(); |
| 26 | // Set the log dir as LauncherAppState is not initialized during restore. |
| 27 | FileLog.setDir(getFilesDir()); |
| 28 | } |
| 29 | |
| 30 | @Override |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 31 | public void onRestore( |
| 32 | BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) { |
| 33 | // Doesn't do incremental backup/restore |
| 34 | } |
| 35 | |
| 36 | @Override |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 37 | public void onRestoreFile(ParcelFileDescriptor data, long size, File destination, int type, |
| 38 | long mode, long mtime) throws IOException { |
| 39 | // Remove old files which might contain obsolete attributes like idp_grid_name in shared |
| 40 | // preference that will obstruct backup's attribute from writing to shared preferences. |
| 41 | if (destination.delete()) { |
Charlie Anderson | c9d11e8 | 2023-08-02 11:41:55 -0400 | [diff] [blame] | 42 | FileLog.d(TAG, "onRestoreFile: Removed obsolete file " + destination); |
Alex Chau | 29a96ad | 2022-02-10 13:12:20 +0000 | [diff] [blame] | 43 | } |
| 44 | super.onRestoreFile(data, size, destination, type, mode, mtime); |
| 45 | } |
| 46 | |
| 47 | @Override |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 48 | public void onBackup( |
| 49 | ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) { |
| 50 | // Doesn't do incremental backup/restore |
| 51 | } |
| 52 | |
| 53 | @Override |
| 54 | public void onRestoreFinished() { |
Sunny Goyal | 68031ca | 2021-08-02 12:23:44 -0700 | [diff] [blame] | 55 | RestoreDbTask.setPending(this); |
Stefan Andonian | 8c0a787 | 2024-10-21 14:26:27 -0700 | [diff] [blame] | 56 | FileLog.d(TAG, "onRestoreFinished: set pending for RestoreDbTask"); |
| 57 | markIfFilesWereNotActuallyRestored(); |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * When restore is finished, we check to see if any db files were successfully restored. If not, |
| 62 | * our restore will fail later, but will report a different cause. This is important to split |
| 63 | * out the metric failures that are launcher's fault, and those that are due to bugs in the |
| 64 | * backup/restore code itself. |
| 65 | */ |
| 66 | private void markIfFilesWereNotActuallyRestored() { |
| 67 | File directory = new File(getDatabasePath(InvariantDeviceProfile.INSTANCE.get(this).dbFile) |
| 68 | .getParent()); |
| 69 | if (!directory.exists()) { |
| 70 | FileLog.e(TAG, "restore failed as target database directory doesn't exist"); |
| 71 | } else { |
| 72 | // Check for any db file that was restored, and collect as list |
| 73 | String fileNames = Arrays.stream(directory.listFiles()) |
| 74 | .map(File::getName) |
| 75 | .filter(n -> n.startsWith(DB_FILE_PREFIX) && n.endsWith(DB_FILE_SUFFIX)) |
| 76 | .collect(Collectors.joining(", ")); |
| 77 | if (fileNames.isBlank()) { |
| 78 | FileLog.e(TAG, "no database files were successfully restored"); |
| 79 | LauncherPrefs.get(this).putSync(NO_DB_FILES_RESTORED.to(true)); |
| 80 | } else { |
| 81 | FileLog.d(TAG, "database files successfully restored: " + fileNames); |
| 82 | } |
| 83 | } |
Sunny Goyal | c190dbf | 2016-05-05 14:37:05 -0700 | [diff] [blame] | 84 | } |
| 85 | } |