Mitigate 10 minutes delay in launcher restore for work apps.

1. Instead of debouncing launcher restore when new install session
(triggered by Play Service due to restore) is created, it is now
throttled at once every 30 seconds. (i.e. Launcher restore is triggered
immediately, but cannot be triggered again within 30 seconds)
2. Removes the backup table when all items are restored. (i.e. no item
were removed as a result of sanitize db due to user didn't sign in to
their work profile)

Bug: 153648870
Change-Id: I32df371f8b47c60a72515876217fd83ac1e56f0a
Test: manually verified with deferred restore
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 21cd04e..48b97fa 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -20,7 +20,6 @@
 import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
 import android.annotation.TargetApi;
 import android.app.backup.BackupManager;
@@ -48,7 +47,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -85,6 +83,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 
 public class LauncherProvider extends ContentProvider {
@@ -92,8 +91,7 @@
     private static final boolean LOGD = false;
 
     private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
-    private static final String TOKEN_RESTORE_BACKUP_TABLE = "restore_backup_table";
-    private static final long RESTORE_BACKUP_TABLE_DELAY = 60000;
+    private static final long RESTORE_BACKUP_TABLE_DELAY = TimeUnit.SECONDS.toMillis(30);
 
     /**
      * Represents the schema of the database. Changes in scheme need not be backwards compatible.
@@ -107,6 +105,8 @@
 
     protected DatabaseHelper mOpenHelper;
 
+    private long mLastRestoreTimestamp = 0L;
+
     /**
      * $ adb shell dumpsys activity provider com.android.launcher3
      */
@@ -412,11 +412,12 @@
                 return null;
             }
             case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
-                final Handler handler = MODEL_EXECUTOR.getHandler();
-                handler.removeCallbacksAndMessages(TOKEN_RESTORE_BACKUP_TABLE);
-                handler.postDelayed(() -> RestoreDbTask.restoreIfPossible(
-                        getContext(), mOpenHelper, new BackupManager(getContext())),
-                        TOKEN_RESTORE_BACKUP_TABLE, RESTORE_BACKUP_TABLE_DELAY);
+                final long ts = System.currentTimeMillis();
+                if (ts - mLastRestoreTimestamp > RESTORE_BACKUP_TABLE_DELAY) {
+                    mLastRestoreTimestamp = ts;
+                    RestoreDbTask.restoreIfPossible(
+                            getContext(), mOpenHelper, new BackupManager(getContext()));
+                }
                 return null;
             }
             case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 976d7ba..901d27f 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -56,8 +56,6 @@
     // Set<String> of session ids of promise icons that have been added to the home screen
     // as FLAG_PROMISE_NEW_INSTALLS.
     protected static final String PROMISE_ICON_IDS = "promise_icon_ids";
-    public static final String KEY_INSTALL_SESSION_CREATED_TIMESTAMP =
-            "key_install_session_created_timestamp";
 
     private static final boolean DEBUG = false;
 
@@ -166,14 +164,13 @@
     }
 
     /**
-     * Attempt to restore workspace layout if the session is triggered due to device restore and it
-     * has a newer timestamp.
+     * Attempt to restore workspace layout if the session is triggered due to device restore.
      */
     public boolean restoreDbIfApplicable(@NonNull final SessionInfo info) {
         if (!Utilities.ATLEAST_OREO || !FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
             return false;
         }
-        if (isRestore(info) && hasNewerTimestamp(mAppContext, info)) {
+        if (isRestore(info)) {
             LauncherSettings.Settings.call(mAppContext.getContentResolver(),
                     LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE);
             return true;
@@ -186,13 +183,6 @@
         return info.getInstallReason() == PackageManager.INSTALL_REASON_DEVICE_RESTORE;
     }
 
-    private static boolean hasNewerTimestamp(
-            @NonNull final Context context, @NonNull final SessionInfo info) {
-        return PackageManagerHelper.getSessionCreatedTimeInMillis(info)
-                > Utilities.getDevicePrefs(context).getLong(
-                        KEY_INSTALL_SESSION_CREATED_TIMESTAMP, 0);
-    }
-
     public boolean promiseIconAddedForId(int sessionId) {
         return mPromiseIconIds.contains(sessionId);
     }
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 33eff57..53183bf 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3.provider;
 
-import static com.android.launcher3.pm.InstallSessionHelper.KEY_INSTALL_SESSION_CREATED_TIMESTAMP;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
 
 import android.app.backup.BackupManager;
@@ -87,13 +86,10 @@
      */
     public static boolean restoreIfPossible(@NonNull Context context,
             @NonNull DatabaseHelper helper, @NonNull BackupManager backupManager) {
-        Utilities.getDevicePrefs(context).edit().putLong(
-                KEY_INSTALL_SESSION_CREATED_TIMESTAMP, System.currentTimeMillis()).apply();
         final SQLiteDatabase db = helper.getWritableDatabase();
         try (SQLiteTransaction t = new SQLiteTransaction(db)) {
             RestoreDbTask task = new RestoreDbTask();
             task.restoreWorkspace(context, db, helper, backupManager);
-            task.restoreAppWidgetIdsIfExists(context);
             t.commit();
             return true;
         } catch (Exception e) {
@@ -107,7 +103,6 @@
      */
     private void backupWorkspace(Context context, SQLiteDatabase db) throws Exception {
         InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
-        // TODO(pinyaoting): Support backing up workspace with multiple grid options.
         new GridBackupTable(context, db, idp.numHotseatIcons, idp.numColumns, idp.numRows)
                 .doBackup(getDefaultProfileId(db), GridBackupTable.OPTION_REQUIRES_SANITIZATION);
     }
@@ -115,13 +110,17 @@
     private void restoreWorkspace(@NonNull Context context, @NonNull SQLiteDatabase db,
             @NonNull DatabaseHelper helper, @NonNull BackupManager backupManager)
             throws Exception {
-        // TODO(pinyaoting): Support restoring workspace with multiple grid options.
         final InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
         GridBackupTable backupTable = new GridBackupTable(context, db, idp.numHotseatIcons,
                 idp.numColumns, idp.numRows);
         if (backupTable.restoreFromRawBackupIfAvailable(getDefaultProfileId(db))) {
-            sanitizeDB(helper, db, backupManager);
+            int itemsDeleted = sanitizeDB(helper, db, backupManager);
             LauncherAppState.getInstance(context).getModel().forceReload();
+            restoreAppWidgetIdsIfExists(context);
+            if (itemsDeleted == 0) {
+                // all the items are restored, we no longer need the backup table
+                dropTable(db, Favorites.BACKUP_TABLE_NAME);
+            }
         }
     }
 
@@ -132,8 +131,10 @@
      *      the restored apps get installed.
      *   3. If the user serial for any restored profile is different than that of the previous
      *      device, update the entries to the new profile id.
+     *
+     * @return number of items deleted.
      */
-    private void sanitizeDB(DatabaseHelper helper, SQLiteDatabase db, BackupManager backupManager)
+    private int sanitizeDB(DatabaseHelper helper, SQLiteDatabase db, BackupManager backupManager)
             throws Exception {
         // Primary user ids
         long myProfileId = helper.getDefaultUserSerial();
@@ -210,6 +211,7 @@
         if (myProfileId != oldProfileId) {
             changeDefaultColumn(db, myProfileId);
         }
+        return itemsDeleted;
     }
 
     /**