1 /* 2 * Copyright (C) 2013 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 17 package com.android.launcher3; 18 19 import android.app.backup.BackupAgentHelper; 20 import android.app.backup.BackupDataInput; 21 import android.app.backup.BackupManager; 22 import android.content.Context; 23 import android.content.SharedPreferences; 24 import android.database.Cursor; 25 import android.os.ParcelFileDescriptor; 26 import android.util.Log; 27 28 import com.android.launcher3.model.GridSizeMigrationTask; 29 30 import java.io.IOException; 31 32 public class LauncherBackupAgentHelper extends BackupAgentHelper { 33 34 private static final String TAG = "LauncherBAHelper"; 35 36 private static final String KEY_LAST_NOTIFIED_TIME = "backup_manager_last_notified"; 37 38 private static final String LAUNCHER_DATA_PREFIX = "L"; 39 40 static final boolean VERBOSE = false; 41 static final boolean DEBUG = false; 42 43 /** 44 * Notify the backup manager that out database is dirty. 45 * 46 * <P>This does not force an immediate backup. 47 * 48 * @param context application context 49 */ 50 public static void dataChanged(Context context) { 51 dataChanged(context, 0); 52 } 53 54 /** 55 * Notify the backup manager that out database is dirty. 56 * 57 * <P>This does not force an immediate backup. 58 * 59 * @param context application context 60 * @param throttleMs duration in ms for which two consecutive calls to backup manager should 61 * not be made. 62 */ 63 public static void dataChanged(Context context, long throttleMs) { 64 SharedPreferences prefs = Utilities.getPrefs(context); 65 long now = System.currentTimeMillis(); 66 long lastTime = prefs.getLong(KEY_LAST_NOTIFIED_TIME, 0); 67 68 // User can manually change the system time, which could lead to now < lastTime. 69 // Re-backup in that case, as the backup will have a wrong lastModifiedTime. 70 if (now < lastTime || now >= (lastTime + throttleMs)) { 71 BackupManager.dataChanged(context.getPackageName()); 72 prefs.edit().putLong(KEY_LAST_NOTIFIED_TIME, now).apply(); 73 } 74 } 75 76 private LauncherBackupHelper mHelper; 77 78 @Override 79 public void onCreate() { 80 super.onCreate(); 81 mHelper = new LauncherBackupHelper(this); 82 addHelper(LAUNCHER_DATA_PREFIX, mHelper); 83 } 84 85 @Override 86 public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) 87 throws IOException { 88 if (!Utilities.ATLEAST_LOLLIPOP) { 89 // No restore for old devices. 90 Log.i(TAG, "You shall not pass!!!"); 91 Log.d(TAG, "Restore is only supported on devices running Lollipop and above."); 92 return; 93 } 94 95 // Clear dB before restore 96 LauncherAppState.getLauncherProvider().createEmptyDB(); 97 98 boolean hasData; 99 try { 100 super.onRestore(data, appVersionCode, newState); 101 // If no favorite was migrated, clear the data and start fresh. 102 final Cursor c = getContentResolver().query( 103 LauncherSettings.Favorites.CONTENT_URI, null, null, null, null); 104 hasData = c.moveToNext(); 105 c.close(); 106 } catch (Exception e) { 107 // If the restore fails, we should do a fresh start. 108 Log.e(TAG, "Restore failed", e); 109 hasData = false; 110 } 111 112 if (hasData && mHelper.restoreSuccessful) { 113 LauncherAppState.getLauncherProvider().clearFlagEmptyDbCreated(); 114 LauncherClings.markFirstRunClingDismissed(this); 115 116 // Rank was added in v4. 117 if (mHelper.restoredBackupVersion <= 3) { 118 LauncherAppState.getLauncherProvider().updateFolderItemsRank(); 119 } 120 121 if (GridSizeMigrationTask.ENABLED && mHelper.shouldAttemptWorkspaceMigration()) { 122 GridSizeMigrationTask.markForMigration(getApplicationContext(), 123 mHelper.widgetSizes, mHelper.migrationCompatibleProfileData); 124 } 125 126 LauncherAppState.getLauncherProvider().convertShortcutsToLauncherActivities(); 127 } else { 128 if (VERBOSE) Log.v(TAG, "Nothing was restored, clearing DB"); 129 LauncherAppState.getLauncherProvider().createEmptyDB(); 130 } 131 } 132 } 133