summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/applications/ApplicationsState.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/applications/ApplicationsState.java')
-rw-r--r--src/com/android/settings/applications/ApplicationsState.java389
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: {