Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4d185e3 authored by Shamali Patwa's avatar Shamali Patwa Committed by Android (Google) Code Review
Browse files

Merge changes from topic "popup-refactor" into main

* changes:
  Delete the unused code from popup provider
  Update references that read popup data provider to use picker provider
  Update references that wrote widget data to popup data provider
  Move widget related listeners to widget picker data provider
  Define widget picker data provider separate from popup provider
  Create a separate class for widget related methods from popup provider
parents edc93ed7 ecf35935
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -48,11 +47,11 @@ import com.android.launcher3.model.WidgetPredictionsRequester;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;

import java.util.ArrayList;
import java.util.HashSet;
@@ -110,8 +109,8 @@ public class WidgetPickerActivity extends BaseActivity {
    private WidgetsModel mModel;
    private LauncherAppState mApp;
    private WidgetPredictionsRequester mWidgetPredictionsRequester;
    private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {
    });
    private final WidgetPickerDataProvider mWidgetPickerDataProvider =
            new WidgetPickerDataProvider();

    private int mDesiredWidgetWidth;
    private int mDesiredWidgetHeight;
@@ -215,8 +214,8 @@ public class WidgetPickerActivity extends BaseActivity {

    @NonNull
    @Override
    public PopupDataProvider getPopupDataProvider() {
        return mPopupDataProvider;
    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
        return mWidgetPickerDataProvider;
    }

    @Override
@@ -293,8 +292,6 @@ public class WidgetPickerActivity extends BaseActivity {
    private void refreshAndBindWidgets() {
        MODEL_EXECUTOR.execute(() -> {
            LauncherAppState app = LauncherAppState.getInstance(this);
            Context context = app.getContext();

            mModel.update(app, null);
            bindWidgets(mModel.getWidgetsByPackageItem());
            // Open sheet once widgets are available, so that it doesn't interrupt the open
@@ -317,7 +314,8 @@ public class WidgetPickerActivity extends BaseActivity {
                shouldShowDefaultWidgets() ? builder.build(widgets,
                        mDefaultWidgetsFilter) : List.of();

        MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(allWidgets, defaultWidgets));
        MAIN_EXECUTOR.execute(
                () -> mWidgetPickerDataProvider.setWidgets(allWidgets, defaultWidgets));
    }

    private void openWidgetsSheet() {
@@ -332,7 +330,7 @@ public class WidgetPickerActivity extends BaseActivity {
    private void bindRecommendedWidgets(List<ItemInfo> recommendedWidgets) {
        // Bind recommendations once picker has finished open animation.
        MAIN_EXECUTOR.getHandler().postDelayed(
                () -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets),
                () -> mWidgetPickerDataProvider.setWidgetRecommendations(recommendedWidgets),
                mDeviceProfile.bottomSheetOpenDuration);
    }

+1 −1
Original line number Diff line number Diff line
@@ -515,7 +515,7 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
        } else if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION) {
            mHotseatPredictionController.setPredictedItems(item);
        } else if (item.containerId == Favorites.CONTAINER_WIDGETS_PREDICTION) {
            getPopupDataProvider().setRecommendedWidgets(item.items);
            getWidgetPickerDataProvider().setWidgetRecommendations(item.items);
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@ import com.android.launcher3.widget.WidgetManagerHelper;
import com.android.launcher3.widget.custom.CustomWidgetManager;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.picker.WidgetsFullSheet;
import com.android.launcher3.widget.picker.model.WidgetPickerDataProvider;
import com.android.launcher3.widget.util.WidgetSizes;
import com.android.systemui.plugins.LauncherOverlayPlugin;
import com.android.systemui.plugins.PluginListener;
@@ -371,6 +372,7 @@ public class Launcher extends StatefulActivity<LauncherState>
    private LauncherAccessibilityDelegate mAccessibilityDelegate;

    private PopupDataProvider mPopupDataProvider;
    private WidgetPickerDataProvider mWidgetPickerDataProvider;

    // We only want to get the SharedPreferences once since it does an FS stat each time we get
    // it from the context.
@@ -532,6 +534,7 @@ public class Launcher extends StatefulActivity<LauncherState>
                mFocusHandler, new CellLayout(mWorkspace.getContext(), mWorkspace));

        mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
        mWidgetPickerDataProvider = new WidgetPickerDataProvider();

        boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this);
        if (internalStateHandled) {
@@ -2702,6 +2705,7 @@ public class Launcher extends StatefulActivity<LauncherState>
        mDragLayer.dump(prefix, writer);
        mStateManager.dump(prefix, writer);
        mPopupDataProvider.dump(prefix, writer);
        mWidgetPickerDataProvider.dump(prefix, writer);
        mDeviceProfile.dump(this, prefix, writer);
        mAppsView.getAppsStore().dump(prefix, writer);

@@ -3011,6 +3015,12 @@ public class Launcher extends StatefulActivity<LauncherState>
        return mPopupDataProvider;
    }

    @NonNull
    @Override
    public WidgetPickerDataProvider getWidgetPickerDataProvider() {
        return mWidgetPickerDataProvider;
    }

    @Override
    public DotInfo getDotInfoForItem(ItemInfo info) {
        return mPopupDataProvider.getDotInfoForItem(info);
+4 −3
Original line number Diff line number Diff line
@@ -254,8 +254,8 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks {
        PopupContainerWithArrow.dismissInvalidPopup(launcher)
    }

    override fun bindAllWidgets(allWidgets: List<WidgetsListBaseEntry?>?) {
        launcher.popupDataProvider.allWidgets = allWidgets
    override fun bindAllWidgets(allWidgets: List<WidgetsListBaseEntry>) {
        launcher.widgetPickerDataProvider.setWidgets(allWidgets, /* defaultWidgets= */ listOf())
    }

    /** Returns the ids of the workspaces to bind. */
@@ -304,7 +304,8 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks {
        }

        val widgetsListBaseEntry: WidgetsListBaseEntry =
            launcher.popupDataProvider.allWidgets.firstOrNull { item: WidgetsListBaseEntry ->
            launcher.widgetPickerDataProvider.get().allWidgets.firstOrNull {
                item: WidgetsListBaseEntry ->
                item.mPkgItem.packageName == BuildConfig.APPLICATION_ID
            } ?: return

+0 −136
Original line number Diff line number Diff line
@@ -24,28 +24,20 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.picker.WidgetRecommendationCategory;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Provides data for the popup menu that appears after long-clicking on apps.
@@ -62,18 +54,6 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
    /** Maps packages to their DotInfo's . */
    private Map<PackageUserKey, DotInfo> mPackageUserToDotInfos = new HashMap<>();

    /** All installed widgets. */
    private List<WidgetsListBaseEntry> mAllWidgets = List.of();
    /**
     * Selectively chosen installed widgets which may be preferred for default display over the list
     * of all widgets.
     */
    private List<WidgetsListBaseEntry> mDefaultWidgets = List.of();
    /** Widgets that can be recommended to the users. */
    private List<ItemInfo> mRecommendedWidgets = List.of();

    private PopupDataChangeListener mChangeListener = PopupDataChangeListener.INSTANCE;

    public PopupDataProvider(Consumer<Predicate<PackageUserKey>> notificationDotsChangeListener) {
        mNotificationDotsChangeListener = notificationDotsChangeListener;
    }
@@ -188,124 +168,8 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
        })) ? dotInfo : null;
    }

    /**
     * Sets a list of recommended widgets ordered by their order of appearance in the widgets
     * recommendation UI.
     */
    public void setRecommendedWidgets(List<ItemInfo> recommendedWidgets) {
        mRecommendedWidgets = recommendedWidgets;
        mChangeListener.onRecommendedWidgetsBound();
    }

    public void setAllWidgets(List<WidgetsListBaseEntry> allWidgets) {
        mAllWidgets = allWidgets;
        mDefaultWidgets = List.of();
        mChangeListener.onWidgetsBound();
    }

    /**
     * Sets the list of widgets to be displayed by default and a complete list that can be displayed
     * when user chooses to show all widgets.
     */
    public void setAllWidgets(List<WidgetsListBaseEntry> allWidgets,
            List<WidgetsListBaseEntry> defaultWidgets) {
        mAllWidgets = allWidgets;
        mDefaultWidgets = defaultWidgets;
        mChangeListener.onWidgetsBound();
    }

    public void setChangeListener(PopupDataChangeListener listener) {
        mChangeListener = listener == null ? PopupDataChangeListener.INSTANCE : listener;
    }

    public List<WidgetsListBaseEntry> getAllWidgets() {
        return mAllWidgets;
    }

    /**
     * Returns a "selectively" chosen list of widgets that may be preferred to be shown by default
     * instead of a complete list.
     */
    public List<WidgetsListBaseEntry> getDefaultWidgets() {
        return mDefaultWidgets;
    }

    /** Returns a list of recommended widgets. */
    public List<WidgetItem> getRecommendedWidgets() {
        HashMap<ComponentKey, WidgetItem> allWidgetItems = new HashMap<>();
        mAllWidgets.stream()
                .filter(entry -> entry instanceof WidgetsListContentEntry)
                .forEach(entry -> ((WidgetsListContentEntry) entry).mWidgets
                        .forEach(widget -> allWidgetItems.put(
                                new ComponentKey(widget.componentName, widget.user), widget)));
        return mRecommendedWidgets.stream()
                .map(recommendedWidget -> allWidgetItems.get(
                        new ComponentKey(recommendedWidget.getTargetComponent(),
                                recommendedWidget.user)))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /** Returns the recommended widgets mapped by their category. */
    @NonNull
    public Map<WidgetRecommendationCategory, List<WidgetItem>> getCategorizedRecommendedWidgets() {
        Map<ComponentKey, WidgetItem> allWidgetItems = mAllWidgets.stream()
                .filter(entry -> entry instanceof WidgetsListContentEntry)
                .flatMap(entry -> entry.mWidgets.stream())
                .distinct()
                .collect(Collectors.toMap(
                        widget -> new ComponentKey(widget.componentName, widget.user),
                        Function.identity()
                ));
        return mRecommendedWidgets.stream()
                .filter(itemInfo -> itemInfo instanceof PendingAddWidgetInfo
                        && ((PendingAddWidgetInfo) itemInfo).recommendationCategory != null)
                .collect(Collectors.groupingBy(
                        it -> ((PendingAddWidgetInfo) it).recommendationCategory,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.stream()
                                        .map(it -> allWidgetItems.get(
                                                new ComponentKey(it.getTargetComponent(),
                                                        it.user)))
                                        .filter(Objects::nonNull)
                                        .collect(Collectors.toList())
                        )
                ));
    }

    public List<WidgetItem> getWidgetsForPackageUser(PackageUserKey packageUserKey) {
        return mAllWidgets.stream()
                .filter(row -> row instanceof WidgetsListContentEntry
                        && row.mPkgItem.packageName.equals(packageUserKey.mPackageName))
                .flatMap(row -> ((WidgetsListContentEntry) row).mWidgets.stream())
                .filter(widget -> packageUserKey.mUser.equals(widget.user))
                .collect(Collectors.toList());
    }

    /** Gets the WidgetsListContentEntry for the currently selected header. */
    public WidgetsListContentEntry getSelectedAppWidgets(PackageUserKey packageUserKey,
            boolean useDefault) {
        List<WidgetsListBaseEntry> widgets = useDefault ? mDefaultWidgets : mAllWidgets;
        return (WidgetsListContentEntry) widgets.stream()
                .filter(row -> row instanceof WidgetsListContentEntry
                        && PackageUserKey.fromPackageItemInfo(row.mPkgItem).equals(packageUserKey))
                .findAny()
                .orElse(null);
    }

    public void dump(String prefix, PrintWriter writer) {
        writer.println(prefix + "PopupDataProvider:");
        writer.println(prefix + "\tmPackageUserToDotInfos:" + mPackageUserToDotInfos);
    }

    public interface PopupDataChangeListener {

        PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { };

        default void onWidgetsBound() { }

        /** A callback to get notified when recommended widgets are bound. */
        default void onRecommendedWidgetsBound() { }
    }
}
Loading