Merge "Prevent multiple RemoteViewAdapters from being set for the same intent."

This commit is contained in:
Winson Chung
2010-09-16 17:02:19 -07:00
committed by Android (Google) Code Review
4 changed files with 40 additions and 11 deletions

View File

@@ -4365,6 +4365,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* @param intent the intent used to identify the RemoteViewsService for the adapter to connect to.
*/
public void setRemoteViewsAdapter(Intent intent) {
// Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
// service handling the specified intent.
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
if (mRemoteAdapter != null && fc.equals(mRemoteAdapter.getRemoteViewsServiceIntent())) {
return;
}
// Otherwise, create a new RemoteViewsAdapter for binding
mRemoteAdapter = new RemoteViewsAdapter(getContext(), intent, this);
}

View File

@@ -779,6 +779,15 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
*/
@android.view.RemotableViewMethod
public void setRemoteViewsAdapter(Intent intent) {
// Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
// service handling the specified intent.
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
if (mRemoteViewsAdapter != null &&
fc.equals(mRemoteViewsAdapter.getRemoteViewsServiceIntent())) {
return;
}
// Otherwise, create a new RemoteViewsAdapter for binding
mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
}

View File

@@ -669,6 +669,9 @@ public class RemoteViewsAdapter extends BaseAdapter {
public RemoteViewsAdapter(Context context, Intent intent, RemoteAdapterConnectionCallback callback) {
mContext = context;
mIntent = intent;
if (mIntent == null) {
throw new IllegalArgumentException("Non-null Intent must be specified.");
}
// initialize the worker thread
mWorkerThread = new HandlerThread("RemoteViewsCache-loader");
@@ -689,6 +692,10 @@ public class RemoteViewsAdapter extends BaseAdapter {
unbindService();
}
public Intent getRemoteViewsServiceIntent() {
return mIntent;
}
public int getCount() {
requestBindService();
return mViewCache.getCount();

View File

@@ -36,7 +36,7 @@ public abstract class RemoteViewsService extends Service {
private static final String LOG_TAG = "RemoteViewsService";
// multimap implementation for reference counting
private HashMap<Intent, Pair<RemoteViewsFactory, Integer>> mRemoteViewFactories;
private HashMap<Intent.FilterComparison, Pair<RemoteViewsFactory, Integer>> mRemoteViewFactories;
private final Object mLock = new Object();
/**
@@ -108,26 +108,28 @@ public abstract class RemoteViewsService extends Service {
}
public RemoteViewsService() {
mRemoteViewFactories = new HashMap<Intent, Pair<RemoteViewsFactory, Integer>>();
mRemoteViewFactories =
new HashMap<Intent.FilterComparison, Pair<RemoteViewsFactory, Integer>>();
}
@Override
public IBinder onBind(Intent intent) {
synchronized (mLock) {
// increment the reference count to the particular factory associated with this intent
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
Pair<RemoteViewsFactory, Integer> factoryRef = null;
RemoteViewsFactory factory = null;
if (!mRemoteViewFactories.containsKey(intent)) {
if (!mRemoteViewFactories.containsKey(fc)) {
factory = onGetViewFactory(intent);
factoryRef = new Pair<RemoteViewsFactory, Integer>(factory, 1);
mRemoteViewFactories.put(intent, factoryRef);
mRemoteViewFactories.put(fc, factoryRef);
factory.onCreate();
} else {
Pair<RemoteViewsFactory, Integer> oldFactoryRef = mRemoteViewFactories.get(intent);
Pair<RemoteViewsFactory, Integer> oldFactoryRef = mRemoteViewFactories.get(fc);
factory = oldFactoryRef.first;
int newRefCount = oldFactoryRef.second.intValue() + 1;
factoryRef = new Pair<RemoteViewsFactory, Integer>(oldFactoryRef.first, newRefCount);
mRemoteViewFactories.put(intent, factoryRef);
mRemoteViewFactories.put(fc, factoryRef);
}
return new RemoteViewsFactoryAdapter(factory);
}
@@ -136,16 +138,19 @@ public abstract class RemoteViewsService extends Service {
@Override
public boolean onUnbind(Intent intent) {
synchronized (mLock) {
if (mRemoteViewFactories.containsKey(intent)) {
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
if (mRemoteViewFactories.containsKey(fc)) {
// this alleviates the user's responsibility of having to clear all factories
Pair<RemoteViewsFactory, Integer> oldFactoryRef = mRemoteViewFactories.get(intent);
Pair<RemoteViewsFactory, Integer> oldFactoryRef =
mRemoteViewFactories.get(fc);
int newRefCount = oldFactoryRef.second.intValue() - 1;
if (newRefCount <= 0) {
oldFactoryRef.first.onDestroy();
mRemoteViewFactories.remove(intent);
mRemoteViewFactories.remove(fc);
} else {
Pair<RemoteViewsFactory, Integer> factoryRef = new Pair<RemoteViewsFactory, Integer>(oldFactoryRef.first, newRefCount);
mRemoteViewFactories.put(intent, factoryRef);
Pair<RemoteViewsFactory, Integer> factoryRef =
new Pair<RemoteViewsFactory, Integer>(oldFactoryRef.first, newRefCount);
mRemoteViewFactories.put(fc, factoryRef);
}
}
}