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

Commit 2bd3d7d1 authored by Hyunyoung Song's avatar Hyunyoung Song
Browse files

Load PackageItemInfo in background thread to prevent ANR

- Decoupled widget model from widget view, and placed the
creation to LauncherModel.
- As a result packagemanager operation, iconcache retrieval is all done inside
LauncherModel on background thread
b/21311085
b/21325319

Change-Id: I294698527db58b89f3da558090a367530c058776
parent 3e4d5f20
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ import android.view.ViewParent;
import android.widget.TextView;

import com.android.launcher3.IconCache.IconLoadRequest;
import com.android.launcher3.widget.PackageItemInfo;
import com.android.launcher3.model.PackageItemInfo;

/**
 * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
+1 −1
Original line number Diff line number Diff line
@@ -42,9 +42,9 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PackageItemInfo;

import java.util.Collection;
import java.util.HashMap;
+10 −9
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -268,8 +269,9 @@ public class Launcher extends Activity
    // Main container view for the all apps screen.
    @Thunk AppsContainerView mAppsView;

    // Main container view for the widget tray screen.
    private WidgetsContainerView mWidgetsView;
    // Main container view and the model for the widget tray screen.
    @Thunk WidgetsContainerView mWidgetsView;
    @Thunk WidgetsModel mWidgetsModel;

    private boolean mAutoAdvanceRunning = false;
    private AppWidgetHostView mQsb;
@@ -4365,23 +4367,22 @@ public class Launcher extends Activity
        }
    }

    @Thunk ArrayList<Object> mWidgetsAndShortcuts;
    private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
            public void run() {
                bindAllPackages(mWidgetsAndShortcuts);
                bindAllPackages(mWidgetsModel);
            }
        };

    @Override
    public void bindAllPackages(final ArrayList<Object> widgetsAndShortcuts) {
    public void bindAllPackages(final WidgetsModel model) {
        if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
            mWidgetsAndShortcuts = widgetsAndShortcuts;
            mWidgetsModel = model;
            return;
        }

        if (mWidgetsView != null && widgetsAndShortcuts != null) {
            mWidgetsView.addWidgets(widgetsAndShortcuts, getPackageManager());
            mWidgetsAndShortcuts = null;
        if (mWidgetsView != null && model != null) {
            mWidgetsView.addWidgets(model);
            mWidgetsModel = null;
        }
    }

+10 −6
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.ManagedProfileHeuristic;
@@ -203,7 +204,7 @@ public class LauncherModel extends BroadcastReceiver
        public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
        public void bindComponentsRemoved(ArrayList<String> packageNames,
                        ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
        public void bindAllPackages(ArrayList<Object> widgetsAndShortcuts);
        public void bindAllPackages(WidgetsModel model);
        public void bindSearchablesChanged();
        public boolean isAllAppsButtonRank(int rank);
        public void onPageBoundSynchronously(int page);
@@ -3344,18 +3345,19 @@ public class LauncherModel extends BroadcastReceiver
        runOnWorkerThread(new Runnable(){
            @Override
            public void run() {
                final ArrayList<Object> list = getWidgetsAndShortcuts(context, refresh);
                final WidgetsModel model = createWidgetsModel(context, refresh);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Callbacks cb = getCallback();
                        if (callbacks == cb && cb != null) {
                            callbacks.bindAllPackages(list);
                            callbacks.bindAllPackages(model);
                        }
                    }
                });
                // update the Widget entries inside DB on the worker thread.
                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(list);
                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
                        model.getRawList());
            }
        });
    }
@@ -3365,13 +3367,15 @@ public class LauncherModel extends BroadcastReceiver
     *
     *  @see #loadAndBindWidgetsAndShortcuts
     */
    private ArrayList<Object> getWidgetsAndShortcuts(Context context, boolean refresh) {
    private WidgetsModel createWidgetsModel(Context context, boolean refresh) {
        PackageManager packageManager = context.getPackageManager();
        final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
        widgetsAndShortcuts.addAll(getWidgetProviders(context, refresh));
        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
        widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
        return widgetsAndShortcuts;
        WidgetsModel model = new WidgetsModel(context);
        model.addWidgetsAndShortcuts(widgetsAndShortcuts);
        return model;
    }

    @Thunk static boolean isPackageDisabled(Context context, String packageName,
+9 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -57,6 +58,8 @@ import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import junit.framework.Assert;

/**
 * Various utilities shared amongst the Launcher's classes.
 */
@@ -641,4 +644,10 @@ public final class Utilities {
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) &&
                (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
    }

    public static void assertWorkerThread() {
        if (LauncherAppState.isDogfoodBuild()) {
            Assert.assertTrue(LauncherModel.sWorkerThread.getThreadId() == Process.myTid());
        }
    }
}
Loading