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

Commit 647be66c authored by Hyunyoung Song's avatar Hyunyoung Song Committed by Android (Google) Code Review
Browse files

Merge "Enabling Private Space Container in Launcher." into main

parents 1da44348 739b3c9f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVA
import static com.android.launcher3.model.LoaderTask.SMARTSPACE_ON_HOME_SCREEN;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.NOTIFICATION_BADGING_URI;
import static com.android.launcher3.util.SettingsCache.PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI;

import android.content.ComponentName;
import android.content.Context;
@@ -166,6 +167,8 @@ public class LauncherAppState implements SafeCloseable {
        onNotificationSettingsChanged(settingsCache.getValue(NOTIFICATION_BADGING_URI));
        mOnTerminateCallback.add(() ->
                settingsCache.unregister(NOTIFICATION_BADGING_URI, notificationLister));
        // Register an observer to notify Launcher about Private Space settings toggle.
        registerPrivateSpaceHideWhenLockListener(settingsCache);
    }

    public LauncherAppState(Context context, @Nullable String iconCacheFileName) {
@@ -188,6 +191,18 @@ public class LauncherAppState implements SafeCloseable {
        }
    }

    private void registerPrivateSpaceHideWhenLockListener(SettingsCache settingsCache) {
        SettingsCache.OnChangeListener psHideWhenLockChangedListener =
                this::onPrivateSpaceHideWhenLockChanged;
        settingsCache.register(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, psHideWhenLockChangedListener);
        mOnTerminateCallback.add(() -> settingsCache.unregister(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI,
                psHideWhenLockChangedListener));
    }

    private void onPrivateSpaceHideWhenLockChanged(boolean isPrivateSpaceHideOnLockEnabled) {
        mModel.forceReload();
    }

    private void refreshAndReloadLauncher() {
        LauncherIcons.clearPool();
        mIconCache.updateIconParams(
+35 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.launcher3.allapps;

import static com.android.launcher3.Flags.enableExpandingPauseWorkButton;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
@@ -69,6 +70,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.R;
@@ -95,6 +97,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * All apps container view with search support for use in a dragging activity.
@@ -133,6 +136,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
    protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
            Process.myUserHandle());
    protected WorkProfileManager mWorkManager;
    protected final PrivateProfileManager mPrivateProfileManager;
    protected final Point mFastScrollerOffset = new Point();
    protected final int mScrimColor;
    protected final float mHeaderThreshold;
@@ -175,6 +179,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
    protected SearchAdapterProvider<?> mMainAdapterProvider;
    private View mBottomSheetHandleArea;
    private boolean mHasWorkApps;
    private boolean mHasPrivateApps;
    private float[] mBottomSheetCornerRadii;
    private ScrimView mScrimView;
    private int mHeaderColor;
@@ -184,6 +189,8 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
    private int mTabsProtectionAlpha;
    @Nullable private AllAppsTransitionController mAllAppsTransitionController;

    private PrivateSpaceHeaderViewController mPrivateSpaceHeaderViewController;

    public ActivityAllAppsContainerView(Context context) {
        this(context, null);
    }
@@ -207,6 +214,11 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
                this,
                mActivityContext.getStatsLogManager(),
                UserCache.INSTANCE.get(mActivityContext));
        mPrivateProfileManager = new PrivateProfileManager(
                mActivityContext.getSystemService(UserManager.class),
                this,
                mActivityContext.getStatsLogManager(),
                UserCache.INSTANCE.get(mActivityContext));
        mAH = Arrays.asList(null, null, null);
        mNavBarScrimPaint = new Paint();
        mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
@@ -246,13 +258,20 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
     */
    protected void initContent() {
        mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
        if (Flags.enablePrivateSpace()) {
            mPrivateSpaceHeaderViewController =
                    new PrivateSpaceHeaderViewController(mPrivateProfileManager);
        }

        mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
                new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, null)));
                new AlphabeticalAppsList<>(mActivityContext,
                        mAllAppsStore,
                        null,
                        mPrivateProfileManager)));
        mAH.set(AdapterHolder.WORK, new AdapterHolder(AdapterHolder.WORK,
                new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, mWorkManager)));
                new AlphabeticalAppsList<>(mActivityContext, mAllAppsStore, mWorkManager, null)));
        mAH.set(SEARCH, new AdapterHolder(SEARCH,
                new AlphabeticalAppsList<>(mActivityContext, null, null)));
                new AlphabeticalAppsList<>(mActivityContext, null, null, null)));

        getLayoutInflater().inflate(R.layout.all_apps_content, this);
        mHeader = findViewById(R.id.all_apps_header);
