From 2db5342f042061a3e34791c3d077447b52a5fc4e Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 1 Mar 2019 16:06:12 -0800 Subject: [PATCH] Fixing some Launcher crashes because of using old model data even after launcher has reloaded Bug: 126289691 Bug: 124288578 Change-Id: Id7fb29716241a13f4e03ee0fc0e879523de4f878 --- src/com/android/launcher3/Launcher.java | 4 ++- src/com/android/launcher3/LauncherModel.java | 29 ++++++++++--------- .../launcher3/LauncherStateManager.java | 26 +++++++++++++---- src/com/android/launcher3/Workspace.java | 10 +++++-- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d65fe763fa..d820448879 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -257,7 +257,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private RotationHelper mRotationHelper; - private final Handler mHandler = new Handler(); + final Handler mHandler = new Handler(); private final Runnable mHandleDeferredResume = this::handleDeferredResume; @Override @@ -1748,6 +1748,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, setWorkspaceLoading(true); // Clear the workspace because it's going to be rebound + mDragController.cancelDrag(); + mWorkspace.clearDropTargets(); mWorkspace.removeAllWorkspaceScreens(); mAppWidgetHost.clearViews(); diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 5ab6eeaff3..b1664f1103 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -34,6 +34,7 @@ import android.util.Pair; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserManagerCompat; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AddWorkspaceItemsTask; @@ -210,20 +211,20 @@ public class LauncherModel extends BroadcastReceiver final int itemId, final ItemInfo item, StackTraceElement[] stackTrace) { ItemInfo modelItem = sBgDataModel.itemsIdMap.get(itemId); if (modelItem != null && item != modelItem) { - // check all the data is consistent - if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) { - ShortcutInfo modelShortcut = (ShortcutInfo) modelItem; - ShortcutInfo shortcut = (ShortcutInfo) item; - if (modelShortcut.title.toString().equals(shortcut.title.toString()) && - modelShortcut.intent.filterEquals(shortcut.intent) && - modelShortcut.id == shortcut.id && - modelShortcut.itemType == shortcut.itemType && - modelShortcut.container == shortcut.container && - modelShortcut.screenId == shortcut.screenId && - modelShortcut.cellX == shortcut.cellX && - modelShortcut.cellY == shortcut.cellY && - modelShortcut.spanX == shortcut.spanX && - modelShortcut.spanY == shortcut.spanY) { + // If it is a release build on a release device, check all the data is consistent as + // we don't want to crash non-dev users. + if (!Utilities.IS_DEBUG_DEVICE && !FeatureFlags.IS_DOGFOOD_BUILD && + modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) { + if (modelItem.title.toString().equals(item.title.toString()) && + modelItem.getIntent().filterEquals(item.getIntent()) && + modelItem.id == item.id && + modelItem.itemType == item.itemType && + modelItem.container == item.container && + modelItem.screenId == item.screenId && + modelItem.cellX == item.cellX && + modelItem.cellY == item.cellY && + modelItem.spanX == item.spanX && + modelItem.spanY == item.spanY) { // For all intents and purposes, this is the same object return; } diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index 119058d006..f6b54f2441 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -248,6 +248,22 @@ public class LauncherStateManager { return; } + if (delay > 0) { + // Create the animation after the delay as some properties can change between preparing + // the animation and running the animation. + int startChangeId = mConfig.mChangeId; + mUiHandler.postDelayed(() -> { + if (mConfig.mChangeId == startChangeId) { + goToStateAnimated(state, fromState, onCompleteRunnable); + } + }, delay); + } else { + goToStateAnimated(state, fromState, onCompleteRunnable); + } + } + + private void goToStateAnimated(LauncherState state, LauncherState fromState, + Runnable onCompleteRunnable) { // Since state NORMAL can be reached from multiple states, just assume that the // transition plays in reverse and use the same duration as previous state. mConfig.duration = state == NORMAL ? fromState.transitionDuration : state.transitionDuration; @@ -256,12 +272,7 @@ public class LauncherStateManager { prepareForAtomicAnimation(fromState, state, builder); AnimatorSet animation = createAnimationToNewWorkspaceInternal( state, builder, onCompleteRunnable); - Runnable runnable = new StartAnimRunnable(animation); - if (delay > 0) { - mUiHandler.postDelayed(runnable, delay); - } else { - mUiHandler.post(runnable); - } + mUiHandler.post(new StartAnimRunnable(animation)); } /** @@ -533,6 +544,8 @@ public class LauncherStateManager { private AnimatorSet mCurrentAnimation; private LauncherState mTargetState; + // Id to keep track of config changes, to tie an animation with the corresponding request + private int mChangeId = 0; /** * Cancels the current animation and resets config variables. @@ -554,6 +567,7 @@ public class LauncherStateManager { mCurrentAnimation = null; playbackController = null; + mChangeId ++; } public PropertySetter getPropertySetter(AnimatorSetBuilder builder) { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 7f5ca423da..7eee8af5a9 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -44,6 +44,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.IBinder; +import android.os.Message; import android.os.Parcelable; import android.os.UserHandle; import android.util.AttributeSet; @@ -521,6 +522,9 @@ public class Workspace extends PagedView mScreenOrder.clear(); mWorkspaceScreens.clear(); + // Remove any deferred refresh callbacks + mLauncher.mHandler.removeCallbacksAndMessages(DeferredWidgetRefresh.class); + // Ensure that the first page is always present bindAndInitFirstWorkspaceScreen(qsb); @@ -3348,13 +3352,15 @@ public class Workspace extends PagedView LauncherAppWidgetHost host) { mInfos = infos; mHost = host; - mHandler = new Handler(); + mHandler = mLauncher.mHandler; mRefreshPending = true; mHost.addProviderChangeListener(this); // Force refresh after 10 seconds, if we don't get the provider changed event. // This could happen when the provider is no longer available in the app. - mHandler.postDelayed(this, 10000); + Message msg = Message.obtain(mHandler, this); + msg.obj = DeferredWidgetRefresh.class; + mHandler.sendMessageDelayed(msg, 10000); } @Override