diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher2/AllApps3D.java | 17 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 38 | ||||
-rw-r--r-- | src/com/android/launcher2/LauncherApplication.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher2/LauncherModel.java | 248 |
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(); |