Merge "Load PackageItemInfo in background thread to prevent ANR" into ub-launcher3-burnaby
This commit is contained in:
committed by
Android (Google) Code Review
commit
edc9c05644
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -3346,18 +3347,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());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3367,13 +3369,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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +206,7 @@ public class WidgetPreviewLoader {
|
||||
* This ensures that we remove entries for packages which changed while the launcher was dead.
|
||||
*/
|
||||
public void removeObsoletePreviews(ArrayList<Object> list) {
|
||||
// This method should always be called from the worker thread.
|
||||
Assert.assertTrue(LauncherModel.sWorkerThread.getThreadId() == Process.myTid());
|
||||
Utilities.assertWorkerThread();
|
||||
|
||||
LongSparseArray<UserHandleCompat> userIdCache = new LongSparseArray<>();
|
||||
LongSparseArray<HashSet<String>> validPackages = new LongSparseArray<>();
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Bitmap;
|
||||
+23
-20
@@ -1,18 +1,19 @@
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.os.Handler;
|
||||
import android.os.Process;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
|
||||
import com.android.launcher3.LauncherModel;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.model.AppNameComparator;
|
||||
import com.android.launcher3.model.WidgetsAndShortcutNameComparator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -37,19 +38,19 @@ public class WidgetsModel {
|
||||
/* Map of widgets and shortcuts that are tracked per package. */
|
||||
private Map<PackageItemInfo, ArrayList<Object>> mWidgetsList = new HashMap<>();
|
||||
|
||||
/* Notifies the adapter when data changes. */
|
||||
private RecyclerView.Adapter mAdapter;
|
||||
private ArrayList<Object> mRawList;
|
||||
|
||||
private Comparator mWidgetAndShortcutNameComparator;
|
||||
private Comparator mAppNameComparator;
|
||||
private final Comparator mWidgetAndShortcutNameComparator;
|
||||
private final Comparator mAppNameComparator;
|
||||
|
||||
private IconCache mIconCache;
|
||||
private final IconCache mIconCache;
|
||||
private final Handler mWorkerHandler;
|
||||
|
||||
public WidgetsModel(Context context, RecyclerView.Adapter adapter) {
|
||||
mAdapter = adapter;
|
||||
public WidgetsModel(Context context) {
|
||||
mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context);
|
||||
mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator();
|
||||
mIconCache = LauncherAppState.getInstance().getIconCache();
|
||||
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
|
||||
}
|
||||
|
||||
// Access methods that may be deleted if the private fields are made package-private.
|
||||
@@ -66,9 +67,15 @@ public class WidgetsModel {
|
||||
return mWidgetsList.get(mPackageItemInfos.get(pos));
|
||||
}
|
||||
|
||||
public void addWidgetsAndShortcuts(ArrayList<Object> widgetsShortcuts, PackageManager pm) {
|
||||
public ArrayList<Object> getRawList() {
|
||||
return mRawList;
|
||||
}
|
||||
|
||||
public void addWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
|
||||
Utilities.assertWorkerThread();
|
||||
mRawList = rawWidgetsShortcuts;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + widgetsShortcuts.size());
|
||||
Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
|
||||
}
|
||||
|
||||
// Temporary list for {@link PackageItemInfos} to avoid having to go through
|
||||
@@ -80,7 +87,7 @@ public class WidgetsModel {
|
||||
mPackageItemInfos.clear();
|
||||
|
||||
// add and update.
|
||||
for (Object o: widgetsShortcuts) {
|
||||
for (Object o: rawWidgetsShortcuts) {
|
||||
String packageName = "";
|
||||
if (o instanceof LauncherAppWidgetProviderInfo) {
|
||||
LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
|
||||
@@ -100,10 +107,9 @@ public class WidgetsModel {
|
||||
} else {
|
||||
widgetsShortcutsList = new ArrayList<Object>();
|
||||
widgetsShortcutsList.add(o);
|
||||
|
||||
pInfo = new PackageItemInfo(packageName);
|
||||
mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(),
|
||||
true /* useLowResIcon */, pInfo);
|
||||
true /* userLowResIcon */, pInfo);
|
||||
mWidgetsList.put(pInfo, widgetsShortcutsList);
|
||||
tmpPackageItemInfos.put(packageName, pInfo);
|
||||
mPackageItemInfos.add(pInfo);
|
||||
@@ -115,8 +121,5 @@ public class WidgetsModel {
|
||||
for (PackageItemInfo p: mPackageItemInfos) {
|
||||
Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator);
|
||||
}
|
||||
|
||||
// notify.
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -36,6 +35,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DragController;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget.DragObject;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.Folder;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
@@ -47,8 +47,6 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.Workspace;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The widgets list view container.
|
||||
*/
|
||||
@@ -68,9 +66,6 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
private DragController mDragController;
|
||||
private IconCache mIconCache;
|
||||
|
||||
/* Data model for the widget */
|
||||
private WidgetsModel mWidgets;
|
||||
|
||||
/* Recycler view related member variables */
|
||||
private RecyclerView mView;
|
||||
private WidgetsListAdapter mAdapter;
|
||||
@@ -98,8 +93,6 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
mDragController = mLauncher.getDragController();
|
||||
mWidgetHostViewLoader = new WidgetHostViewLoader(mLauncher);
|
||||
mAdapter = new WidgetsListAdapter(context, this, this, mLauncher);
|
||||
mWidgets = new WidgetsModel(context, mAdapter);
|
||||
mAdapter.setWidgetsModel(mWidgets);
|
||||
mIconCache = (LauncherAppState.getInstance()).getIconCache();
|
||||
|
||||
if (DEBUG) {
|
||||
@@ -109,10 +102,6 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("onFinishInflate [widgets size=%d]",
|
||||
mWidgets.getPackageSize()));
|
||||
}
|
||||
mView = (RecyclerView) findViewById(R.id.widgets_list_view);
|
||||
mView.setAdapter(mAdapter);
|
||||
|
||||
@@ -145,10 +134,6 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
|
||||
public void scrollToTop() {
|
||||
mView.scrollToPosition(0);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, String.format("scrollToTop, [widgets size=%d]",
|
||||
mWidgets.getPackageSize()));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -374,8 +359,9 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
/**
|
||||
* Initialize the widget data model.
|
||||
*/
|
||||
public void addWidgets(ArrayList<Object> widgetsShortcuts, PackageManager pm) {
|
||||
mWidgets.addWidgetsAndShortcuts(widgetsShortcuts, pm);
|
||||
public void addWidgets(WidgetsModel model) {
|
||||
mAdapter.setWidgetsModel(model);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private WidgetPreviewLoader getWidgetPreviewLoader() {
|
||||
|
||||
@@ -38,6 +38,8 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user