Loading quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java +42 −34 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.util.Log; import android.util.SparseArray; import android.widget.RemoteViews; Loading @@ -33,14 +34,14 @@ 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; import com.android.launcher3.widget.LauncherWidgetHolder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.function.IntConsumer; Loading @@ -50,6 +51,8 @@ import java.util.function.IntConsumer; */ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { private static final String TAG = "QuickstepWidgetHolder"; private static final UpdateKey<AppWidgetProviderInfo> KEY_PROVIDER_UPDATE = AppWidgetHostView::onUpdateProviderInfo; private static final UpdateKey<RemoteViews> KEY_VIEWS_UPDATE = Loading @@ -63,6 +66,8 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { private static AppWidgetHost sWidgetHost = null; private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>(); private final @Nullable RemoteViews.InteractionHandler mInteractionHandler; private final @NonNull IntConsumer mAppWidgetRemovedCallback; Loading @@ -71,15 +76,14 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { // Map to all pending updated keyed with appWidgetId; private final SparseArray<PendingUpdate> mPendingUpdateMap = new SparseArray<>(); @Thunk QuickstepWidgetHolder(@NonNull Context context, private QuickstepWidgetHolder(@NonNull Context context, @Nullable IntConsumer appWidgetRemovedCallback, @Nullable RemoteViews.InteractionHandler interactionHandler) { super(context, appWidgetRemovedCallback); mAppWidgetRemovedCallback = appWidgetRemovedCallback != null ? appWidgetRemovedCallback : i -> {}; mInteractionHandler = interactionHandler; sHolders.add(this); MAIN_EXECUTOR.execute(() -> sHolders.add(this)); } @Override Loading Loading @@ -107,11 +111,7 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { 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); AppWidgetHostView view = mViews.get(widgetId); if (view == null) { continue; } Loading @@ -131,7 +131,16 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { mPendingUpdateMap.clear(); } private <T> void addPendingAction(int widgetId, UpdateKey<T> key, T data) { private <T> void onWidgetUpdate(int widgetId, UpdateKey<T> key, T data) { if (isListening()) { AppWidgetHostView view = mViews.get(widgetId); if (view == null) { return; } key.accept(view, data); return; } PendingUpdate pendingUpdate = mPendingUpdateMap.get(widgetId); if (pendingUpdate == null) { pendingUpdate = new PendingUpdate(); Loading Loading @@ -167,7 +176,11 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { */ @Override public void destroy() { sHolders.remove(this); try { MAIN_EXECUTOR.submit(() -> sHolders.remove(this)).get(); } catch (Exception e) { Log.e(TAG, "Failed to remove self from holder list", e); } } @Override Loading Loading @@ -228,15 +241,16 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { } widgetView.setInteractionHandler(mInteractionHandler); widgetView.setAppWidget(appWidgetId, appWidget); mViews.put(appWidgetId, widgetView); QuickstepWidgetHolderListener listener = sListeners.get(appWidgetId); if (listener == null) { listener = new QuickstepWidgetHolderListener(appWidgetId, this, widgetView); listener = new QuickstepWidgetHolderListener(appWidgetId); sWidgetHost.setListener(appWidgetId, listener); sListeners.put(appWidgetId, listener); } else { listener.resetView(this, widgetView); } RemoteViews remoteViews = listener.addHolder(this); widgetView.updateAppWidget(remoteViews); return widgetView; } Loading @@ -247,31 +261,30 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { @Override public void clearViews() { for (int i = sListeners.size() - 1; i >= 0; i--) { sListeners.valueAt(i).mView.remove(this); sListeners.valueAt(i).mListeningHolders.remove(this); } } private static class QuickstepWidgetHolderListener implements AppWidgetHost.AppWidgetHostListener { @NonNull private final Map<QuickstepWidgetHolder, AppWidgetHostView> mView = new WeakHashMap<>(); // Static listeners should use a set that is backed by WeakHashMap to avoid memory leak private final Set<QuickstepWidgetHolder> mListeningHolders = Collections.newSetFromMap( new WeakHashMap<>()); private final int mWidgetId; @Nullable private RemoteViews mRemoteViews = null; private @Nullable RemoteViews mRemoteViews; QuickstepWidgetHolderListener(int widgetId, @NonNull QuickstepWidgetHolder holder, @NonNull LauncherAppWidgetHostView view) { QuickstepWidgetHolderListener(int widgetId) { mWidgetId = widgetId; mView.put(holder, view); } @UiThread public void resetView(@NonNull QuickstepWidgetHolder holder, @NonNull AppWidgetHostView view) { mView.put(holder, view); view.updateAppWidget(mRemoteViews); @Nullable public RemoteViews addHolder(@NonNull QuickstepWidgetHolder holder) { mListeningHolders.add(holder); return mRemoteViews; } @Override Loading @@ -295,13 +308,8 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { } 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); } })); MAIN_EXECUTOR.execute(() -> mListeningHolders.forEach(holder -> holder.onWidgetUpdate(mWidgetId, key, data))); } } Loading Loading
quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java +42 −34 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.util.Log; import android.util.SparseArray; import android.widget.RemoteViews; Loading @@ -33,14 +34,14 @@ 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; import com.android.launcher3.widget.LauncherWidgetHolder; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.function.BiConsumer; import java.util.function.IntConsumer; Loading @@ -50,6 +51,8 @@ import java.util.function.IntConsumer; */ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { private static final String TAG = "QuickstepWidgetHolder"; private static final UpdateKey<AppWidgetProviderInfo> KEY_PROVIDER_UPDATE = AppWidgetHostView::onUpdateProviderInfo; private static final UpdateKey<RemoteViews> KEY_VIEWS_UPDATE = Loading @@ -63,6 +66,8 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { private static AppWidgetHost sWidgetHost = null; private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>(); private final @Nullable RemoteViews.InteractionHandler mInteractionHandler; private final @NonNull IntConsumer mAppWidgetRemovedCallback; Loading @@ -71,15 +76,14 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { // Map to all pending updated keyed with appWidgetId; private final SparseArray<PendingUpdate> mPendingUpdateMap = new SparseArray<>(); @Thunk QuickstepWidgetHolder(@NonNull Context context, private QuickstepWidgetHolder(@NonNull Context context, @Nullable IntConsumer appWidgetRemovedCallback, @Nullable RemoteViews.InteractionHandler interactionHandler) { super(context, appWidgetRemovedCallback); mAppWidgetRemovedCallback = appWidgetRemovedCallback != null ? appWidgetRemovedCallback : i -> {}; mInteractionHandler = interactionHandler; sHolders.add(this); MAIN_EXECUTOR.execute(() -> sHolders.add(this)); } @Override Loading Loading @@ -107,11 +111,7 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { 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); AppWidgetHostView view = mViews.get(widgetId); if (view == null) { continue; } Loading @@ -131,7 +131,16 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { mPendingUpdateMap.clear(); } private <T> void addPendingAction(int widgetId, UpdateKey<T> key, T data) { private <T> void onWidgetUpdate(int widgetId, UpdateKey<T> key, T data) { if (isListening()) { AppWidgetHostView view = mViews.get(widgetId); if (view == null) { return; } key.accept(view, data); return; } PendingUpdate pendingUpdate = mPendingUpdateMap.get(widgetId); if (pendingUpdate == null) { pendingUpdate = new PendingUpdate(); Loading Loading @@ -167,7 +176,11 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { */ @Override public void destroy() { sHolders.remove(this); try { MAIN_EXECUTOR.submit(() -> sHolders.remove(this)).get(); } catch (Exception e) { Log.e(TAG, "Failed to remove self from holder list", e); } } @Override Loading Loading @@ -228,15 +241,16 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { } widgetView.setInteractionHandler(mInteractionHandler); widgetView.setAppWidget(appWidgetId, appWidget); mViews.put(appWidgetId, widgetView); QuickstepWidgetHolderListener listener = sListeners.get(appWidgetId); if (listener == null) { listener = new QuickstepWidgetHolderListener(appWidgetId, this, widgetView); listener = new QuickstepWidgetHolderListener(appWidgetId); sWidgetHost.setListener(appWidgetId, listener); sListeners.put(appWidgetId, listener); } else { listener.resetView(this, widgetView); } RemoteViews remoteViews = listener.addHolder(this); widgetView.updateAppWidget(remoteViews); return widgetView; } Loading @@ -247,31 +261,30 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { @Override public void clearViews() { for (int i = sListeners.size() - 1; i >= 0; i--) { sListeners.valueAt(i).mView.remove(this); sListeners.valueAt(i).mListeningHolders.remove(this); } } private static class QuickstepWidgetHolderListener implements AppWidgetHost.AppWidgetHostListener { @NonNull private final Map<QuickstepWidgetHolder, AppWidgetHostView> mView = new WeakHashMap<>(); // Static listeners should use a set that is backed by WeakHashMap to avoid memory leak private final Set<QuickstepWidgetHolder> mListeningHolders = Collections.newSetFromMap( new WeakHashMap<>()); private final int mWidgetId; @Nullable private RemoteViews mRemoteViews = null; private @Nullable RemoteViews mRemoteViews; QuickstepWidgetHolderListener(int widgetId, @NonNull QuickstepWidgetHolder holder, @NonNull LauncherAppWidgetHostView view) { QuickstepWidgetHolderListener(int widgetId) { mWidgetId = widgetId; mView.put(holder, view); } @UiThread public void resetView(@NonNull QuickstepWidgetHolder holder, @NonNull AppWidgetHostView view) { mView.put(holder, view); view.updateAppWidget(mRemoteViews); @Nullable public RemoteViews addHolder(@NonNull QuickstepWidgetHolder holder) { mListeningHolders.add(holder); return mRemoteViews; } @Override Loading @@ -295,13 +308,8 @@ public final class QuickstepWidgetHolder extends LauncherWidgetHolder { } 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); } })); MAIN_EXECUTOR.execute(() -> mListeningHolders.forEach(holder -> holder.onWidgetUpdate(mWidgetId, key, data))); } } Loading