mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 10:48:19 +00:00
Merge "Deferred widget update" into tm-qpr-dev am: 3f07d154fb
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/21405131 Change-Id: I20005f8053c4b8935b040febc0dc4efff074ac98 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -32,6 +32,7 @@ import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
@@ -41,13 +42,21 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
/**
|
||||
* {@link LauncherWidgetHolder} that puts the app widget host in the background
|
||||
*/
|
||||
public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
|
||||
private static final UpdateKey<AppWidgetProviderInfo> KEY_PROVIDER_UPDATE =
|
||||
AppWidgetHostView::onUpdateProviderInfo;
|
||||
private static final UpdateKey<RemoteViews> KEY_VIEWS_UPDATE =
|
||||
AppWidgetHostView::updateAppWidget;
|
||||
private static final UpdateKey<Integer> KEY_VIEW_DATA_CHANGED =
|
||||
AppWidgetHostView::onViewDataChanged;
|
||||
|
||||
private static final List<QuickstepWidgetHolder> sHolders = new ArrayList<>();
|
||||
private static final SparseArray<QuickstepWidgetHolderListener> sListeners =
|
||||
new SparseArray<>();
|
||||
@@ -59,6 +68,8 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
private final @NonNull IntConsumer mAppWidgetRemovedCallback;
|
||||
|
||||
private final ArrayList<ProviderChangedListener> mProviderChangedListeners = new ArrayList<>();
|
||||
// Map to all pending updated keyed with appWidgetId;
|
||||
private final SparseArray<PendingUpdate> mPendingUpdateMap = new SparseArray<>();
|
||||
|
||||
@Thunk
|
||||
QuickstepWidgetHolder(@NonNull Context context,
|
||||
@@ -90,6 +101,57 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
return sWidgetHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateDeferredView() {
|
||||
super.updateDeferredView();
|
||||
int count = mPendingUpdateMap.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
int widgetId = mPendingUpdateMap.keyAt(i);
|
||||
QuickstepWidgetHolderListener listener = sListeners.get(widgetId);
|
||||
if (listener == null) {
|
||||
continue;
|
||||
}
|
||||
AppWidgetHostView view = listener.mView.get(this);
|
||||
if (view == null) {
|
||||
continue;
|
||||
}
|
||||
PendingUpdate pendingUpdate = mPendingUpdateMap.valueAt(i);
|
||||
if (pendingUpdate == null) {
|
||||
continue;
|
||||
}
|
||||
if (pendingUpdate.providerInfo != null) {
|
||||
KEY_PROVIDER_UPDATE.accept(view, pendingUpdate.providerInfo);
|
||||
}
|
||||
if (pendingUpdate.remoteViews != null) {
|
||||
KEY_VIEWS_UPDATE.accept(view, pendingUpdate.remoteViews);
|
||||
}
|
||||
pendingUpdate.changedViews.forEach(
|
||||
viewId -> KEY_VIEW_DATA_CHANGED.accept(view, viewId));
|
||||
}
|
||||
mPendingUpdateMap.clear();
|
||||
}
|
||||
|
||||
private <T> void addPendingAction(int widgetId, UpdateKey<T> key, T data) {
|
||||
PendingUpdate pendingUpdate = mPendingUpdateMap.get(widgetId);
|
||||
if (pendingUpdate == null) {
|
||||
pendingUpdate = new PendingUpdate();
|
||||
mPendingUpdateMap.put(widgetId, pendingUpdate);
|
||||
}
|
||||
|
||||
if (KEY_PROVIDER_UPDATE.equals(key)) {
|
||||
// For provider change, remove all updates
|
||||
pendingUpdate.providerInfo = (AppWidgetProviderInfo) data;
|
||||
pendingUpdate.remoteViews = null;
|
||||
pendingUpdate.changedViews.clear();
|
||||
} else if (KEY_VIEWS_UPDATE.equals(key)) {
|
||||
// For views update, remove all previous updates, except the provider
|
||||
pendingUpdate.remoteViews = (RemoteViews) data;
|
||||
pendingUpdate.changedViews.clear();
|
||||
} else if (KEY_VIEW_DATA_CHANGED.equals(key)) {
|
||||
pendingUpdate.changedViews.add((Integer) data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the specified app widget from the host
|
||||
* @param appWidgetId The ID of the app widget to be deleted
|
||||
@@ -108,6 +170,12 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
sHolders.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldListen(int flags) {
|
||||
return (flags & (FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED))
|
||||
== (FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener that is triggered when the providers of the widgets are changed
|
||||
* @param listener The listener that notifies when the providers changed
|
||||
@@ -163,7 +231,7 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
|
||||
QuickstepWidgetHolderListener listener = sListeners.get(appWidgetId);
|
||||
if (listener == null) {
|
||||
listener = new QuickstepWidgetHolderListener(this, widgetView);
|
||||
listener = new QuickstepWidgetHolderListener(appWidgetId, this, widgetView);
|
||||
sWidgetHost.setListener(appWidgetId, listener);
|
||||
sListeners.put(appWidgetId, listener);
|
||||
} else {
|
||||
@@ -185,14 +253,17 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
|
||||
private static class QuickstepWidgetHolderListener
|
||||
implements AppWidgetHost.AppWidgetHostListener {
|
||||
|
||||
@NonNull
|
||||
private final Map<QuickstepWidgetHolder, AppWidgetHostView> mView = new WeakHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private RemoteViews mRemoteViews = null;
|
||||
private final int mWidgetId;
|
||||
|
||||
QuickstepWidgetHolderListener(@NonNull QuickstepWidgetHolder holder,
|
||||
@Nullable private RemoteViews mRemoteViews = null;
|
||||
|
||||
QuickstepWidgetHolderListener(int widgetId, @NonNull QuickstepWidgetHolder holder,
|
||||
@NonNull LauncherAppWidgetHostView view) {
|
||||
mWidgetId = widgetId;
|
||||
mView.put(holder, view);
|
||||
}
|
||||
|
||||
@@ -207,24 +278,30 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
@WorkerThread
|
||||
public void onUpdateProviderInfo(@Nullable AppWidgetProviderInfo info) {
|
||||
mRemoteViews = null;
|
||||
executeOnMainExecutor(v -> v.onUpdateProviderInfo(info));
|
||||
executeOnMainExecutor(KEY_PROVIDER_UPDATE, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WorkerThread
|
||||
public void updateAppWidget(@Nullable RemoteViews views) {
|
||||
mRemoteViews = views;
|
||||
executeOnMainExecutor(v -> v.updateAppWidget(mRemoteViews));
|
||||
executeOnMainExecutor(KEY_VIEWS_UPDATE, mRemoteViews);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WorkerThread
|
||||
public void onViewDataChanged(int viewId) {
|
||||
executeOnMainExecutor(v -> v.onViewDataChanged(viewId));
|
||||
executeOnMainExecutor(KEY_VIEW_DATA_CHANGED, viewId);
|
||||
}
|
||||
|
||||
private void executeOnMainExecutor(Consumer<AppWidgetHostView> consumer) {
|
||||
MAIN_EXECUTOR.execute(() -> mView.values().forEach(consumer));
|
||||
private <T> void executeOnMainExecutor(UpdateKey<T> key, T data) {
|
||||
MAIN_EXECUTOR.execute(() -> mView.forEach((holder, view) -> {
|
||||
if (holder.isListening()) {
|
||||
key.accept(view, data);
|
||||
} else {
|
||||
holder.addPendingAction(mWidgetId, key, data);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,4 +344,12 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder {
|
||||
return new QuickstepWidgetHolder(context, appWidgetRemovedCallback, interactionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PendingUpdate {
|
||||
public final IntSet changedViews = new IntSet();
|
||||
public AppWidgetProviderInfo providerInfo;
|
||||
public RemoteViews remoteViews;
|
||||
}
|
||||
|
||||
private interface UpdateKey<T> extends BiConsumer<AppWidgetHostView, T> { }
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ import java.util.function.IntConsumer;
|
||||
public class LauncherWidgetHolder {
|
||||
public static final int APPWIDGET_HOST_ID = 1024;
|
||||
|
||||
private static final int FLAG_LISTENING = 1;
|
||||
private static final int FLAG_STATE_IS_NORMAL = 1 << 1;
|
||||
private static final int FLAG_ACTIVITY_STARTED = 1 << 2;
|
||||
private static final int FLAG_ACTIVITY_RESUMED = 1 << 3;
|
||||
protected static final int FLAG_LISTENING = 1;
|
||||
protected static final int FLAG_STATE_IS_NORMAL = 1 << 1;
|
||||
protected static final int FLAG_ACTIVITY_STARTED = 1 << 2;
|
||||
protected static final int FLAG_ACTIVITY_RESUMED = 1 << 3;
|
||||
private static final int FLAGS_SHOULD_LISTEN =
|
||||
FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED | FLAG_ACTIVITY_RESUMED;
|
||||
|
||||
@@ -77,7 +77,7 @@ public class LauncherWidgetHolder {
|
||||
@NonNull
|
||||
private final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();
|
||||
|
||||
private int mFlags = FLAG_STATE_IS_NORMAL;
|
||||
protected int mFlags = FLAG_STATE_IS_NORMAL;
|
||||
|
||||
// TODO(b/191735836): Replace with ActivityOptions.KEY_SPLASH_SCREEN_STYLE when un-hidden
|
||||
private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle";
|
||||
@@ -115,6 +115,13 @@ public class LauncherWidgetHolder {
|
||||
// widgets upon bind anyway. See issue 14255011 for more context.
|
||||
}
|
||||
|
||||
updateDeferredView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update any views which have been deferred because the host was not listening.
|
||||
*/
|
||||
protected void updateDeferredView() {
|
||||
// We go in reverse order and inflate any deferred or cached widget
|
||||
for (int i = mViews.size() - 1; i >= 0; i--) {
|
||||
LauncherAppWidgetHostView view = mViews.valueAt(i);
|
||||
@@ -464,7 +471,7 @@ public class LauncherWidgetHolder {
|
||||
}
|
||||
|
||||
final boolean listening = isListening();
|
||||
if (!listening && (mFlags & FLAGS_SHOULD_LISTEN) == FLAGS_SHOULD_LISTEN) {
|
||||
if (!listening && shouldListen(mFlags)) {
|
||||
// Postpone starting listening until all flags are on.
|
||||
startListening();
|
||||
} else if (listening && (mFlags & FLAG_ACTIVITY_STARTED) == 0) {
|
||||
@@ -473,6 +480,14 @@ public class LauncherWidgetHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the holder should be listening for widget updates based
|
||||
* on the provided state flags.
|
||||
*/
|
||||
protected boolean shouldListen(int flags) {
|
||||
return (flags & FLAGS_SHOULD_LISTEN) == FLAGS_SHOULD_LISTEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the new LauncherWidgetHolder instance
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user