Fix out-of-sync updates during grid change
This is a combination of two issues:
1. Widget updates are not passed to the holder when the launcher binding starts
2. Updates from widgetHost.startListening() are overriden by out-of-date info
Fix: 322919716
Test: Manual
Flag: N/A
Change-Id: I9665117412c87b19ed5d98263bb4f9b8da21c5c7
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
index e3ff281..23e2622 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
@@ -26,10 +26,10 @@
import android.util.SparseArray;
import android.widget.RemoteViews;
+import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.WidgetsModel;
@@ -265,6 +265,14 @@
}
}
+ /**
+ * Clears all the internal widget views excluding the update listeners
+ */
+ @Override
+ public void clearWidgetViews() {
+ mViews.clear();
+ }
+
private static class QuickstepWidgetHolderListener
implements AppWidgetHost.AppWidgetHostListener {
@@ -288,21 +296,21 @@
}
@Override
- @WorkerThread
+ @AnyThread
public void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo info) {
mRemoteViews = null;
executeOnMainExecutor(KEY_PROVIDER_UPDATE, info);
}
@Override
- @WorkerThread
+ @AnyThread
public void updateAppWidget(@Nullable RemoteViews views) {
mRemoteViews = views;
executeOnMainExecutor(KEY_VIEWS_UPDATE, mRemoteViews);
}
@Override
- @WorkerThread
+ @AnyThread
public void onViewDataChanged(int viewId) {
executeOnMainExecutor(KEY_VIEW_DATA_CHANGED, viewId);
}
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index 9b65a31..f582be0 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -63,7 +63,8 @@
launcher.dragController.cancelDrag()
launcher.workspace.clearDropTargets()
launcher.workspace.removeAllWorkspaceScreens()
- launcher.appWidgetHolder.clearViews()
+ // Avoid clearing the widget update listeners for staying up-to-date with widget info
+ launcher.appWidgetHolder.clearWidgetViews()
launcher.hotseat?.resetLayout(launcher.deviceProfile.isVerticalBarLayout)
TraceHelper.INSTANCE.endSection()
}
diff --git a/src/com/android/launcher3/widget/LauncherWidgetHolder.java b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
index 15bd6ed..2fcf8c5 100644
--- a/src/com/android/launcher3/widget/LauncherWidgetHolder.java
+++ b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
@@ -103,7 +103,7 @@
if (WidgetsModel.GO_DISABLE_WIDGETS) {
return;
}
- setListeningFlag(true);
+
try {
mWidgetHost.startListening();
} catch (Exception e) {
@@ -115,6 +115,8 @@
// have been established by this point, and we will end up populating the
// widgets upon bind anyway. See issue 14255011 for more context.
}
+ // TODO: Investigate why widgetHost.startListening() always return non-empty updates
+ setListeningFlag(true);
updateDeferredView();
}
@@ -442,6 +444,13 @@
}
/**
+ * Clears all the internal widget views
+ */
+ public void clearWidgetViews() {
+ clearViews();
+ }
+
+ /**
* @return True if the host is listening to the updates, false otherwise
*/
public boolean isListening() {