summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/AllApps3D.java17
-rw-r--r--src/com/android/launcher2/Launcher.java38
-rw-r--r--src/com/android/launcher2/LauncherApplication.java2
-rw-r--r--src/com/android/launcher2/LauncherModel.java248
4 files changed, 183 insertions, 122 deletions
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 36e19ceee..1279ff8c1 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -148,7 +148,6 @@ public class AllApps3D extends RSSurfaceView
super(context, attrs);
setFocusable(true);
setSoundEffectsEnabled(false);
- getHolder().setFormat(PixelFormat.TRANSLUCENT);
final ViewConfiguration config = ViewConfiguration.get(context);
mSlop = config.getScaledTouchSlop();
mMaxFlingVelocity = config.getScaledMaximumFlingVelocity();
@@ -939,7 +938,23 @@ public class AllApps3D extends RSSurfaceView
public void run() {
sRollo.mScrollPos = ((float)mData[0]) / (1 << 16);
mVelocity = ((float)mData[1]) / (1 << 16);
+
+ boolean lastVisible = isVisible();
mZoom = ((float)mData[2]) / (1 << 16);
+
+ final boolean visible = isVisible();
+ if (visible != lastVisible) {
+ post(new Runnable() {
+ public void run() {
+ if (visible) {
+ showSurface();
+ } else {
+ hideSurface();
+ }
+ }
+ });
+ }
+
sZoomDirty = false;
}
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 52f122479..6bd915aa0 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;
@@ -94,7 +95,7 @@ public final class Launcher extends Activity
static final boolean LOGD = false;
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;
@@ -246,11 +247,6 @@ public final class Launcher extends Activity
android.os.Debug.stopMethodTracing();
}
- // We have a new AllAppsView, we need to re-bind everything, and it could have
- // changed in our absence.
- mModel.setAllAppsDirty();
- mModel.setWorkspaceDirty();
-
if (!mRestoring) {
mModel.startLoader(this, true);
}
@@ -586,10 +582,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;
}
@@ -1859,7 +1851,6 @@ public final class Launcher extends Activity
if (mWorkspaceLoading) {
lockAllApps();
- mModel.setWorkspaceDirty();
mModel.startLoader(Launcher.this, false);
} else {
final FolderIcon folderIcon = (FolderIcon)
@@ -1869,7 +1860,6 @@ public final class Launcher extends Activity
getWorkspace().requestLayout();
} else {
lockAllApps();
- mModel.setWorkspaceDirty();
mWorkspaceLoading = true;
mModel.startLoader(Launcher.this, false);
}
@@ -1885,8 +1875,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
@@ -2102,7 +2093,11 @@ public final class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public int getCurrentWorkspaceScreen() {
- return mWorkspace.getCurrentScreen();
+ if (mWorkspace != null) {
+ return mWorkspace.getCurrentScreen();
+ } else {
+ return SCREEN_COUNT / 2;
+ }
}
/**
@@ -2185,10 +2180,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 +2203,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/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index be448a891..eda92d999 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -73,8 +73,6 @@ public class LauncherApplication extends Application {
private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- // TODO: lockAllApps();
- mModel.setWorkspaceDirty();
mModel.startLoader(LauncherApplication.this, false);
}
};
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index d2cebc0d4..17f75732a 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
@@ -70,6 +71,12 @@ public class LauncherModel extends BroadcastReceiver {
private DeferredHandler mHandler = new DeferredHandler();
private Loader mLoader = new Loader();
+ // We start off with everything not loaded. After that, we assume that
+ // our monitoring of the package manager provides all updates and we never
+ // need to do a requery. These are only ever touched from the loader thread.
+ private boolean mWorkspaceLoaded;
+ private boolean mAllAppsLoaded;
+
private boolean mBeforeFirstLoad = true; // only access this from main thread
private WeakReference<Callbacks> mCallbacks;
@@ -90,6 +97,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) {
@@ -285,17 +293,6 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
- * We pick up most of the changes to all apps.
- */
- public void setAllAppsDirty() {
- mLoader.setAllAppsDirty();
- }
-
- public void setWorkspaceDirty() {
- mLoader.setWorkspaceDirty();
- }
-
- /**
* Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
* ACTION_PACKAGE_CHANGED.
*/
@@ -307,13 +304,13 @@ public class LauncherModel extends BroadcastReceiver {
ArrayList<ApplicationInfo> removed = null;
ArrayList<ApplicationInfo> modified = null;
- synchronized (mAllAppsListLock) {
- if (mBeforeFirstLoad) {
- // If we haven't even loaded yet, don't bother, since we'll just pick
- // up the changes.
- return;
- }
+ if (mBeforeFirstLoad) {
+ // If we haven't even loaded yet, don't bother, since we'll just pick
+ // up the changes.
+ return;
+ }
+ synchronized (mAllAppsListLock) {
final String action = intent.getAction();
if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
@@ -396,8 +393,9 @@ public class LauncherModel extends BroadcastReceiver {
if (packages == null || packages.length == 0) {
return;
}
- setAllAppsDirty();
- setWorkspaceDirty();
+ synchronized (this) {
+ mAllAppsLoaded = mWorkspaceLoaded = false;
+ }
startLoader(context, false);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
String packages[] = intent.getStringArrayExtra(
@@ -405,8 +403,9 @@ public class LauncherModel extends BroadcastReceiver {
if (packages == null || packages.length == 0) {
return;
}
- setAllAppsDirty();
- setWorkspaceDirty();
+ synchronized (this) {
+ mAllAppsLoaded = mWorkspaceLoaded = false;
+ }
startLoader(context, false);
}
}
@@ -418,12 +417,6 @@ public class LauncherModel extends BroadcastReceiver {
private LoaderThread mLoaderThread;
- private int mLastWorkspaceSeq = 0;
- private int mWorkspaceSeq = 1;
-
- private int mLastAllAppsSeq = 0;
- private int mAllAppsSeq = 1;
-
final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
@@ -439,6 +432,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;
@@ -463,18 +457,6 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- public void setWorkspaceDirty() {
- synchronized (mLock) {
- mWorkspaceSeq++;
- }
- }
-
- public void setAllAppsDirty() {
- synchronized (mLock) {
- mAllAppsSeq++;
- }
- }
-
/**
* Runnable for the thread that loads the contents of the launcher:
* - workspace icons
@@ -486,7 +468,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,58 +502,54 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- public void run() {
- waitForOtherThread();
+ private void loadAndBindWorkspace() {
+ // Load the workspace
- // 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);
+ // Other other threads can unset mWorkspaceLoaded, so atomically set it,
+ // and then if they unset it, or we unset it because of mStopped, it will
+ // be unset.
+ boolean loaded;
+ synchronized (this) {
+ loaded = mWorkspaceLoaded;
+ mWorkspaceLoaded = true;
}
- // Load the workspace only if it's dirty.
- int workspaceSeq;
- boolean workspaceDirty;
- synchronized (mLock) {
- workspaceSeq = mWorkspaceSeq;
- workspaceDirty = mWorkspaceSeq != mLastWorkspaceSeq;
- }
- if (workspaceDirty) {
+ // For now, just always reload the workspace. It's ~100 ms vs. the
+ // binding which takes many hundreds of ms.
+ // We can reconsider.
+ if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindWorkspace loaded=" + loaded);
+ if (true || !loaded) {
loadWorkspace();
- }
- synchronized (mLock) {
- // If we're not stopped, and nobody has incremented mWorkspaceSeq.
if (mStopped) {
+ mWorkspaceLoaded = false;
return;
}
- if (workspaceSeq == mWorkspaceSeq) {
- mLastWorkspaceSeq = mWorkspaceSeq;
- }
}
// Bind the workspace
bindWorkspace();
-
+ }
+
+ 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 +557,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) {
+
+ 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");
loadAndBindAllApps();
}
+
+ // 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");
+ loadAndBindAllApps();
+ } 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,8 +618,12 @@ 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.
+ // renderscript allocations aren't charged to the java heap.
mHandler.post(new Runnable() {
public void run() {
System.gc();
@@ -697,7 +695,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 +1026,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,14 +1084,60 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "bound workspace in "
+ (SystemClock.uptimeMillis()-t) + "ms");
}
- if (Launcher.PROFILE_ROTATE) {
- android.os.Debug.stopMethodTracing();
- }
}
});
}
private void loadAndBindAllApps() {
+ // Other other threads can unset mAllAppsLoaded, so atomically set it,
+ // and then if they unset it, or we unset it because of mStopped, it will
+ // be unset.
+ boolean loaded;
+ synchronized (this) {
+ loaded = mAllAppsLoaded;
+ mAllAppsLoaded = true;
+ }
+
+ if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindAllApps loaded=" + loaded);
+ if (!loaded) {
+ loadAllAppsByBatch();
+ if (mStopped) {
+ mAllAppsLoaded = false;
+ return;
+ }
+ } else {
+ onlyBindAllApps();
+ }
+ }
+
+ private void onlyBindAllApps() {
+ final Callbacks oldCallbacks = mCallbacks.get();
+ if (oldCallbacks == null) {
+ // This launcher has exited and nobody bothered to tell us. Just bail.
+ Log.w(TAG, "LoaderThread running with no launcher (onlyBindAllApps)");
+ return;
+ }
+
+ // shallow copy
+ final ArrayList<ApplicationInfo> list
+ = (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
+ mHandler.post(new Runnable() {
+ public void run() {
+ final long t = SystemClock.uptimeMillis();
+ final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.bindAllApplications(list);
+ }
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "bound all " + list.size() + " apps from cache in "
+ + (SystemClock.uptimeMillis()-t) + "ms");
+ }
+ }
+ });
+
+ }
+
+ private void loadAllAppsByBatch() {
final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
// Don't use these two variables in any of the callback runnables.
@@ -1101,7 +1145,7 @@ public class LauncherModel extends BroadcastReceiver {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
// This launcher has exited and nobody bothered to tell us. Just bail.
- Log.w(TAG, "LoaderThread running with no launcher (loadAndBindAllApps)");
+ Log.w(TAG, "LoaderThread running with no launcher (loadAllAppsByBatch)");
return;
}
@@ -1152,7 +1196,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,15 +1262,11 @@ 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);
}
}
public void dumpState() {
- Log.d(TAG, "mLoader.mLastWorkspaceSeq=" + mLoader.mLastWorkspaceSeq);
- Log.d(TAG, "mLoader.mWorkspaceSeq=" + mLoader.mWorkspaceSeq);
- Log.d(TAG, "mLoader.mLastAllAppsSeq=" + mLoader.mLastAllAppsSeq);
- Log.d(TAG, "mLoader.mAllAppsSeq=" + mLoader.mAllAppsSeq);
Log.d(TAG, "mLoader.mItems size=" + mLoader.mItems.size());
if (mLoaderThread != null) {
mLoaderThread.dumpState();