From 0807c946b698d6a533f25b79c282ce2f0f4511fa Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 28 Apr 2020 13:58:45 -0700 Subject: [PATCH 01/55] 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 --- .../android/launcher3/LauncherProvider.java | 19 ++++++++++--------- .../launcher3/pm/InstallSessionHelper.java | 14 ++------------ .../launcher3/provider/RestoreDbTask.java | 18 ++++++++++-------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 21cd04e20c..48b97fafd3 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -20,7 +20,6 @@ import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_A 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.net.Uri; 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.net.URISyntaxException; 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 @@ public class LauncherProvider extends ContentProvider { 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 @@ public class LauncherProvider extends ContentProvider { protected DatabaseHelper mOpenHelper; + private long mLastRestoreTimestamp = 0L; + /** * $ adb shell dumpsys activity provider com.android.launcher3 */ @@ -412,11 +412,12 @@ public class LauncherProvider extends ContentProvider { 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 976d7ba5a0..901d27f373 100644 --- a/src/com/android/launcher3/pm/InstallSessionHelper.java +++ b/src/com/android/launcher3/pm/InstallSessionHelper.java @@ -56,8 +56,6 @@ public class InstallSessionHelper { // Set 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 @@ public class InstallSessionHelper { } /** - * 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 @@ public class InstallSessionHelper { 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 33eff5716f..53183bf210 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 class RestoreDbTask { */ 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 @@ public class RestoreDbTask { */ 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 @@ public class RestoreDbTask { 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 @@ public class RestoreDbTask { * 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 @@ public class RestoreDbTask { if (myProfileId != oldProfileId) { changeDefaultColumn(db, myProfileId); } + return itemsDeleted; } /** From e620872b18c8ab24a32e35c1617be486b8a20556 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 5 May 2020 18:18:40 -0700 Subject: [PATCH 02/55] Add logs to debug playtime crash and band aid fix for release builds. Bug: 153821199 Change-Id: I0caa546254bb51ca8b88cdb16d79c054560bf2be --- .../android/launcher3/LauncherAnimationRunner.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java index 2cb23f1599..fc60434215 100644 --- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java @@ -26,6 +26,7 @@ import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.Handler; +import android.util.Log; import androidx.annotation.BinderThread; import androidx.annotation.UiThread; @@ -37,6 +38,8 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat, WrappedAnimationRunnerImpl { + private static final String TAG = "LauncherAnimationRunner"; + private final Handler mHandler; private final boolean mStartAtFrontOfQueue; private AnimationResult mAnimationResult; @@ -151,7 +154,16 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo // Because t=0 has the app icon in its original spot, we can skip the // first frame and have the same movement one frame earlier. - mAnimator.setCurrentPlayTime(getSingleFrameMs(context)); + int singleFrameMs = getSingleFrameMs(context); + long playTime = singleFrameMs; + // b/153821199 Add logs to debug crash but ensure release builds do not crash. + if (Utilities.IS_DEBUG_DEVICE) { + Log.e(TAG, "Total duration=[" + mAnimator.getTotalDuration() + + "], singleFrameMs=[" + singleFrameMs + "], mAnimator=" + mAnimator); + } else { + playTime = Math.min(singleFrameMs, mAnimator.getTotalDuration()); + } + mAnimator.setCurrentPlayTime(playTime); } } } From 78f53856a98dbc01aa86a1540ae23a7a9b0052bb Mon Sep 17 00:00:00 2001 From: Sreyas Date: Mon, 27 Apr 2020 13:29:57 -0700 Subject: [PATCH 03/55] Disabling OverviewActionsView buttons while scrolling or clear all shown. Bug: 153469850, 153387526 Video: https://drive.google.com/a/google.com/file/d/1mOc8yubux92iKtXRtSOKTcnjWWzvDgC7/view?usp=sharing Change-Id: Id507d3a050e67057fc34a30771c9566ddfcf94ca --- .../android/quickstep/views/RecentsView.java | 11 +++++++++++ quickstep/res/values/styles.xml | 4 ++-- .../android/quickstep/util/LayoutUtils.java | 19 +++++++++++++++++++ res/color/overview_button.xml | 11 +++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 res/color/overview_button.xml diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index d9cbe0bc62..31563ad03c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -123,6 +123,7 @@ import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskUtils; import com.android.quickstep.ViewUtils; import com.android.quickstep.util.AppWindowAnimationHelper; +import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.WindowSizeStrategy; import com.android.systemui.plugins.ResourceProvider; @@ -597,9 +598,18 @@ public abstract class RecentsView extends PagedView impl } } + @Override + protected void onPageBeginTransition() { + super.onPageBeginTransition(); + LayoutUtils.setViewEnabled(mActionsView, false); + } + @Override protected void onPageEndTransition() { super.onPageEndTransition(); + if (getScrollX() == getScrollForPage(getPageNearestToCenterOfScreen())) { + LayoutUtils.setViewEnabled(mActionsView, true); + } if (getNextPage() > 0) { setSwipeDownShouldLaunchApp(true); } @@ -958,6 +968,7 @@ public abstract class RecentsView extends PagedView impl setCurrentPage(0); mDwbToastShown = false; mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0); + LayoutUtils.setViewEnabled(mActionsView, true); } public @Nullable TaskView getRunningTaskView() { diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml index c97ee7c52a..d3c4f4d93b 100644 --- a/quickstep/res/values/styles.xml +++ b/quickstep/res/values/styles.xml @@ -79,8 +79,8 @@ +