Fixing slow binding when returning to Launcher

Bug: 8978842
Bug: 8660324

Change-Id: Idfa37c05ed299faa465ea66de4b43d30da77ecbc
This commit is contained in:
Michael Jurka
2013-05-20 18:20:48 +02:00
parent 447bf84d24
commit c402cd9992
4 changed files with 112 additions and 56 deletions
@@ -240,6 +240,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
WidgetPreviewLoader mWidgetPreviewLoader; WidgetPreviewLoader mWidgetPreviewLoader;
private boolean mInBulkBind;
private boolean mNeedToUpdatePageCountsAndInvalidateData;
public AppsCustomizePagedView(Context context, AttributeSet attrs) { public AppsCustomizePagedView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
mLayoutInflater = LayoutInflater.from(context); mLayoutInflater = LayoutInflater.from(context);
@@ -440,38 +443,57 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} }
public void onPackagesUpdated() { public void onPackagesUpdated(ArrayList<Object> widgetsAndShortcuts) {
// Get the list of widgets and shortcuts // Get the list of widgets and shortcuts
mWidgets.clear(); mWidgets.clear();
List<AppWidgetProviderInfo> widgets = for (Object o : widgetsAndShortcuts) {
AppWidgetManager.getInstance(mLauncher).getInstalledProviders(); if (o instanceof AppWidgetProviderInfo) {
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); AppWidgetProviderInfo widget = (AppWidgetProviderInfo) o;
List<ResolveInfo> shortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0); widget.label = widget.label.trim();
for (AppWidgetProviderInfo widget : widgets) { if (widget.minWidth > 0 && widget.minHeight > 0) {
widget.label = widget.label.trim(); // Ensure that all widgets we show can be added on a workspace of this size
if (widget.minWidth > 0 && widget.minHeight > 0) { int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
// Ensure that all widgets we show can be added on a workspace of this size int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, widget);
int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget); int minSpanX = Math.min(spanXY[0], minSpanXY[0]);
int[] minSpanXY = Launcher.getMinSpanForWidget(mLauncher, widget); int minSpanY = Math.min(spanXY[1], minSpanXY[1]);
int minSpanX = Math.min(spanXY[0], minSpanXY[0]); if (minSpanX <= LauncherModel.getCellCountX() &&
int minSpanY = Math.min(spanXY[1], minSpanXY[1]);
if (minSpanX <= LauncherModel.getCellCountX() &&
minSpanY <= LauncherModel.getCellCountY()) { minSpanY <= LauncherModel.getCellCountY()) {
mWidgets.add(widget); mWidgets.add(widget);
} else {
Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" +
widget.minWidth + ", " + widget.minHeight + ")");
}
} else { } else {
Log.e(TAG, "Widget " + widget.provider + " can not fit on this device (" + Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" +
widget.minWidth + ", " + widget.minHeight + ")"); widget.minWidth + ", " + widget.minHeight + ")");
} }
} else { } else {
Log.e(TAG, "Widget " + widget.provider + " has invalid dimensions (" + // just add shortcuts
widget.minWidth + ", " + widget.minHeight + ")"); mWidgets.add(o);
} }
} }
mWidgets.addAll(shortcuts); updatePageCountsAndInvalidateData();
Collections.sort(mWidgets, }
new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
updatePageCounts(); public void setBulkBind(boolean bulkBind) {
invalidateOnDataChange(); if (bulkBind) {
mInBulkBind = true;
} else {
mInBulkBind = false;
if (mNeedToUpdatePageCountsAndInvalidateData) {
updatePageCountsAndInvalidateData();
}
}
}
private void updatePageCountsAndInvalidateData() {
if (mInBulkBind) {
mNeedToUpdatePageCountsAndInvalidateData = true;
} else {
updatePageCounts();
invalidateOnDataChange();
mNeedToUpdatePageCountsAndInvalidateData = false;
}
} }
@Override @Override
@@ -1526,8 +1548,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
public void setApps(ArrayList<ApplicationInfo> list) { public void setApps(ArrayList<ApplicationInfo> list) {
mApps = list; mApps = list;
Collections.sort(mApps, LauncherModel.getAppNameComparator()); Collections.sort(mApps, LauncherModel.getAppNameComparator());
updatePageCounts(); updatePageCountsAndInvalidateData();
invalidateOnDataChange();
} }
private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) { private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
// We add it in place, in alphabetical order // We add it in place, in alphabetical order
@@ -1542,8 +1563,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
} }
public void addApps(ArrayList<ApplicationInfo> list) { public void addApps(ArrayList<ApplicationInfo> list) {
addAppsWithoutInvalidate(list); addAppsWithoutInvalidate(list);
updatePageCounts(); updatePageCountsAndInvalidateData();
invalidateOnDataChange();
} }
private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) { private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
ComponentName removeComponent = item.intent.getComponent(); ComponentName removeComponent = item.intent.getComponent();
@@ -1569,8 +1589,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
} }
public void removeApps(ArrayList<ApplicationInfo> appInfos) { public void removeApps(ArrayList<ApplicationInfo> appInfos) {
removeAppsWithoutInvalidate(appInfos); removeAppsWithoutInvalidate(appInfos);
updatePageCounts(); updatePageCountsAndInvalidateData();
invalidateOnDataChange();
} }
public void updateApps(ArrayList<ApplicationInfo> list) { public void updateApps(ArrayList<ApplicationInfo> list) {
// We remove and re-add the updated applications list because it's properties may have // We remove and re-add the updated applications list because it's properties may have
@@ -1578,8 +1597,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// place in the list. // place in the list.
removeAppsWithoutInvalidate(list); removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list); addAppsWithoutInvalidate(list);
updatePageCounts(); updatePageCountsAndInvalidateData();
invalidateOnDataChange();
} }
public void reset() { public void reset() {
+45 -21
View File
@@ -126,7 +126,7 @@ public final class Launcher extends Activity
static final boolean PROFILE_STARTUP = false; static final boolean PROFILE_STARTUP = false;
static final boolean DEBUG_WIDGETS = false; static final boolean DEBUG_WIDGETS = false;
static final boolean DEBUG_STRICT_MODE = false; static final boolean DEBUG_STRICT_MODE = false;
static final boolean DEBUG_RESUME_TIME = true; static final boolean DEBUG_RESUME_TIME = false;
private static final int MENU_GROUP_WALLPAPER = 1; private static final int MENU_GROUP_WALLPAPER = 1;
private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1; private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1;
@@ -392,7 +392,8 @@ public final class Launcher extends Activity
// Update customization drawer _after_ restoring the states // Update customization drawer _after_ restoring the states
if (mAppsCustomizeContent != null) { if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.onPackagesUpdated(); mAppsCustomizeContent.onPackagesUpdated(
LauncherModel.getSortedWidgetsAndShortcuts(this));
} }
if (PROFILE_STARTUP) { if (PROFILE_STARTUP) {
@@ -759,19 +760,28 @@ public final class Launcher extends Activity
mRestoring = false; mRestoring = false;
mOnResumeNeedsLoad = false; mOnResumeNeedsLoad = false;
} }
// We might have postponed some bind calls until onResume (see waitUntilResume) -- if (mOnResumeCallbacks.size() > 0) {
// execute them here // We might have postponed some bind calls until onResume (see waitUntilResume) --
long startTimeCallbacks = 0; // execute them here
if (DEBUG_RESUME_TIME) { long startTimeCallbacks = 0;
startTimeCallbacks = System.currentTimeMillis(); if (DEBUG_RESUME_TIME) {
} startTimeCallbacks = System.currentTimeMillis();
for (int i = 0; i < mOnResumeCallbacks.size(); i++) { }
mOnResumeCallbacks.get(i).run();
} if (mAppsCustomizeContent != null) {
mOnResumeCallbacks.clear(); mAppsCustomizeContent.setBulkBind(true);
if (DEBUG_RESUME_TIME) { }
Log.d(TAG, "Time spent processing callbacks in onResume: " + for (int i = 0; i < mOnResumeCallbacks.size(); i++) {
(System.currentTimeMillis() - startTimeCallbacks)); mOnResumeCallbacks.get(i).run();
}
if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.setBulkBind(false);
}
mOnResumeCallbacks.clear();
if (DEBUG_RESUME_TIME) {
Log.d(TAG, "Time spent processing callbacks in onResume: " +
(System.currentTimeMillis() - startTimeCallbacks));
}
} }
// Reset the pressed state of icons that were locked in the press state while activities // Reset the pressed state of icons that were locked in the press state while activities
@@ -3308,9 +3318,13 @@ public final class Launcher extends Activity
* @return true if we are currently paused. The caller might be able to * @return true if we are currently paused. The caller might be able to
* skip some work in that case since we will come back again. * skip some work in that case since we will come back again.
*/ */
private boolean waitUntilResume(Runnable run) { private boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) {
if (mPaused) { if (mPaused) {
Log.i(TAG, "Deferring update until onResume"); Log.i(TAG, "Deferring update until onResume");
if (deletePreviousRunnables) {
while (mOnResumeCallbacks.remove(run)) {
}
}
mOnResumeCallbacks.add(run); mOnResumeCallbacks.add(run);
return true; return true;
} else { } else {
@@ -3318,6 +3332,10 @@ public final class Launcher extends Activity
} }
} }
private boolean waitUntilResume(Runnable run) {
return waitUntilResume(run, false);
}
/** /**
* If the activity is currently paused, signal that we need to re-run the loader * If the activity is currently paused, signal that we need to re-run the loader
* in onResume. * in onResume.
@@ -3761,17 +3779,23 @@ public final class Launcher extends Activity
/** /**
* A number of packages were updated. * A number of packages were updated.
*/ */
public void bindPackagesUpdated() {
if (waitUntilResume(new Runnable() { private ArrayList<Object> mWidgetsAndShortcuts;
private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
public void run() { public void run() {
bindPackagesUpdated(); bindPackagesUpdated(mWidgetsAndShortcuts);
mWidgetsAndShortcuts = null;
} }
})) { };
public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) {
if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
mWidgetsAndShortcuts = widgetsAndShortcuts;
return; return;
} }
if (mAppsCustomizeContent != null) { if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.onPackagesUpdated(); mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts);
} }
} }
@@ -50,6 +50,6 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
protected void onProvidersChanged() { protected void onProvidersChanged() {
// Once we get the message that widget packages are updated, we need to rebind items // Once we get the message that widget packages are updated, we need to rebind items
// in AppsCustomize accordingly. // in AppsCustomize accordingly.
mLauncher.bindPackagesUpdated(); mLauncher.bindPackagesUpdated(LauncherModel.getSortedWidgetsAndShortcuts(mLauncher));
} }
} }
+16 -2
View File
@@ -161,7 +161,7 @@ public class LauncherModel extends BroadcastReceiver {
public void bindComponentsRemoved(ArrayList<String> packageNames, public void bindComponentsRemoved(ArrayList<String> packageNames,
ArrayList<ApplicationInfo> appInfos, ArrayList<ApplicationInfo> appInfos,
boolean matchPackageNamesOnly); boolean matchPackageNamesOnly);
public void bindPackagesUpdated(); public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
public boolean isAllAppsVisible(); public boolean isAllAppsVisible();
public boolean isAllAppsButtonRank(int rank); public boolean isAllAppsButtonRank(int rank);
public void bindSearchablesChanged(); public void bindSearchablesChanged();
@@ -2105,18 +2105,32 @@ public class LauncherModel extends BroadcastReceiver {
}); });
} }
final ArrayList<Object> widgetsAndShortcuts =
getSortedWidgetsAndShortcuts(context);
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks == cb && cb != null) { if (callbacks == cb && cb != null) {
callbacks.bindPackagesUpdated(); callbacks.bindPackagesUpdated(widgetsAndShortcuts);
} }
} }
}); });
} }
} }
// Returns a list of ResolveInfos/AppWindowInfos in sorted order
public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {
PackageManager packageManager = context.getPackageManager();
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
Collections.sort(widgetsAndShortcuts,
new LauncherModel.WidgetAndShortcutNameComparator(packageManager));
return widgetsAndShortcuts;
}
/** /**
* This is called from the code that adds shortcuts from the intent receiver. This * This is called from the code that adds shortcuts from the intent receiver. This
* doesn't have a Cursor, but * doesn't have a Cursor, but