am dca66123: Batch loading of icons for AllApps.

This commit is contained in:
Daniel Sandler 2010-04-15 13:32:07 -07:00 committed by Android Git Automerger
commit e825010dc9
7 changed files with 111 additions and 45 deletions

View File

@ -50,6 +50,8 @@ public class AllApps2D
private static final String TAG = "Launcher.AllApps2D";
private static final int BATCH_SIZE = 6; // give us a few apps at a time
private Launcher mLauncher;
private DragController mDragController;
@ -300,6 +302,10 @@ public class AllApps2D
return -1;
}
public int getAppBatchSize() {
return BATCH_SIZE;
}
public void dumpState() {
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList", mAllAppsList);
}

View File

@ -73,6 +73,8 @@ public class AllApps3D extends RSSurfaceView
private static final int SELECTION_ICONS = 1;
private static final int SELECTION_HOME = 2;
private static final int BATCH_SIZE = 0; // give us all the apps at once
private Launcher mLauncher;
private DragController mDragController;
@ -1593,6 +1595,10 @@ public class AllApps3D extends RSSurfaceView
}
}
public int getAppBatchSize() {
return BATCH_SIZE;
}
public void dumpState() {
Log.d(TAG, "sRS=" + sRS);
Log.d(TAG, "sRollo=" + sRollo);

View File

@ -24,6 +24,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -56,10 +57,17 @@ class AllAppsList {
/**
* Add the supplied ApplicationInfo objects to the list, and enqueue it into the
* list to broadcast when notify() is called.
*
* Postcondition: data and added are sorted in order of LauncherModel.APP_NAME_COMPARATOR.
*/
public void add(ApplicationInfo info) {
data.add(info);
added.add(info);
int pos = Collections.binarySearch(data, info, LauncherModel.APP_NAME_COMPARATOR);
if (pos < 0) pos = -1 - pos;
data.add(pos, info);
pos = Collections.binarySearch(added, info, LauncherModel.APP_NAME_COMPARATOR);
if (pos < 0) pos = -1 - pos;
added.add(pos, info);
}
public void clear() {
@ -86,9 +94,7 @@ class AllAppsList {
if (matches.size() > 0) {
for (ResolveInfo info : matches) {
ApplicationInfo item = new ApplicationInfo(info, mIconCache);
data.add(item);
added.add(item);
add(new ApplicationInfo(info, mIconCache));
}
}
}
@ -139,9 +145,7 @@ class AllAppsList {
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
if (applicationInfo == null) {
applicationInfo = new ApplicationInfo(info, mIconCache);
data.add(applicationInfo);
added.add(applicationInfo);
add(new ApplicationInfo(info, mIconCache));
} else {
mIconCache.remove(applicationInfo.componentName);
mIconCache.getTitleAndIcon(applicationInfo, info);

View File

@ -40,8 +40,10 @@ public interface AllAppsView {
public void removeApps(ArrayList<ApplicationInfo> list);
public void updateApps(ArrayList<ApplicationInfo> list);
public int getAppBatchSize();
public void dumpState();
public void surrender();
}

View File

@ -87,6 +87,12 @@ public class DeferredHandler {
post(new IdleRunnable(runnable));
}
public void cancelRunnable(Runnable runnable) {
synchronized (mQueue) {
while (mQueue.remove(runnable)) { }
}
}
public void cancel() {
synchronized (mQueue) {
mQueue.clear();

View File

@ -2085,6 +2085,15 @@ public final class Launcher extends Activity
mAllAppsGrid.removeApps(apps);
}
/**
* Find out how many apps we should send to the grid at a time.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
public int getAppBatchSize() {
return mAllAppsGrid.getAppBatchSize();
}
/**
* Prints out out state for debugging.
*/

View File

@ -62,6 +62,8 @@ public class LauncherModel extends BroadcastReceiver {
static final boolean DEBUG_LOADERS = false;
static final String TAG = "Launcher.Model";
final int ALL_APPS_LOAD_DELAY = 150; // ms
private final LauncherApplication mApp;
private final Object mLock = new Object();
private DeferredHandler mHandler = new DeferredHandler();
@ -86,6 +88,7 @@ public class LauncherModel extends BroadcastReceiver {
public void bindAppsAdded(ArrayList<ApplicationInfo> apps);
public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);
public void bindAppsRemoved(ArrayList<ApplicationInfo> apps);
public int getAppBatchSize();
}
LauncherModel(LauncherApplication app, IconCache iconCache) {
@ -575,6 +578,13 @@ public class LauncherModel extends BroadcastReceiver {
}
}
// Whew! Hard work done.
synchronized (mLock) {
if (mIsLaunching) {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
}
// Load all apps if they're dirty
int allAppsSeq;
boolean allAppsDirty;
@ -587,7 +597,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
if (allAppsDirty) {
loadAllApps();
loadAndBindAllApps();
}
synchronized (mLock) {
// If we're not stopped, and nobody has incremented mAllAppsSeq.
@ -599,11 +609,6 @@ public class LauncherModel extends BroadcastReceiver {
}
}
// Bind all apps
if (allAppsDirty) {
bindAllApps();
}
// Clear out this reference, otherwise we end up holding it until all of the
// callback runnables are done.
mContext = null;
@ -1014,7 +1019,9 @@ public class LauncherModel extends BroadcastReceiver {
});
}
private void loadAllApps() {
private void loadAndBindAllApps() {
final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
@ -1026,53 +1033,79 @@ public class LauncherModel extends BroadcastReceiver {
final PackageManager packageManager = mContext.getPackageManager();
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
int N;
int batchSize = callbacks.getAppBatchSize();
synchronized (mLock) {
mBeforeFirstLoad = false;
mAllAppsList.clear();
if (apps != null) {
long t = SystemClock.uptimeMillis();
if (apps == null) return;
N = apps.size();
if (batchSize <= 0)
batchSize = N;
}
int N = apps.size();
for (int i=0; i<N && !mStopped; i++) {
int i=0;
while (i < N && !mStopped) {
synchronized (mLock) {
final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
for (int j=0; i<N && j<batchSize; j++) {
// This builds the icon bitmaps.
mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
i++;
}
// re-sort before binding this batch to the grid
Collections.sort(mAllAppsList.data, APP_NAME_COMPARATOR);
Collections.sort(mAllAppsList.added, APP_NAME_COMPARATOR);
if (DEBUG_LOADERS) {
Log.d(TAG, "cached app icons in "
+ (SystemClock.uptimeMillis()-t) + "ms");
Log.d(TAG, "batch of " + batchSize + " icons processed in "
+ (SystemClock.uptimeMillis()-t2) + "ms");
}
}
mHandler.post(bindAllAppsTask);
if (ALL_APPS_LOAD_DELAY > 0) {
try {
Thread.sleep(ALL_APPS_LOAD_DELAY);
} catch (InterruptedException exc) { }
}
}
if (DEBUG_LOADERS) {
Log.d(TAG, "cached all " + N + " apps in "
+ (SystemClock.uptimeMillis()-t) + "ms");
}
}
private void bindAllApps() {
synchronized (mLock) {
final ArrayList<ApplicationInfo> results
= (ArrayList<ApplicationInfo>) mAllAppsList.data.clone();
// We're adding this now, so clear out this so we don't re-send them.
mAllAppsList.added = new ArrayList<ApplicationInfo>();
final Callbacks old = mCallbacks.get();
mHandler.post(new Runnable() {
public void run() {
final long t = SystemClock.uptimeMillis();
final int count = results.size();
final Runnable bindAllAppsTask = new Runnable() {
public void run() {
final long t = SystemClock.uptimeMillis();
int count = 0;
Callbacks callbacks = null;
ArrayList<ApplicationInfo> results = null;
synchronized (mLock) {
mHandler.cancelRunnable(this);
Callbacks callbacks = tryGetCallbacks(old);
if (callbacks != null) {
callbacks.bindAllApplications(results);
}
results = (ArrayList<ApplicationInfo>) mAllAppsList.data.clone();
// We're adding this now, so clear out this so we don't re-send them.
mAllAppsList.added = new ArrayList<ApplicationInfo>();
count = results.size();
if (DEBUG_LOADERS) {
Log.d(TAG, "bound app " + count + " icons in "
+ (SystemClock.uptimeMillis() - t) + "ms");
}
}
});
callbacks = tryGetCallbacks(mCallbacks.get());
}
if (callbacks != null && count > 0) {
callbacks.bindAllApplications(results);
}
if (DEBUG_LOADERS) {
Log.d(TAG, "bound " + count + " apps in "
+ (SystemClock.uptimeMillis() - t) + "ms");
}
}
}
};
public void dumpState() {
Log.d(TAG, "mLoader.mLoaderThread.mContext=" + mContext);