summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2010-06-07 14:59:01 -0400
committerDaniel Sandler <dsandler@android.com>2010-06-07 16:45:16 -0400
commit843e860e8ebab96ff70988f2829fac38afd9d937 (patch)
treee4a39c52dc17424c400c4a56e69f301b5263d707 /src
parent81a9248156ecd099e4b1bd1b9541436be2a5b57f (diff)
downloadandroid_packages_apps_Trebuchet-843e860e8ebab96ff70988f2829fac38afd9d937.tar.gz
android_packages_apps_Trebuchet-843e860e8ebab96ff70988f2829fac38afd9d937.tar.bz2
android_packages_apps_Trebuchet-843e860e8ebab96ff70988f2829fac38afd9d937.zip
Load All Apps before the workspace if All Apps is showing.
This change reorganizes the increasingly Byzantine loader thread so that the order of (workspace, allapps) can be reversed if the user is currently looking at the all apps view. The perceptual improvement in performance is huge if you change the Launcher's orientation while All Apps is visible (which forces a reload/bind of everything); now that AA doesn't have to wait behind the workspace it (specifically, its first batch of icons) appears much, much faster. Bug: 2722977 Change-Id: I07a9afd5f1cff4019f2640b082872176ba0a887e
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/Launcher.java27
-rw-r--r--src/com/android/launcher2/LauncherModel.java145
2 files changed, 111 insertions, 61 deletions
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 52f122479..62aaa8be6 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -49,6 +49,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.LiveFolders;
import android.text.Selection;
@@ -91,10 +92,10 @@ import com.android.launcher.R;
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {
static final String TAG = "Launcher";
- static final boolean LOGD = false;
+ static final boolean LOGD = true;
static final boolean PROFILE_STARTUP = false;
- static final boolean PROFILE_ROTATE = false;
+ static final boolean DEBUG_WIDGETS = false;
static final boolean DEBUG_USER_INTERFACE = false;
private static final int WALLPAPER_SCREENS_SPAN = 2;
@@ -586,10 +587,6 @@ public final class Launcher extends Activity
// Flag the loader to stop early before switching
mModel.stopLoader();
mAllAppsGrid.surrender();
-
- if (PROFILE_ROTATE) {
- android.os.Debug.startMethodTracing("/sdcard/launcher-rotate");
- }
return Boolean.TRUE;
}
@@ -1885,8 +1882,9 @@ public final class Launcher extends Activity
}
}
- boolean isAllAppsVisible() {
- return mAllAppsGrid.isVisible();
+ // Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
+ public boolean isAllAppsVisible() {
+ return (mAllAppsGrid != null) ? mAllAppsGrid.isVisible() : false;
}
// AllAppsView.Watcher
@@ -2185,10 +2183,18 @@ public final class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAppWidget(LauncherAppWidgetInfo item) {
+ final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
+ if (DEBUG_WIDGETS) {
+ Log.d(TAG, "bindAppWidget: " + item);
+ }
final Workspace workspace = mWorkspace;
final int appWidgetId = item.appWidgetId;
final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+ if (DEBUG_WIDGETS) {
+ Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
+ }
+
item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
@@ -2200,6 +2206,11 @@ public final class Launcher extends Activity
workspace.requestLayout();
mDesktopItems.add(item);
+
+ if (DEBUG_WIDGETS) {
+ Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
+ + (SystemClock.uptimeMillis()-start) + "ms");
+ }
}
/**
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index d2cebc0d4..96ceb747f 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -60,6 +60,7 @@ import com.android.launcher.R;
*/
public class LauncherModel extends BroadcastReceiver {
static final boolean DEBUG_LOADERS = false;
+ static final boolean PROFILE_LOADERS = false;
static final String TAG = "Launcher.Model";
private int mBatchSize; // 0 is all apps at once
@@ -90,6 +91,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 boolean isAllAppsVisible();
}
LauncherModel(LauncherApplication app, IconCache iconCache) {
@@ -439,6 +441,7 @@ public class LauncherModel extends BroadcastReceiver {
if (DEBUG_LOADERS) {
Log.d(TAG, "startLoader isLaunching=" + isLaunching);
}
+
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
LoaderThread oldThread = mLoaderThread;
@@ -486,7 +489,7 @@ public class LauncherModel extends BroadcastReceiver {
private Thread mWaitThread;
private boolean mIsLaunching;
private boolean mStopped;
- private boolean mWorkspaceDoneBinding;
+ private boolean mLoadAndBindStepFinished;
LoaderThread(Context context, Thread waitThread, boolean isLaunching) {
mContext = context;
@@ -520,16 +523,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- public void run() {
- waitForOtherThread();
-
- // Elevate priority when Home launches for the first time to avoid
- // starving at boot time. Staring at a blank home is not cool.
- synchronized (mLock) {
- android.os.Process.setThreadPriority(mIsLaunching
- ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
- }
-
+ private void loadAndBindWorkspace() {
// Load the workspace only if it's dirty.
int workspaceSeq;
boolean workspaceDirty;
@@ -543,6 +537,10 @@ public class LauncherModel extends BroadcastReceiver {
synchronized (mLock) {
// If we're not stopped, and nobody has incremented mWorkspaceSeq.
if (mStopped) {
+ if (PROFILE_LOADERS) {
+ android.os.Debug.stopMethodTracing();
+ }
+
return;
}
if (workspaceSeq == mWorkspaceSeq) {
@@ -552,26 +550,54 @@ public class LauncherModel extends BroadcastReceiver {
// Bind the workspace
bindWorkspace();
-
+ }
+
+ private void loadAndBindAllAppsIfDirty() {
+ // Load all apps if they're dirty
+ int allAppsSeq;
+ boolean allAppsDirty;
+ synchronized (mLock) {
+ allAppsSeq = mAllAppsSeq;
+ allAppsDirty = mAllAppsSeq != mLastAllAppsSeq;
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "mAllAppsSeq=" + mAllAppsSeq
+ + " mLastAllAppsSeq=" + mLastAllAppsSeq + " allAppsDirty");
+ }
+ }
+ if (allAppsDirty) {
+ loadAndBindAllApps();
+ }
+ synchronized (mLock) {
+ // If we're not stopped, and nobody has incremented mAllAppsSeq.
+ if (mStopped) {
+ return;
+ }
+ if (allAppsSeq == mAllAppsSeq) {
+ mLastAllAppsSeq = mAllAppsSeq;
+ }
+ }
+ }
+
+ private void waitForIdle() {
// Wait until the either we're stopped or the other threads are done.
// This way we don't start loading all apps until the workspace has settled
// down.
synchronized (LoaderThread.this) {
+ final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
mHandler.postIdle(new Runnable() {
public void run() {
synchronized (LoaderThread.this) {
- mWorkspaceDoneBinding = true;
+ mLoadAndBindStepFinished = true;
if (DEBUG_LOADERS) {
- Log.d(TAG, "done with workspace");
- }
+ Log.d(TAG, "done with previous binding step");
+ }
LoaderThread.this.notify();
}
}
});
- if (DEBUG_LOADERS) {
- Log.d(TAG, "waiting to be done with workspace");
- }
- while (!mStopped && !mWorkspaceDoneBinding) {
+
+ while (!mStopped && !mLoadAndBindStepFinished) {
try {
this.wait();
} catch (InterruptedException ex) {
@@ -579,41 +605,57 @@ public class LauncherModel extends BroadcastReceiver {
}
}
if (DEBUG_LOADERS) {
- Log.d(TAG, "done waiting to be done with workspace");
+ Log.d(TAG, "waited "
+ + (SystemClock.uptimeMillis()-workspaceWaitTime)
+ + "ms for previous step to finish binding");
}
}
+ }
- // Whew! Hard work done.
+ public void run() {
+ waitForOtherThread();
+
+ // Optimize for end-user experience: if the Launcher is up and // running with the
+ // All Apps interface in the foreground, load All Apps first. Otherwise, load the
+ // workspace first (default).
+ final Callbacks cbk = mCallbacks.get();
+ final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
+
+ // Elevate priority when Home launches for the first time to avoid
+ // starving at boot time. Staring at a blank home is not cool.
synchronized (mLock) {
- if (mIsLaunching) {
- android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
+ android.os.Process.setThreadPriority(mIsLaunching
+ ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
}
- // Load all apps if they're dirty
- int allAppsSeq;
- boolean allAppsDirty;
- synchronized (mLock) {
- allAppsSeq = mAllAppsSeq;
- allAppsDirty = mAllAppsSeq != mLastAllAppsSeq;
- if (DEBUG_LOADERS) {
- Log.d(TAG, "mAllAppsSeq=" + mAllAppsSeq
- + " mLastAllAppsSeq=" + mLastAllAppsSeq + " allAppsDirty");
- }
+ if (PROFILE_LOADERS) {
+ android.os.Debug.startMethodTracing("/sdcard/launcher-loaders");
}
- if (allAppsDirty) {
- loadAndBindAllApps();
+
+ if (loadWorkspaceFirst) {
+ if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
+ loadAndBindWorkspace();
+ } else {
+ if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");
+ loadAndBindAllAppsIfDirty();
}
+
+ // Whew! Hard work done.
synchronized (mLock) {
- // If we're not stopped, and nobody has incremented mAllAppsSeq.
- if (mStopped) {
- return;
- }
- if (allAppsSeq == mAllAppsSeq) {
- mLastAllAppsSeq = mAllAppsSeq;
+ if (mIsLaunching) {
+ android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}
+ // second step
+ if (loadWorkspaceFirst) {
+ if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
+ loadAndBindAllAppsIfDirty();
+ } else {
+ if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
+ loadAndBindWorkspace();
+ }
+
// Clear out this reference, otherwise we end up holding it until all of the
// callback runnables are done.
mContext = null;
@@ -624,6 +666,10 @@ public class LauncherModel extends BroadcastReceiver {
mLoaderThread = null;
}
+ if (PROFILE_LOADERS) {
+ android.os.Debug.stopMethodTracing();
+ }
+
// Trigger a gc to try to clean up after the stuff is done, since the
// renderscript allocations aren't charge to the java heap.
mHandler.post(new Runnable() {
@@ -672,10 +718,6 @@ public class LauncherModel extends BroadcastReceiver {
// check & update map of what's occupied; used to discard overlapping/invalid items
private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
- if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- return true;
- }
-
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
if (occupied[item.screen][x][y] != null) {
@@ -697,7 +739,7 @@ public class LauncherModel extends BroadcastReceiver {
}
private void loadWorkspace() {
- long t = SystemClock.uptimeMillis();
+ final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final Context context = mContext;
final ContentResolver contentResolver = context.getContentResolver();
@@ -1028,7 +1070,7 @@ public class LauncherModel extends BroadcastReceiver {
}
});
// Wait until the queue goes empty.
- mHandler.postIdle(new Runnable() {
+ mHandler.post(new Runnable() {
public void run() {
if (DEBUG_LOADERS) {
Log.d(TAG, "Going to start binding widgets soon.");
@@ -1086,9 +1128,6 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "bound workspace in "
+ (SystemClock.uptimeMillis()-t) + "ms");
}
- if (Launcher.PROFILE_ROTATE) {
- android.os.Debug.stopMethodTracing();
- }
}
});
}
@@ -1152,7 +1191,7 @@ public class LauncherModel extends BroadcastReceiver {
new ResolveInfo.DisplayNameComparator(packageManager));
if (DEBUG_LOADERS) {
Log.d(TAG, "sort took "
- + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+ + (SystemClock.uptimeMillis()-sortTime) + "ms");
}
}
@@ -1218,7 +1257,7 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "mLoader.mLoaderThread.mWaitThread=" + mWaitThread);
Log.d(TAG, "mLoader.mLoaderThread.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoader.mLoaderThread.mStopped=" + mStopped);
- Log.d(TAG, "mLoader.mLoaderThread.mWorkspaceDoneBinding=" + mWorkspaceDoneBinding);
+ Log.d(TAG, "mLoader.mLoaderThread.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
}
}