@@ -592,7 +611,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
        } else {
            mainRecyclerView = findViewById(R.id.apps_list_view);
            workRecyclerView = null;
            mAH.get(AdapterHolder.MAIN).setup(mainRecyclerView, null);
            mAH.get(AdapterHolder.MAIN).setup(mainRecyclerView, mPersonalMatcher);
            mAH.get(AdapterHolder.WORK).mRecyclerView = null;
        }
        setUpCustomRecyclerViewPool(
@@ -860,7 +879,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>

    protected BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> appsList) {
        return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
                mMainAdapterProvider);
                mMainAdapterProvider, mPrivateSpaceHeaderViewController);
    }

    // TODO(b/216683257): Remove when Taskbar All Apps supports search.
@@ -973,13 +992,19 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>

    @VisibleForTesting
    public void onAppsUpdated() {
        mHasWorkApps = mWorkManager.hasWorkApps();
        mHasWorkApps = Stream.of(mAllAppsStore.getApps())
                .anyMatch(mWorkManager.getItemInfoMatcher());
        mHasPrivateApps = Stream.of(mAllAppsStore.getApps())
                .anyMatch(mPrivateProfileManager.getItemInfoMatcher());
        if (!isSearching()) {
            rebindAdapters();
        }
        if (mHasWorkApps) {
            mWorkManager.reset();
        }
        if (mHasPrivateApps) {
            mPrivateProfileManager.reset();
        }

        mActivityContext.getStatsLogManager().logger()
                .withCardinality(mAllAppsStore.getApps().length)
@@ -1245,6 +1270,10 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
        return mAH.get(SEARCH).mAppsList;
    }

    public AlphabeticalAppsList<T> getPersonalAppList() {
        return mAH.get(MAIN).mAppsList;
    }

    public FloatingHeaderView getFloatingHeaderView() {
        return mHeader;
    }
