diff options
author | Svetoslav Ganov <svetoslavganov@google.com> | 2012-05-07 18:23:44 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-05-07 18:23:44 -0700 |
commit | b1ae25cb37e92a30d196290b75a159e5382c5b34 (patch) | |
tree | 2fa20cf2a87868d09cbd7f630874f4177d0e34f7 /core/java/android/widget/ActivityChooserModel.java | |
parent | b2ee0d57672faf42ca88fa878dc7e688046c915e (diff) | |
parent | ca858797816be82e2b1e2b88dea17b20e52d8429 (diff) | |
download | frameworks_base-b1ae25cb37e92a30d196290b75a159e5382c5b34.zip frameworks_base-b1ae25cb37e92a30d196290b75a159e5382c5b34.tar.gz frameworks_base-b1ae25cb37e92a30d196290b75a159e5382c5b34.tar.bz2 |
Merge "ActivityChooserModel does not handle package changes on the thread that created it." into jb-dev
Diffstat (limited to 'core/java/android/widget/ActivityChooserModel.java')
-rw-r--r-- | core/java/android/widget/ActivityChooserModel.java | 547 |
1 files changed, 244 insertions, 303 deletions
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java index fba8d3a..1578154 100644 --- a/core/java/android/widget/ActivityChooserModel.java +++ b/core/java/android/widget/ActivityChooserModel.java @@ -21,9 +21,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; import android.database.DataSetObservable; -import android.database.DataSetObserver; import android.os.AsyncTask; -import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.util.Xml; @@ -42,10 +40,8 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; /** * <p> @@ -239,7 +235,7 @@ public class ActivityChooserModel extends DataSetObservable { /** * List of activities that can handle the current intent. */ - private final List<ActivityResolveInfo> mActivites = new ArrayList<ActivityResolveInfo>(); + private final List<ActivityResolveInfo> mActivities = new ArrayList<ActivityResolveInfo>(); /** * List with historical choice records. @@ -278,18 +274,18 @@ public class ActivityChooserModel extends DataSetObservable { /** * Flag whether choice history can be read. In general many clients can - * share the same data model and {@link #readHistoricalData()} may be called + * share the same data model and {@link #readHistoricalDataIfNeeded()} may be called * by arbitrary of them any number of times. Therefore, this class guarantees * that the very first read succeeds and subsequent reads can be performed - * only after a call to {@link #persistHistoricalData()} followed by change + * only after a call to {@link #persistHistoricalDataIfNeeded()} followed by change * of the share records. */ private boolean mCanReadHistoricalData = true; /** * Flag whether the choice history was read. This is used to enforce that - * before calling {@link #persistHistoricalData()} a call to - * {@link #persistHistoricalData()} has been made. This aims to avoid a + * before calling {@link #persistHistoricalDataIfNeeded()} a call to + * {@link #persistHistoricalDataIfNeeded()} has been made. This aims to avoid a * scenario in which a choice history file exits, it is not read yet and * it is overwritten. Note that always all historical records are read in * full and the file is rewritten. This is necessary since we need to @@ -299,16 +295,16 @@ public class ActivityChooserModel extends DataSetObservable { /** * Flag whether the choice records have changed. In general many clients can - * share the same data model and {@link #persistHistoricalData()} may be called + * share the same data model and {@link #persistHistoricalDataIfNeeded()} may be called * by arbitrary of them any number of times. Therefore, this class guarantees * that choice history will be persisted only if it has changed. */ private boolean mHistoricalRecordsChanged = true; /** - * Hander for scheduling work on client tread. + * Flag whether to reload the activities for the current intent. */ - private final Handler mHandler = new Handler(); + private boolean mReloadActivities = false; /** * Policy for controlling how the model handles chosen activities. @@ -346,7 +342,6 @@ public class ActivityChooserModel extends DataSetObservable { dataModel = new ActivityChooserModel(context, historyFileName); sDataModelRegistry.put(historyFileName, dataModel); } - dataModel.readHistoricalData(); return dataModel; } } @@ -383,7 +378,8 @@ public class ActivityChooserModel extends DataSetObservable { return; } mIntent = intent; - loadActivitiesLocked(); + mReloadActivities = true; + ensureConsistentState(); } } @@ -407,7 +403,8 @@ public class ActivityChooserModel extends DataSetObservable { */ public int getActivityCount() { synchronized (mInstanceLock) { - return mActivites.size(); + ensureConsistentState(); + return mActivities.size(); } } @@ -421,7 +418,8 @@ public class ActivityChooserModel extends DataSetObservable { */ public ResolveInfo getActivity(int index) { synchronized (mInstanceLock) { - return mActivites.get(index).resolveInfo; + ensureConsistentState(); + return mActivities.get(index).resolveInfo; } } @@ -433,15 +431,18 @@ public class ActivityChooserModel extends DataSetObservable { * @return The index if found, -1 otherwise. */ public int getActivityIndex(ResolveInfo activity) { - List<ActivityResolveInfo> activities = mActivites; - final int activityCount = activities.size(); - for (int i = 0; i < activityCount; i++) { - ActivityResolveInfo currentActivity = activities.get(i); - if (currentActivity.resolveInfo == activity) { - return i; + synchronized (mInstanceLock) { + ensureConsistentState(); + List<ActivityResolveInfo> activities = mActivities; + final int activityCount = activities.size(); + for (int i = 0; i < activityCount; i++) { + ActivityResolveInfo currentActivity = activities.get(i); + if (currentActivity.resolveInfo == activity) { + return i; + } } + return INVALID_INDEX; } - return INVALID_INDEX; } /** @@ -462,30 +463,34 @@ public class ActivityChooserModel extends DataSetObservable { * @see OnChooseActivityListener */ public Intent chooseActivity(int index) { - ActivityResolveInfo chosenActivity = mActivites.get(index); + synchronized (mInstanceLock) { + ensureConsistentState(); - ComponentName chosenName = new ComponentName( - chosenActivity.resolveInfo.activityInfo.packageName, - chosenActivity.resolveInfo.activityInfo.name); + ActivityResolveInfo chosenActivity = mActivities.get(index); - Intent choiceIntent = new Intent(mIntent); - choiceIntent.setComponent(chosenName); + ComponentName chosenName = new ComponentName( + chosenActivity.resolveInfo.activityInfo.packageName, + chosenActivity.resolveInfo.activityInfo.name); - if (mActivityChoserModelPolicy != null) { - // Do not allow the policy to change the intent. - Intent choiceIntentCopy = new Intent(choiceIntent); - final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this, - choiceIntentCopy); - if (handled) { - return null; + Intent choiceIntent = new Intent(mIntent); + choiceIntent.setComponent(chosenName); + + if (mActivityChoserModelPolicy != null) { + // Do not allow the policy to change the intent. + Intent choiceIntentCopy = new Intent(choiceIntent); + final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this, + choiceIntentCopy); + if (handled) { + return null; + } } - } - HistoricalRecord historicalRecord = new HistoricalRecord(chosenName, - System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT); - addHisoricalRecord(historicalRecord); + HistoricalRecord historicalRecord = new HistoricalRecord(chosenName, + System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT); + addHisoricalRecord(historicalRecord); - return choiceIntent; + return choiceIntent; + } } /** @@ -494,7 +499,9 @@ public class ActivityChooserModel extends DataSetObservable { * @param listener The listener. */ public void setOnChooseActivityListener(OnChooseActivityListener listener) { - mActivityChoserModelPolicy = listener; + synchronized (mInstanceLock) { + mActivityChoserModelPolicy = listener; + } } /** @@ -508,8 +515,9 @@ public class ActivityChooserModel extends DataSetObservable { */ public ResolveInfo getDefaultActivity() { synchronized (mInstanceLock) { - if (!mActivites.isEmpty()) { - return mActivites.get(0).resolveInfo; + ensureConsistentState(); + if (!mActivities.isEmpty()) { + return mActivities.get(0).resolveInfo; } } return null; @@ -526,72 +534,50 @@ public class ActivityChooserModel extends DataSetObservable { * @param index The index of the activity to set as default. */ public void setDefaultActivity(int index) { - ActivityResolveInfo newDefaultActivity = mActivites.get(index); - ActivityResolveInfo oldDefaultActivity = mActivites.get(0); - - final float weight; - if (oldDefaultActivity != null) { - // Add a record with weight enough to boost the chosen at the top. - weight = oldDefaultActivity.weight - newDefaultActivity.weight - + DEFAULT_ACTIVITY_INFLATION; - } else { - weight = DEFAULT_HISTORICAL_RECORD_WEIGHT; - } - - ComponentName defaultName = new ComponentName( - newDefaultActivity.resolveInfo.activityInfo.packageName, - newDefaultActivity.resolveInfo.activityInfo.name); - HistoricalRecord historicalRecord = new HistoricalRecord(defaultName, - System.currentTimeMillis(), weight); - addHisoricalRecord(historicalRecord); - } - - /** - * Reads the history data from the backing file if the latter - * was provided. Calling this method more than once before a call - * to {@link #persistHistoricalData()} has been made has no effect. - * <p> - * <strong>Note:</strong> Historical data is read asynchronously and - * as soon as the reading is completed any registered - * {@link DataSetObserver}s will be notified. Also no historical - * data is read until this method is invoked. - * <p> - */ - private void readHistoricalData() { synchronized (mInstanceLock) { - if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) { - return; - } - mCanReadHistoricalData = false; - mReadShareHistoryCalled = true; - if (!TextUtils.isEmpty(mHistoryFileName)) { - AsyncTask.SERIAL_EXECUTOR.execute(new HistoryLoader()); + ensureConsistentState(); + + ActivityResolveInfo newDefaultActivity = mActivities.get(index); + ActivityResolveInfo oldDefaultActivity = mActivities.get(0); + + final float weight; + if (oldDefaultActivity != null) { + // Add a record with weight enough to boost the chosen at the top. + weight = oldDefaultActivity.weight - newDefaultActivity.weight + + DEFAULT_ACTIVITY_INFLATION; + } else { + weight = DEFAULT_HISTORICAL_RECORD_WEIGHT; } + + ComponentName defaultName = new ComponentName( + newDefaultActivity.resolveInfo.activityInfo.packageName, + newDefaultActivity.resolveInfo.activityInfo.name); + HistoricalRecord historicalRecord = new HistoricalRecord(defaultName, + System.currentTimeMillis(), weight); + addHisoricalRecord(historicalRecord); } } /** * Persists the history data to the backing file if the latter - * was provided. Calling this method before a call to {@link #readHistoricalData()} + * was provided. Calling this method before a call to {@link #readHistoricalDataIfNeeded()} * throws an exception. Calling this method more than one without choosing an * activity has not effect. * * @throws IllegalStateException If this method is called before a call to - * {@link #readHistoricalData()}. + * {@link #readHistoricalDataIfNeeded()}. */ - private void persistHistoricalData() { - synchronized (mInstanceLock) { - if (!mReadShareHistoryCalled) { - throw new IllegalStateException("No preceding call to #readHistoricalData"); - } - if (!mHistoricalRecordsChanged) { - return; - } - mHistoricalRecordsChanged = false; - mCanReadHistoricalData = true; - if (!TextUtils.isEmpty(mHistoryFileName)) { - AsyncTask.SERIAL_EXECUTOR.execute(new HistoryPersister()); - } + private void persistHistoricalDataIfNeeded() { + if (!mReadShareHistoryCalled) { + throw new IllegalStateException("No preceding call to #readHistoricalData"); + } + if (!mHistoricalRecordsChanged) { + return; + } + mHistoricalRecordsChanged = false; + if (!TextUtils.isEmpty(mHistoryFileName)) { + new PersistHistoryAsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, + new ArrayList<HistoricalRecord>(mHistoricalRecords), mHistoryFileName); } } @@ -608,21 +594,7 @@ public class ActivityChooserModel extends DataSetObservable { return; } mActivitySorter = activitySorter; - sortActivities(); - } - } - - /** - * Sorts the activities based on history and an intent. If - * a sorter is not specified this a default implementation is used. - * - * @see #setActivitySorter(ActivitySorter) - */ - private void sortActivities() { - synchronized (mInstanceLock) { - if (mActivitySorter != null && !mActivites.isEmpty()) { - mActivitySorter.sort(mIntent, mActivites, - Collections.unmodifiableList(mHistoricalRecords)); + if (sortActivitiesIfNeeded()) { notifyChanged(); } } @@ -647,8 +619,10 @@ public class ActivityChooserModel extends DataSetObservable { return; } mHistoryMaxSize = historyMaxSize; - pruneExcessiveHistoricalRecordsLocked(); - sortActivities(); + pruneExcessiveHistoricalRecordsIfNeeded(); + if (sortActivitiesIfNeeded()) { + notifyChanged(); + } } } @@ -670,6 +644,7 @@ public class ActivityChooserModel extends DataSetObservable { */ public int getHistorySize() { synchronized (mInstanceLock) { + ensureConsistentState(); return mHistoricalRecords.size(); } } @@ -681,82 +656,110 @@ public class ActivityChooserModel extends DataSetObservable { } /** - * Adds a historical record. - * - * @param historicalRecord The record to add. - * @return True if the record was added. + * Ensures the model is in a consistent state which is the + * activities for the current intent have been loaded, the + * most recent history has been read, and the activities + * are sorted. */ - private boolean addHisoricalRecord(HistoricalRecord historicalRecord) { - synchronized (mInstanceLock) { - final boolean added = mHistoricalRecords.add(historicalRecord); - if (added) { - mHistoricalRecordsChanged = true; - pruneExcessiveHistoricalRecordsLocked(); - persistHistoricalData(); - sortActivities(); - } - return added; + private void ensureConsistentState() { + boolean stateChanged = loadActivitiesIfNeeded(); + stateChanged |= readHistoricalDataIfNeeded(); + pruneExcessiveHistoricalRecordsIfNeeded(); + if (stateChanged) { + sortActivitiesIfNeeded(); + notifyChanged(); } } /** - * Prunes older excessive records to guarantee {@link #mHistoryMaxSize}. + * Sorts the activities if necessary which is if there is a + * sorter, there are some activities to sort, and there is some + * historical data. + * + * @return Whether sorting was performed. */ - private void pruneExcessiveHistoricalRecordsLocked() { - List<HistoricalRecord> choiceRecords = mHistoricalRecords; - final int pruneCount = choiceRecords.size() - mHistoryMaxSize; - if (pruneCount <= 0) { - return; - } - mHistoricalRecordsChanged = true; - for (int i = 0; i < pruneCount; i++) { - HistoricalRecord prunedRecord = choiceRecords.remove(0); - if (DEBUG) { - Log.i(LOG_TAG, "Pruned: " + prunedRecord); - } + private boolean sortActivitiesIfNeeded() { + if (mActivitySorter != null && mIntent != null + && !mActivities.isEmpty() && !mHistoricalRecords.isEmpty()) { + mActivitySorter.sort(mIntent, mActivities, + Collections.unmodifiableList(mHistoricalRecords)); + return true; } + return false; } /** - * Loads the activities. + * Loads the activities for the current intent if needed which is + * if they are not already loaded for the current intent. + * + * @return Whether loading was performed. */ - private void loadActivitiesLocked() { - mActivites.clear(); - if (mIntent != null) { - List<ResolveInfo> resolveInfos = - mContext.getPackageManager().queryIntentActivities(mIntent, 0); + private boolean loadActivitiesIfNeeded() { + if (mReloadActivities && mIntent != null) { + mReloadActivities = false; + mActivities.clear(); + List<ResolveInfo> resolveInfos = mContext.getPackageManager() + .queryIntentActivities(mIntent, 0); final int resolveInfoCount = resolveInfos.size(); for (int i = 0; i < resolveInfoCount; i++) { ResolveInfo resolveInfo = resolveInfos.get(i); - mActivites.add(new ActivityResolveInfo(resolveInfo)); + mActivities.add(new ActivityResolveInfo(resolveInfo)); } - sortActivities(); - } else { - notifyChanged(); + return true; } + return false; } /** - * Prunes historical records for a package that goes away. + * Reads the historical data if necessary which is it has + * changed, there is a history file, and there is not persist + * in progress. * - * @param packageName The name of the package that goes away. + * @return Whether reading was performed. */ - private void pruneHistoricalRecordsForPackageLocked(String packageName) { - boolean recordsRemoved = false; - - List<HistoricalRecord> historicalRecords = mHistoricalRecords; - for (int i = 0; i < historicalRecords.size(); i++) { - HistoricalRecord historicalRecord = historicalRecords.get(i); - String recordPackageName = historicalRecord.activity.getPackageName(); - if (recordPackageName.equals(packageName)) { - historicalRecords.remove(historicalRecord); - recordsRemoved = true; - } + private boolean readHistoricalDataIfNeeded() { + if (mCanReadHistoricalData && mHistoricalRecordsChanged && + !TextUtils.isEmpty(mHistoryFileName)) { + mCanReadHistoricalData = false; + mReadShareHistoryCalled = true; + readHistoricalDataImpl(); + return true; } + return false; + } - if (recordsRemoved) { + /** + * Adds a historical record. + * + * @param historicalRecord The record to add. + * @return True if the record was added. + */ + private boolean addHisoricalRecord(HistoricalRecord historicalRecord) { + final boolean added = mHistoricalRecords.add(historicalRecord); + if (added) { mHistoricalRecordsChanged = true; - sortActivities(); + pruneExcessiveHistoricalRecordsIfNeeded(); + persistHistoricalDataIfNeeded(); + sortActivitiesIfNeeded(); + notifyChanged(); + } + return added; + } + + /** + * Prunes older excessive records to guarantee maxHistorySize. + */ + private void pruneExcessiveHistoricalRecordsIfNeeded() { + final int pruneCount = mHistoricalRecords.size() - mHistoryMaxSize; + if (pruneCount <= 0) { + return; + } + mHistoricalRecordsChanged = true; + for (int i = 0; i < pruneCount; i++) { + HistoricalRecord prunedRecord = mHistoricalRecords.remove(0); + if (DEBUG) { + Log.i(LOG_TAG, "Pruned: " + prunedRecord); + } } } @@ -974,112 +977,72 @@ public class ActivityChooserModel extends DataSetObservable { /** * Command for reading the historical records from a file off the UI thread. */ - private final class HistoryLoader implements Runnable { - - public void run() { - FileInputStream fis = null; - try { - fis = mContext.openFileInput(mHistoryFileName); - } catch (FileNotFoundException fnfe) { - if (DEBUG) { - Log.i(LOG_TAG, "Could not open historical records file: " + mHistoryFileName); - } - return; + private void readHistoricalDataImpl() { + FileInputStream fis = null; + try { + fis = mContext.openFileInput(mHistoryFileName); + } catch (FileNotFoundException fnfe) { + if (DEBUG) { + Log.i(LOG_TAG, "Could not open historical records file: " + mHistoryFileName); } - try { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); - - int type = XmlPullParser.START_DOCUMENT; - while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { - type = parser.next(); - } - - if (!TAG_HISTORICAL_RECORDS.equals(parser.getName())) { - throw new XmlPullParserException("Share records file does not start with " - + TAG_HISTORICAL_RECORDS + " tag."); - } - - List<HistoricalRecord> readRecords = new ArrayList<HistoricalRecord>(); + return; + } + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(fis, null); - while (true) { - type = parser.next(); - if (type == XmlPullParser.END_DOCUMENT) { - break; - } - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - String nodeName = parser.getName(); - if (!TAG_HISTORICAL_RECORD.equals(nodeName)) { - throw new XmlPullParserException("Share records file not well-formed."); - } + int type = XmlPullParser.START_DOCUMENT; + while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { + type = parser.next(); + } - String activity = parser.getAttributeValue(null, ATTRIBUTE_ACTIVITY); - final long time = - Long.parseLong(parser.getAttributeValue(null, ATTRIBUTE_TIME)); - final float weight = - Float.parseFloat(parser.getAttributeValue(null, ATTRIBUTE_WEIGHT)); + if (!TAG_HISTORICAL_RECORDS.equals(parser.getName())) { + throw new XmlPullParserException("Share records file does not start with " + + TAG_HISTORICAL_RECORDS + " tag."); + } - HistoricalRecord readRecord = new HistoricalRecord(activity, time, - weight); - readRecords.add(readRecord); + List<HistoricalRecord> historicalRecords = mHistoricalRecords; + historicalRecords.clear(); - if (DEBUG) { - Log.i(LOG_TAG, "Read " + readRecord.toString()); - } + while (true) { + type = parser.next(); + if (type == XmlPullParser.END_DOCUMENT) { + break; } - - if (DEBUG) { - Log.i(LOG_TAG, "Read " + readRecords.size() + " historical records."); + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + String nodeName = parser.getName(); + if (!TAG_HISTORICAL_RECORD.equals(nodeName)) { + throw new XmlPullParserException("Share records file not well-formed."); } - synchronized (mInstanceLock) { - Set<HistoricalRecord> uniqueShareRecords = - new LinkedHashSet<HistoricalRecord>(readRecords); - - // Make sure no duplicates. Example: Read a file with - // one record, add one record, persist the two records, - // add a record, read the persisted records - the - // read two records should not be added again. - List<HistoricalRecord> historicalRecords = mHistoricalRecords; - final int historicalRecordsCount = historicalRecords.size(); - for (int i = historicalRecordsCount - 1; i >= 0; i--) { - HistoricalRecord historicalRecord = historicalRecords.get(i); - uniqueShareRecords.add(historicalRecord); - } - - if (historicalRecords.size() == uniqueShareRecords.size()) { - return; - } + String activity = parser.getAttributeValue(null, ATTRIBUTE_ACTIVITY); + final long time = + Long.parseLong(parser.getAttributeValue(null, ATTRIBUTE_TIME)); + final float weight = + Float.parseFloat(parser.getAttributeValue(null, ATTRIBUTE_WEIGHT)); + HistoricalRecord readRecord = new HistoricalRecord(activity, time, weight); + historicalRecords.add(readRecord); - // Make sure the oldest records go to the end. - historicalRecords.clear(); - historicalRecords.addAll(uniqueShareRecords); - - mHistoricalRecordsChanged = true; - - // Do this on the client thread since the client may be on the UI - // thread, wait for data changes which happen during sorting, and - // perform UI modification based on the data change. - mHandler.post(new Runnable() { - public void run() { - pruneExcessiveHistoricalRecordsLocked(); - sortActivities(); - } - }); + if (DEBUG) { + Log.i(LOG_TAG, "Read " + readRecord.toString()); } - } catch (XmlPullParserException xppe) { - Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, xppe); - } catch (IOException ioe) { - Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, ioe); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException ioe) { - /* ignore */ - } + } + + if (DEBUG) { + Log.i(LOG_TAG, "Read " + historicalRecords.size() + " historical records."); + } + } catch (XmlPullParserException xppe) { + Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, xppe); + } catch (IOException ioe) { + Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, ioe); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ioe) { + /* ignore */ } } } @@ -1088,21 +1051,21 @@ public class ActivityChooserModel extends DataSetObservable { /** * Command for persisting the historical records to a file off the UI thread. */ - private final class HistoryPersister implements Runnable { + private final class PersistHistoryAsyncTask extends AsyncTask<Object, Void, Void> { - public void run() { - FileOutputStream fos = null; - List<HistoricalRecord> records = null; + @Override + @SuppressWarnings("unchecked") + public Void doInBackground(Object... args) { + List<HistoricalRecord> historicalRecords = (List<HistoricalRecord>) args[0]; + String hostoryFileName = (String) args[1]; - synchronized (mInstanceLock) { - records = new ArrayList<HistoricalRecord>(mHistoricalRecords); - } + FileOutputStream fos = null; try { - fos = mContext.openFileOutput(mHistoryFileName, Context.MODE_PRIVATE); + fos = mContext.openFileOutput(hostoryFileName, Context.MODE_PRIVATE); } catch (FileNotFoundException fnfe) { - Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, fnfe); - return; + Log.e(LOG_TAG, "Error writing historical recrod file: " + hostoryFileName, fnfe); + return null; } XmlSerializer serializer = Xml.newSerializer(); @@ -1112,11 +1075,12 @@ public class ActivityChooserModel extends DataSetObservable { serializer.startDocument("UTF-8", true); serializer.startTag(null, TAG_HISTORICAL_RECORDS); - final int recordCount = records.size(); + final int recordCount = historicalRecords.size(); for (int i = 0; i < recordCount; i++) { - HistoricalRecord record = records.remove(0); + HistoricalRecord record = historicalRecords.remove(0); serializer.startTag(null, TAG_HISTORICAL_RECORD); - serializer.attribute(null, ATTRIBUTE_ACTIVITY, record.activity.flattenToString()); + serializer.attribute(null, ATTRIBUTE_ACTIVITY, + record.activity.flattenToString()); serializer.attribute(null, ATTRIBUTE_TIME, String.valueOf(record.time)); serializer.attribute(null, ATTRIBUTE_WEIGHT, String.valueOf(record.weight)); serializer.endTag(null, TAG_HISTORICAL_RECORD); @@ -1138,6 +1102,7 @@ public class ActivityChooserModel extends DataSetObservable { } catch (IOException ioe) { Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ioe); } finally { + mCanReadHistoricalData = true; if (fos != null) { try { fos.close(); @@ -1146,6 +1111,7 @@ public class ActivityChooserModel extends DataSetObservable { } } } + return null; } } @@ -1155,33 +1121,8 @@ public class ActivityChooserModel extends DataSetObservable { private final class DataModelPackageMonitor extends PackageMonitor { @Override - public void onPackageAdded(String packageName, int uid) { - synchronized (mInstanceLock) { - loadActivitiesLocked(); - } - } - - @Override - public void onPackageAppeared(String packageName, int reason) { - synchronized (mInstanceLock) { - loadActivitiesLocked(); - } - } - - @Override - public void onPackageRemoved(String packageName, int uid) { - synchronized (mInstanceLock) { - pruneHistoricalRecordsForPackageLocked(packageName); - loadActivitiesLocked(); - } - } - - @Override - public void onPackageDisappeared(String packageName, int reason) { - synchronized (mInstanceLock) { - pruneHistoricalRecordsForPackageLocked(packageName); - loadActivitiesLocked(); - } + public void onSomePackagesChanged() { + mReloadActivities = true; } } } |