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

Commit d16a5745 authored by Rohit Goyal's avatar Rohit Goyal Committed by Android (Google) Code Review
Browse files

Merge "Add support for progress bar for archived apps in AllApps view." into main

parents 8cba27bc 04fe042e
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -933,9 +933,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
            if (mIcon instanceof PreloadIconDrawable) {
                preloadIconDrawable = (PreloadIconDrawable) mIcon;
                preloadIconDrawable.setLevel(progressLevel);
                // TODO(b/302115555): For archived apps, show icon as disabled if active session
                //  exists.
                preloadIconDrawable.setIsDisabled(info.getProgressLevel() == 0);
                preloadIconDrawable.setIsDisabled(isIconDisabled(info));
            } else {
                preloadIconDrawable = makePreloadIcon();
                setIcon(preloadIconDrawable);
@@ -960,11 +958,18 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
        final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);

        preloadDrawable.setLevel(progressLevel);
        // TODO(b/302115555): For archived apps, show icon as disabled if active session exists.
        preloadDrawable.setIsDisabled(info.getProgressLevel() == 0);
        preloadDrawable.setIsDisabled(isIconDisabled(info));
        return preloadDrawable;
    }

    private boolean isIconDisabled(ItemInfoWithIcon info) {
        if (info.isArchived()) {
            return info.getProgressLevel() == 0
                    && (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0;
        }
        return info.getProgressLevel() == 0;
    }

    public void applyDotState(ItemInfo itemInfo, boolean animate) {
        if (mIcon instanceof FastBitmapDrawable) {
            boolean wasDotted = mDotInfo != null;
+17 −4
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.launcher3.model;

import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ARCHIVED;

import android.content.ComponentName;
import android.content.Context;
@@ -53,6 +55,7 @@ import java.util.function.Predicate;
/**
 * Stores the list of all applications for the all apps view.
 */
@SuppressWarnings("NewApi")
public class AllAppsList {

    private static final String TAG = "AllAppsList";
@@ -200,13 +203,18 @@ public class AllAppsList {
            if (tgtComp != null && tgtComp.getPackageName().equals(installInfo.packageName)
                    && appInfo.user.equals(user)) {
                if (installInfo.state == PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING
                        || installInfo.state == PackageInstallInfo.STATUS_INSTALLING) {
                        || installInfo.state == PackageInstallInfo.STATUS_INSTALLING
                        // In case unarchival fails, we would want to keep the icon and update
                        // back the progress to 0 for the all apps view without removing the
                        // icon, which is contrary to what happens during normal app installation
                        // flow.
                        || (installInfo.state == PackageInstallInfo.STATUS_FAILED
                                && appInfo.isArchived())) {
                    if (appInfo.isAppStartable()
                            && installInfo.state == PackageInstallInfo.STATUS_INSTALLING) {
                            && installInfo.state == PackageInstallInfo.STATUS_INSTALLING
                            && !appInfo.isArchived()) {
                        continue;
                    }
                    // TODO(b/302115555): Handle the case when archived apps are to be updated
                    //  during unarchival start.
                    appInfo.setProgressLevel(installInfo);

                    updatedAppInfos.add(appInfo);
@@ -322,6 +330,11 @@ public class AllAppsList {
                            PackageManagerHelper.getLoadingProgress(info),
                            PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);
                    applicationInfo.intent = launchIntent;
                    if (enableSupportForArchiving() && info.getActivityInfo().isArchived) {
                        // In case an app is archived, the respective item flag corresponding to
                        // archiving should also be applied during package updates
                        applicationInfo.runtimeStatusFlags |= FLAG_ARCHIVED;
                    }

                    mDataChanged = true;
                }
+22 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.launcher3.model;

import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
import static com.android.launcher3.Flags.enableSupportForArchiving;
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
@@ -30,6 +31,7 @@ import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;

@@ -143,6 +145,7 @@ public class LoaderTask implements Runnable {
    private final UserManagerState mUserManagerState;
    protected final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap = new ArrayMap<>();
    private Map<ShortcutKey, ShortcutInfo> mShortcutKeyToPinnedShortcuts;
    private HashMap<PackageUserKey, SessionInfo> mInstallingPkgsCached;

    private boolean mStopped;

@@ -170,6 +173,7 @@ public class LoaderTask implements Runnable {
        mSessionHelper = InstallSessionHelper.INSTANCE.get(mApp.getContext());
        mIconCache = mApp.getIconCache();
        mUserManagerState = userManagerState;
        mInstallingPkgsCached = null;
    }

    protected synchronized void waitForIdle() {
@@ -417,6 +421,9 @@ public class LoaderTask implements Runnable {

            final HashMap<PackageUserKey, SessionInfo> installingPkgs =
                    mSessionHelper.getActiveSessions();
            if (enableSupportForArchiving()) {
                mInstallingPkgsCached = installingPkgs;
            }
            installingPkgs.forEach(mApp.getIconCache()::updateSessionCache);
            FileLog.d(TAG, "loadWorkspace: Packages with active install sessions: "
                    + installingPkgs.keySet().stream().map(info -> info.mPackageName).toList());
@@ -649,8 +656,20 @@ public class LoaderTask implements Runnable {
            for (int i = 0; i < apps.size(); i++) {
                LauncherActivityInfo app = apps.get(i);
                AppInfo appInfo = new AppInfo(app, user, quietMode);
                // TODO(b/302115555): Handle the case when archived apps with active sessions are
                //  loaded.
                if (enableSupportForArchiving() && app.getApplicationInfo().isArchived) {
                    // For archived apps, include progress info in case there is a pending
                    // install session post restart of device.
                    String appPackageName = app.getApplicationInfo().packageName;
                    SessionInfo si = mInstallingPkgsCached != null ? mInstallingPkgsCached.get(
                            new PackageUserKey(appPackageName, user))
                            : mSessionHelper.getActiveSessionInfo(user,
                                    appPackageName);
                    if (si != null) {
                        appInfo.runtimeStatusFlags |= FLAG_INSTALL_SESSION_ACTIVE;
                        appInfo.setProgressLevel((int) (si.getProgress() * 100),
                                PackageInstallInfo.STATUS_INSTALLING);
                    }
                }

                iconRequestInfos.add(new IconRequestInfo<>(
                        appInfo, app, /* useLowResIcon= */ false));
+17 −6
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import androidx.test.runner.AndroidJUnit4;

import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.tapl.AllApps;
import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.TestUtil;
@@ -143,16 +144,26 @@ public class TaplPromiseIconUiTest extends AbstractLauncherUiTest {
        assertThat(mDevice.executeShellCommand(String.format("pm archive %s", DUMMY_PACKAGE)))
                .isEqualTo("Success\n");

        final ItemOperator findPromiseApp = (info, view) ->
                info != null && TextUtils.equals(info.title, DUMMY_LABEL);

        // Create and add test session
        mSessionId = createSession(DUMMY_PACKAGE, /* label= */ "",
                Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8));

        // Verify promise icon is added
        waitForLauncherCondition("Test Promise App not found on workspace", launcher ->
                launcher.getWorkspace().getFirstMatch(findPromiseApp) != null);
        // Verify promise icon is added to all apps view. The icon may not be added to the
        // workspace even if there might be no icon present for archived app. But icon will
        // always be in all apps view. In case an icon is not added, an exception would be thrown.
        final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();

        // Wait for the promise icon to be added.
        waitForLauncherCondition(
                DUMMY_PACKAGE + " app was not found on all apps after being archived",
                launcher -> {
                    try {
                        allApps.getAppIcon(DUMMY_LABEL);
                    } catch (Throwable t) {
                        return false;
                    }
                    return true;
                });

        // Remove session
        mTargetContext.getPackageManager().getPackageInstaller().abandonSession(mSessionId);