Merge "Removing flake when 2 long-press events happened on single long press" into ub-launcher3-master
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index ab6393a..71d77fc 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -43,6 +43,7 @@
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.views.RecentsView;
+import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -51,10 +52,18 @@
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TaplTestsQuickstep extends AbstractQuickStepTest {
+ private int mLauncherPid;
+
@Before
public void setUp() throws Exception {
super.setUp();
TaplTestsLauncher3.initialize(this);
+ mLauncherPid = mLauncher.getPid();
+ }
+
+ @After
+ public void teardown() {
+ assertEquals("Launcher crashed, pid mismatch:", mLauncherPid, mLauncher.getPid());
}
private void startTestApps() throws Exception {
diff --git a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
index 83b8599..6223760 100644
--- a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
@@ -23,12 +23,14 @@
import android.database.sqlite.SQLiteDatabase;
+import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.LauncherModelHelper;
import com.android.launcher3.util.LauncherRoboTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.LooperMode;
/**
@@ -44,7 +46,8 @@
@Before
public void setUp() {
mModelHelper = new LauncherModelHelper();
- mDb = mModelHelper.provider.getDbWithRestoreDbTask();
+ RestoreDbTask.setPending(RuntimeEnvironment.application, true);
+ mDb = mModelHelper.provider.getDb();
}
@Test
diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 655055c..e8b7157 100644
--- a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -28,6 +28,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.Settings;
@@ -276,6 +277,8 @@
Context context = RuntimeEnvironment.application;
LauncherSettings.Settings.call(context.getContentResolver(),
LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
int[][][] ids = new int[typeArray.length][][];
for (int i = 0; i < typeArray.length; i++) {
@@ -312,7 +315,6 @@
idp.numRows = idp.numColumns = idp.numHotseatIcons = DEFAULT_GRID_SIZE;
idp.iconBitmapSize = DEFAULT_BITMAP_SIZE;
- provider.setAllowLoadDefaultFavorites(true);
Settings.Secure.putString(context.getContentResolver(),
"launcher3.layout.provider", TEST_PROVIDER_AUTHORITY);
@@ -340,4 +342,20 @@
filter.addCategory(Intent.CATEGORY_DEFAULT);
spm.addIntentFilterForActivity(cn, filter);
}
+
+ /**
+ * An extension of LauncherProvider backed up by in-memory database.
+ */
+ public static class TestLauncherProvider extends LauncherProvider {
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ public SQLiteDatabase getDb() {
+ createDbIfNotExists();
+ return mOpenHelper.getWritableDatabase();
+ }
+ }
}
diff --git a/robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java b/robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java
deleted file mode 100644
index 8ae6528..0000000
--- a/robolectric_tests/src/com/android/launcher3/util/TestLauncherProvider.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.android.launcher3.util;
-
-import android.content.Context;
-import android.database.sqlite.SQLiteDatabase;
-
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.provider.RestoreDbTask;
-
-/**
- * An extension of LauncherProvider backed up by in-memory database.
- */
-public class TestLauncherProvider extends LauncherProvider {
-
- private boolean mAllowLoadDefaultFavorites;
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- protected synchronized void createDbIfNotExists() {
- if (mOpenHelper == null) {
- mOpenHelper = new MyDatabaseHelper(getContext(), mAllowLoadDefaultFavorites);
- }
- }
-
- public void setAllowLoadDefaultFavorites(boolean allowLoadDefaultFavorites) {
- mAllowLoadDefaultFavorites = allowLoadDefaultFavorites;
- }
-
- public SQLiteDatabase getDb() {
- createDbIfNotExists();
- return mOpenHelper.getWritableDatabase();
- }
-
- public SQLiteDatabase getDbWithRestoreDbTask() {
- RestoreDbTask.setPending(getContext(), true);
- super.createDbIfNotExists();
- return mOpenHelper.getWritableDatabase();
- }
-
- private static class MyDatabaseHelper extends DatabaseHelper {
-
- private final boolean mAllowLoadDefaultFavorites;
-
- MyDatabaseHelper(Context context, boolean allowLoadDefaultFavorites) {
- super(context, null);
- mAllowLoadDefaultFavorites = allowLoadDefaultFavorites;
- initIds();
- }
-
- @Override
- public long getDefaultUserSerial() {
- return 0;
- }
-
- @Override
- protected void onEmptyDbCreated() {
- if (mAllowLoadDefaultFavorites) {
- super.onEmptyDbCreated();
- }
- }
-
- @Override
- protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
- }
-}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index b589560..b0ab35c 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -18,6 +18,7 @@
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;
@@ -45,6 +46,7 @@
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;
@@ -87,6 +89,8 @@
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;
/**
* Represents the schema of the database. Changes in scheme need not be backwards compatible.
@@ -388,8 +392,11 @@
return null;
}
case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: {
- RestoreDbTask.restoreIfPossible(
- getContext(), mOpenHelper, new BackupManager(getContext()));
+ 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);
return null;
}
}
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index f0bae02..89f0a3d 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -78,6 +78,7 @@
}
InstallSessionHelper packageInstallerCompat = InstallSessionHelper.INSTANCE.get(context);
+ packageInstallerCompat.restoreDbIfApplicable(info);
if (TextUtils.isEmpty(info.getAppPackageName())
|| info.getInstallReason() != PackageManager.INSTALL_REASON_USER
|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 81dcba3..75609fe 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -136,6 +136,10 @@
public static final TogglableFlag ENABLE_OVERVIEW_ACTIONS = new TogglableFlag(
"ENABLE_OVERVIEW_ACTIONS", false, "Show app actions in Overview");
+ public static final TogglableFlag ENABLE_DATABASE_RESTORE = new TogglableFlag(
+ "ENABLE_DATABASE_RESTORE", true,
+ "Enable database restore when new restore session is created");
+
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 186293f..976d7ba 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -29,6 +29,10 @@
import android.os.UserHandle;
import android.text.TextUtils;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
@@ -52,6 +56,8 @@
// 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;
@@ -159,6 +165,34 @@
return list;
}
+ /**
+ * Attempt to restore workspace layout if the session is triggered due to device restore and it
+ * has a newer timestamp.
+ */
+ public boolean restoreDbIfApplicable(@NonNull final SessionInfo info) {
+ if (!Utilities.ATLEAST_OREO || !FeatureFlags.ENABLE_DATABASE_RESTORE.get()) {
+ return false;
+ }
+ if (isRestore(info) && hasNewerTimestamp(mAppContext, info)) {
+ LauncherSettings.Settings.call(mAppContext.getContentResolver(),
+ LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE);
+ return true;
+ }
+ return false;
+ }
+
+ @RequiresApi(26)
+ private static boolean isRestore(@NonNull final SessionInfo info) {
+ 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 7ee30cc..407ff31 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,6 +16,7 @@
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;
@@ -86,6 +87,8 @@
*/
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();
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 8b2ee36..6c18747 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -16,6 +16,7 @@
package com.android.launcher3.util;
+import static android.content.pm.PackageInstaller.SessionInfo;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import android.app.AppOpsManager;
@@ -44,6 +45,8 @@
import android.util.Pair;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.AppInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppWidgetInfo;
@@ -345,4 +348,15 @@
}
return false;
}
+
+ /**
+ * Returns the created time in millis of given session info. Returns 0 if not available.
+ */
+ public static long getSessionCreatedTimeInMillis(@NonNull final SessionInfo info) {
+ try {
+ return (long) SessionInfo.class.getDeclaredMethod("getCreatedMillis").invoke(info);
+ } catch (Exception e) {
+ return 0;
+ }
+ }
}