+3 −2
Original line number Diff line number Diff line
@@ -73,8 +73,9 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends


    public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
            AlphabeticalAppsList apps, SearchAdapterProvider<?> adapterProvider) {
        super(activityContext, inflater, apps, adapterProvider);
            AlphabeticalAppsList apps, SearchAdapterProvider<?> adapterProvider,
            PrivateSpaceHeaderViewController privateSpaceHeaderViewController) {
        super(activityContext, inflater, apps, adapterProvider, privateSpaceHeaderViewController);
        mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
        mGridLayoutMgr.setSpanSizeLookup(new GridSpanSizer());
        setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
+56 −15
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DiffUtil;

import com.android.launcher3.Flags;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -47,6 +48,8 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement

    private final WorkProfileManager mWorkProviderManager;

    private final PrivateProfileManager mPrivateProviderManager;

    /**
     * Info about a fast scroller section, depending if sections are merged, the fast scroller
     * sections will not be the same set as the section headers.
@@ -68,6 +71,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement

    // The set of apps from the system
    private final List<AppInfo> mApps = new ArrayList<>();
    private final List<AppInfo> mPrivateApps = new ArrayList<>();
    @Nullable
    private final AllAppsStore<T> mAllAppsStore;

@@ -87,11 +91,12 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
    private Predicate<ItemInfo> mItemFilter;

    public AlphabeticalAppsList(Context context, @Nullable AllAppsStore<T> appsStore,
            WorkProfileManager workProfileManager) {
            WorkProfileManager workProfileManager, PrivateProfileManager privateProfileManager) {
        mAllAppsStore = appsStore;
        mActivityContext = ActivityContext.lookupContext(context);
        mAppNameComparator = new AppInfoComparator(context);
        mWorkProviderManager = workProfileManager;
        mPrivateProviderManager = privateProfileManager;
        mNumAppsPerRowAllApps = mActivityContext.getDeviceProfile().numShownAllAppsColumns;
        if (mAllAppsStore != null) {
            mAllAppsStore.addUpdateListener(this);
@@ -197,12 +202,20 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
        }
        // Sort the list of apps
        mApps.clear();
        mPrivateApps.clear();

        Stream<AppInfo> appSteam = Stream.of(mAllAppsStore.getApps());
        Stream<AppInfo> privateAppStream = Stream.of(mAllAppsStore.getApps());

        if (!hasSearchResults() && mItemFilter != null) {
            appSteam = appSteam.filter(mItemFilter);
            if (mPrivateProviderManager != null) {
                privateAppStream = privateAppStream
                        .filter(mPrivateProviderManager.getItemInfoMatcher());
            }
        }
        appSteam = appSteam.sorted(mAppNameComparator);
        privateAppStream = privateAppStream.sorted(mAppNameComparator);

        // As a special case for some languages (currently only Simplified Chinese), we may need to
        // coalesce sections
@@ -221,6 +234,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
        }

        appSteam.forEachOrdered(mApps::add);
        privateAppStream.forEachOrdered(mPrivateApps::add);
        // Recompose the set of adapter items from the current set of apps
        if (mSearchResults.isEmpty()) {
            updateAdapterItems();
@@ -250,18 +264,10 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
                addApps = mWorkProviderManager.shouldShowWorkApps();
            }
            if (addApps) {
                String lastSectionName = null;
                for (AppInfo info : mApps) {
                    mAdapterItems.add(AdapterItem.asApp(info));

                    String sectionName = info.sectionName;
                    // Create a new section if the section names do not match
                    if (!sectionName.equals(lastSectionName)) {
                        lastSectionName = sectionName;
                        mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, position));
                    }
                    position++;
                addAppsWithSections(mApps, position);
            }
            if (Flags.enablePrivateSpace()) {
                addPrivateSpaceItems(position);
            }
        }
        mAccessibilityResultsCount = (int) mAdapterItems.stream()
@@ -275,7 +281,8 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
            int rowIndex = -1;
            for (AdapterItem item : mAdapterItems) {
                item.rowIndex = 0;
                if (BaseAllAppsAdapter.isDividerViewType(item.viewType)) {
                if (BaseAllAppsAdapter.isDividerViewType(item.viewType)
                        || BaseAllAppsAdapter.isPrivateSpaceHeaderView(item.viewType)) {
                    numAppsInSection = 0;
                } else if (BaseAllAppsAdapter.isIconViewType(item.viewType)) {
                    if (numAppsInSection % mNumAppsPerRowAllApps == 0) {
@@ -297,6 +304,40 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
        }
    }

    void addPrivateSpaceItems(int position) {
        if (mPrivateProviderManager != null
                && !mPrivateProviderManager.isPrivateSpaceHidden()
                && !mPrivateApps.isEmpty()) {
            // Always add PS Header if Space is present and visible.
            position += mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems);
            int privateSpaceState = mPrivateProviderManager.getCurrentState();
            switch (privateSpaceState) {
                case PrivateProfileManager.STATE_DISABLED:
                case PrivateProfileManager.STATE_TRANSITION:
                    break;
                case PrivateProfileManager.STATE_ENABLED:
                    // Add PS Apps only in Enabled State.
                    addAppsWithSections(mPrivateApps, position);
                    break;
            }
        }
    }

    private void addAppsWithSections(List<AppInfo> appList, int startPosition) {
        String lastSectionName = null;
        for (AppInfo info : appList) {
            mAdapterItems.add(AdapterItem.asApp(info));

            String sectionName = info.sectionName;
            // Create a new section if the section names do not match
            if (!sectionName.equals(lastSectionName)) {
                lastSectionName = sectionName;
                mFastScrollerSections.add(new FastScrollSectionInfo(sectionName, startPosition));
            }
            startPosition++;
        }
    }

    private static class MyDiffCallback extends DiffUtil.Callback {

        private final List<AdapterItem> mOldList;
+20 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;
@@ -139,9 +140,16 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
    protected final OnClickListener mOnIconClickListener;
    protected final OnLongClickListener mOnIconLongClickListener;
    protected OnFocusChangeListener mIconFocusListener;
    private final PrivateSpaceHeaderViewController mPrivateSpaceHeaderViewController;

    public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
            AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider) {
        this(activityContext, inflater, apps, adapterProvider, null);
    }

    public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
            AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider,
            PrivateSpaceHeaderViewController privateSpaceHeaderViewController) {
        mActivityContext = activityContext;
        mApps = apps;
        mLayoutInflater = inflater;
@@ -150,6 +158,7 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
        mOnIconLongClickListener = mActivityContext.getAllAppsItemLongClickListener();

        mAdapterProvider = adapterProvider;
        mPrivateSpaceHeaderViewController = privateSpaceHeaderViewController;
    }

    /** Checks if the passed viewType represents all apps divider. */
@@ -162,6 +171,11 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
        return isViewType(viewType, VIEW_TYPE_MASK_ICON);
    }

    /** Checks if the passed viewType represents private space header. */
    public static boolean isPrivateSpaceHeaderView(int viewType) {
        return isViewType(viewType, VIEW_TYPE_MASK_PRIVATE_SPACE_HEADER);
    }

    public void setIconFocusListener(OnFocusChangeListener focusListener) {
        mIconFocusListener = focusListener;
    }
@@ -230,6 +244,12 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
                break;
            }
            case VIEW_TYPE_PRIVATE_SPACE_HEADER:
                RelativeLayout psHeaderLayout = holder.itemView.findViewById(
                        R.id.ps_header_layout);
                assert mPrivateSpaceHeaderViewController != null;
                assert psHeaderLayout != null;
                mPrivateSpaceHeaderViewController.addPrivateSpaceHeaderViewElements(psHeaderLayout);
                break;
            case VIEW_TYPE_ALL_APPS_DIVIDER:
            case VIEW_TYPE_WORK_DISABLED_CARD:
                // nothing to do
Loading