diff options
Diffstat (limited to 'src/com/android/settings/applications/ApplicationsState.java')
-rw-r--r-- | src/com/android/settings/applications/ApplicationsState.java | 389 |
1 files changed, 244 insertions, 145 deletions
diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java index 799b34a..0a5c26e 100644 --- a/src/com/android/settings/applications/ApplicationsState.java +++ b/src/com/android/settings/applications/ApplicationsState.java @@ -227,24 +227,21 @@ public class ApplicationsState { PackageIntentReceiver mPackageIntentReceiver; boolean mResumed; - Callbacks mCurCallbacks; - // Information about all applications. Synchronize on mAppEntries + // Information about all applications. Synchronize on mEntriesMap // to protect access to these. + final ArrayList<Session> mSessions = new ArrayList<Session>(); + final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>(); final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges(); final HashMap<String, AppEntry> mEntriesMap = new HashMap<String, AppEntry>(); final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>(); List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>(); long mCurId = 1; String mCurComputingSizePkg; + boolean mSessionsChanged; - // Rebuilding of app list. Synchronized on mRebuildSync. - final Object mRebuildSync = new Object(); - boolean mRebuildRequested; - boolean mRebuildAsync; - AppFilter mRebuildFilter; - Comparator<AppEntry> mRebuildComparator; - ArrayList<AppEntry> mRebuildResult; + // Temporary for dispatching session callbacks. Only touched by main thread. + final ArrayList<Session> mActiveSessions = new ArrayList<Session>(); /** * Receives notifications when applications are added/removed. @@ -262,6 +259,9 @@ public class ApplicationsState { sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); mContext.registerReceiver(this, sdFilter); } + void unregisterReceiver() { + mContext.unregisterReceiver(this); + } @Override public void onReceive(Context context, Intent intent) { String actionStr = intent.getAction(); @@ -300,6 +300,21 @@ public class ApplicationsState { } } + void rebuildActiveSessions() { + synchronized (mEntriesMap) { + if (!mSessionsChanged) { + return; + } + mActiveSessions.clear(); + for (int i=0; i<mSessions.size(); i++) { + Session s = mSessions.get(i); + if (s.mResumed) { + mActiveSessions.add(s); + } + } + } + } + class MainHandler extends Handler { static final int MSG_REBUILD_COMPLETE = 1; static final int MSG_PACKAGE_LIST_CHANGED = 2; @@ -310,35 +325,39 @@ public class ApplicationsState { @Override public void handleMessage(Message msg) { + rebuildActiveSessions(); switch (msg.what) { case MSG_REBUILD_COMPLETE: { - if (mCurCallbacks != null) { - mCurCallbacks.onRebuildComplete((ArrayList<AppEntry>)msg.obj); + Session s = (Session)msg.obj; + if (mActiveSessions.contains(s)) { + s.mCallbacks.onRebuildComplete(s.mLastAppList); } } break; case MSG_PACKAGE_LIST_CHANGED: { - if (mCurCallbacks != null) { - mCurCallbacks.onPackageListChanged(); + for (int i=0; i<mActiveSessions.size(); i++) { + mActiveSessions.get(i).mCallbacks.onPackageListChanged(); } } break; case MSG_PACKAGE_ICON_CHANGED: { - if (mCurCallbacks != null) { - mCurCallbacks.onPackageIconChanged(); + for (int i=0; i<mActiveSessions.size(); i++) { + mActiveSessions.get(i).mCallbacks.onPackageIconChanged(); } } break; case MSG_PACKAGE_SIZE_CHANGED: { - if (mCurCallbacks != null) { - mCurCallbacks.onPackageSizeChanged((String)msg.obj); + for (int i=0; i<mActiveSessions.size(); i++) { + mActiveSessions.get(i).mCallbacks.onPackageSizeChanged( + (String)msg.obj); } } break; case MSG_ALL_SIZES_COMPUTED: { - if (mCurCallbacks != null) { - mCurCallbacks.onAllSizesComputed(); + for (int i=0; i<mActiveSessions.size(); i++) { + mActiveSessions.get(i).mCallbacks.onAllSizesComputed(); } } break; case MSG_RUNNING_STATE_CHANGED: { - if (mCurCallbacks != null) { - mCurCallbacks.onRunningStateChanged(msg.arg1 != 0); + for (int i=0; i<mActiveSessions.size(); i++) { + mActiveSessions.get(i).mCallbacks.onRunningStateChanged( + msg.arg1 != 0); } } break; } @@ -391,157 +410,226 @@ public class ApplicationsState { } } - void resume(Callbacks callbacks) { - if (DEBUG_LOCKING) Log.v(TAG, "resume about to acquire lock..."); - synchronized (mEntriesMap) { - mCurCallbacks = callbacks; - mResumed = true; - if (mPackageIntentReceiver == null) { - mPackageIntentReceiver = new PackageIntentReceiver(); - mPackageIntentReceiver.registerReceiver(); - } - mApplications = mPm.getInstalledApplications( - PackageManager.GET_UNINSTALLED_PACKAGES | - PackageManager.GET_DISABLED_COMPONENTS); - if (mApplications == null) { - mApplications = new ArrayList<ApplicationInfo>(); - } - - if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { - // If an interesting part of the configuration has changed, we - // should completely reload the app entries. - mEntriesMap.clear(); - mAppEntries.clear(); - } else { - for (int i=0; i<mAppEntries.size(); i++) { - mAppEntries.get(i).sizeStale = true; - } - } + public class Session { + final Callbacks mCallbacks; + boolean mResumed; - for (int i=0; i<mApplications.size(); i++) { - final ApplicationInfo info = mApplications.get(i); - // Need to trim out any applications that are disabled by - // something different than the user. - if (!info.enabled && info.enabledSetting - != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { - mApplications.remove(i); - i--; - continue; - } - final AppEntry entry = mEntriesMap.get(info.packageName); - if (entry != null) { - entry.info = info; + // Rebuilding of app list. Synchronized on mRebuildSync. + final Object mRebuildSync = new Object(); + boolean mRebuildRequested; + boolean mRebuildAsync; + AppFilter mRebuildFilter; + Comparator<AppEntry> mRebuildComparator; + ArrayList<AppEntry> mRebuildResult; + ArrayList<AppEntry> mLastAppList; + + Session(Callbacks callbacks) { + mCallbacks = callbacks; + } + + public void resume() { + if (DEBUG_LOCKING) Log.v(TAG, "resume about to acquire lock..."); + synchronized (mEntriesMap) { + if (!mResumed) { + mResumed = true; + mSessionsChanged = true; + doResumeIfNeededLocked(); } } - mCurComputingSizePkg = null; - if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) { - mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES); - } if (DEBUG_LOCKING) Log.v(TAG, "...resume releasing lock"); } - } - void pause() { - if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock..."); - synchronized (mEntriesMap) { - mCurCallbacks = null; - mResumed = false; - if (DEBUG_LOCKING) Log.v(TAG, "...pause releasing lock"); + public void pause() { + if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock..."); + synchronized (mEntriesMap) { + if (mResumed) { + mResumed = false; + mSessionsChanged = true; + mBackgroundHandler.removeMessages(BackgroundHandler.MSG_REBUILD_LIST, this); + doPauseIfNeededLocked(); + } + if (DEBUG_LOCKING) Log.v(TAG, "...pause releasing lock"); + } } - } - // Creates a new list of app entries with the given filter and comparator. - ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator) { - synchronized (mRebuildSync) { - mRebuildRequested = true; - mRebuildAsync = false; - mRebuildFilter = filter; - mRebuildComparator = comparator; - mRebuildResult = null; - if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) { - mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_REBUILD_LIST); - } - - // We will wait for .25s for the list to be built. - long waitend = SystemClock.uptimeMillis()+250; - - while (mRebuildResult == null) { - long now = SystemClock.uptimeMillis(); - if (now >= waitend) { - break; + // Creates a new list of app entries with the given filter and comparator. + ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator) { + synchronized (mRebuildSync) { + synchronized (mEntriesMap) { + mRebuildingSessions.add(this); + mRebuildRequested = true; + mRebuildAsync = false; + mRebuildFilter = filter; + mRebuildComparator = comparator; + mRebuildResult = null; + if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) { + Message msg = mBackgroundHandler.obtainMessage( + BackgroundHandler.MSG_REBUILD_LIST); + mBackgroundHandler.sendMessage(msg); + } } - try { - mRebuildSync.wait(waitend - now); - } catch (InterruptedException e) { + + // We will wait for .25s for the list to be built. + long waitend = SystemClock.uptimeMillis()+250; + + while (mRebuildResult == null) { + long now = SystemClock.uptimeMillis(); + if (now >= waitend) { + break; + } + try { + mRebuildSync.wait(waitend - now); + } catch (InterruptedException e) { + } } - } - mRebuildAsync = true; + mRebuildAsync = true; - return mRebuildResult; + return mRebuildResult; + } } - } - void handleRebuildList() { - AppFilter filter; - Comparator<AppEntry> comparator; - synchronized (mRebuildSync) { - if (!mRebuildRequested) { - return; + void handleRebuildList() { + AppFilter filter; + Comparator<AppEntry> comparator; + synchronized (mRebuildSync) { + if (!mRebuildRequested) { + return; + } + + filter = mRebuildFilter; + comparator = mRebuildComparator; + mRebuildRequested = false; + mRebuildFilter = null; + mRebuildComparator = null; } - filter = mRebuildFilter; - comparator = mRebuildComparator; - mRebuildRequested = false; - mRebuildFilter = null; - mRebuildComparator = null; - } + Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); - Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); + if (filter != null) { + filter.init(); + } + + List<ApplicationInfo> apps; + synchronized (mEntriesMap) { + apps = new ArrayList<ApplicationInfo>(mApplications); + } - if (filter != null) { - filter.init(); + ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>(); + if (DEBUG) Log.i(TAG, "Rebuilding..."); + for (int i=0; i<apps.size(); i++) { + ApplicationInfo info = apps.get(i); + if (filter == null || filter.filterApp(info)) { + synchronized (mEntriesMap) { + if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock"); + AppEntry entry = getEntryLocked(info); + entry.ensureLabel(mContext); + if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry); + filteredApps.add(entry); + if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock"); + } + } + } + + Collections.sort(filteredApps, comparator); + + synchronized (mRebuildSync) { + if (!mRebuildRequested) { + mLastAppList = filteredApps; + if (!mRebuildAsync) { + mRebuildResult = filteredApps; + mRebuildSync.notifyAll(); + } else { + if (!mMainHandler.hasMessages(MainHandler.MSG_REBUILD_COMPLETE, this)) { + Message msg = mMainHandler.obtainMessage( + MainHandler.MSG_REBUILD_COMPLETE, this); + mMainHandler.sendMessage(msg); + } + } + } + } + + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } - - List<ApplicationInfo> apps; + + public void release() { + pause(); + synchronized (mEntriesMap) { + mSessions.remove(this); + } + } + } + + public Session newSession(Callbacks callbacks) { + Session s = new Session(callbacks); synchronized (mEntriesMap) { - apps = new ArrayList<ApplicationInfo>(mApplications); + mSessions.add(s); } + return s; + } - ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>(); - if (DEBUG) Log.i(TAG, "Rebuilding..."); - for (int i=0; i<apps.size(); i++) { - ApplicationInfo info = apps.get(i); - if (filter == null || filter.filterApp(info)) { - synchronized (mEntriesMap) { - if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock"); - AppEntry entry = getEntryLocked(info); - entry.ensureLabel(mContext); - if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry); - filteredApps.add(entry); - if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock"); - } + void doResumeIfNeededLocked() { + if (mResumed) { + return; + } + mResumed = true; + if (mPackageIntentReceiver == null) { + mPackageIntentReceiver = new PackageIntentReceiver(); + mPackageIntentReceiver.registerReceiver(); + } + mApplications = mPm.getInstalledApplications( + PackageManager.GET_UNINSTALLED_PACKAGES | + PackageManager.GET_DISABLED_COMPONENTS); + if (mApplications == null) { + mApplications = new ArrayList<ApplicationInfo>(); + } + + if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { + // If an interesting part of the configuration has changed, we + // should completely reload the app entries. + mEntriesMap.clear(); + mAppEntries.clear(); + } else { + for (int i=0; i<mAppEntries.size(); i++) { + mAppEntries.get(i).sizeStale = true; } } - Collections.sort(filteredApps, comparator); - - synchronized (mRebuildSync) { - if (!mRebuildRequested) { - if (!mRebuildAsync) { - mRebuildResult = filteredApps; - mRebuildSync.notifyAll(); - } else { - if (!mMainHandler.hasMessages(MainHandler.MSG_REBUILD_COMPLETE)) { - Message msg = mMainHandler.obtainMessage( - MainHandler.MSG_REBUILD_COMPLETE, filteredApps); - mMainHandler.sendMessage(msg); - } - } + for (int i=0; i<mApplications.size(); i++) { + final ApplicationInfo info = mApplications.get(i); + // Need to trim out any applications that are disabled by + // something different than the user. + if (!info.enabled && info.enabledSetting + != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { + mApplications.remove(i); + i--; + continue; + } + final AppEntry entry = mEntriesMap.get(info.packageName); + if (entry != null) { + entry.info = info; } } + mCurComputingSizePkg = null; + if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) { + mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES); + } + } - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + void doPauseIfNeededLocked() { + if (!mResumed) { + return; + } + for (int i=0; i<mSessions.size(); i++) { + if (mSessions.get(i).mResumed) { + return; + } + } + mResumed = false; + if (mPackageIntentReceiver != null) { + mPackageIntentReceiver.unregisterReceiver(); + mPackageIntentReceiver = null; + } } AppEntry getEntry(String packageName) { @@ -772,7 +860,18 @@ public class ApplicationsState { @Override public void handleMessage(Message msg) { // Always try rebuilding list first thing, if needed. - handleRebuildList(); + ArrayList<Session> rebuildingSessions = null; + synchronized (mEntriesMap) { + if (mRebuildingSessions.size() > 0) { + rebuildingSessions = new ArrayList<Session>(mRebuildingSessions); + mRebuildingSessions.clear(); + } + } + if (rebuildingSessions != null) { + for (int i=0; i<rebuildingSessions.size(); i++) { + rebuildingSessions.get(i).handleRebuildList(); + } + } switch (msg.what) { case MSG_REBUILD_LIST: { |