Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b3a2cf2 authored by Winson Chung's avatar Winson Chung
Browse files

Prevent multiple RemoteViewAdapters from being set for the same intent.

Fixing issue where we were comparing and storing intents incorrectly in the RemoteViewsService reference counting scheme.

Change-Id: Iedf5997ed3a3ee7f8729cf8689121913196571f8
parent c5958f8a
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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);
    }

+9 −0
Original line number Diff line number Diff line
@@ -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);
    }

+7 −0
Original line number Diff line number Diff line
@@ -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();
+16 −11
Original line number Diff line number Diff line
@@ -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);
                }
            }
        }