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

Commit 78c926c9 authored by Olawale Ogunwale's avatar Olawale Ogunwale Committed by Android Git Automerger
Browse files

am bcfa7cb2: am 259a649a: am 6091dcbb: Merge "[ActivityManager] Improve...

am bcfa7cb2: am 259a649a: am 6091dcbb: Merge "[ActivityManager] Improve multi-thread access the same provider"

* commit 'bcfa7cb2':
  [ActivityManager] Improve multi-thread access the same provider
parents ee006da8 bcfa7cb2
Loading
Loading
Loading
Loading
+69 −33
Original line number Diff line number Diff line
@@ -254,18 +254,21 @@ public final class ActivityThread {
        }
    }

    static final class AcquiringProviderRecord {
        IActivityManager.ContentProviderHolder holder;
        boolean acquiring = true;
        int requests = 1;
    }

    // The lock of mProviderMap protects the following variables.
    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
        = new ArrayMap<ProviderKey, ProviderClientRecord>();
    final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
        = new ArrayMap<IBinder, ProviderRefCount>();
    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
        = new ArrayMap<IBinder, ProviderClientRecord>();
    final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
            = new ArrayMap<ComponentName, ProviderClientRecord>();
    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<>();
    final ArrayMap<ProviderKey, AcquiringProviderRecord> mAcquiringProviderMap = new ArrayMap<>();
    final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap = new ArrayMap<>();
    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders = new ArrayMap<>();
    final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName = new ArrayMap<>();

    final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
        = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
            = new ArrayMap<>();

    final GcIdler mGcIdler = new GcIdler();
    boolean mGcIdlerScheduled = false;
@@ -345,7 +348,7 @@ public final class ActivityThread {
        }
    }

    final class ProviderClientRecord {
    static final class ProviderClientRecord {
        final String[] mNames;
        final IContentProvider mProvider;
        final ContentProvider mLocalProvider;
@@ -4693,23 +4696,58 @@ public final class ActivityThread {

    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        final ProviderKey key = new ProviderKey(auth, userId);
        final IContentProvider provider = acquireExistingProvider(c, key, stable);
        if (provider != null) {
            return provider;
        }
        AcquiringProviderRecord r;
        boolean first = false;
        synchronized (mAcquiringProviderMap) {
            r = mAcquiringProviderMap.get(key);
            if (r == null) {
                r = new AcquiringProviderRecord();
                mAcquiringProviderMap.put(key, r);
                first = true;
            } else {
                r.requests++;
            }
        }

        // There is a possible race here.  Another thread may try to acquire
        // the same provider at the same time.  When this happens, we want to ensure
        // that the first one wins.
        IActivityManager.ContentProviderHolder holder = null;
        if (first) {
            // Multiple threads may try to acquire the same provider at the same time.
            // When this happens, we only let the first one really gets provider.
            // Other threads just wait for its result.
            // Note that we cannot hold the lock while acquiring and installing the
            // provider since it might take a long time to run and it could also potentially
            // be re-entrant in the case where the provider is in the same process.
        IActivityManager.ContentProviderHolder holder = null;
            try {
                holder = ActivityManagerNative.getDefault().getContentProvider(
                        getApplicationThread(), auth, userId, stable);
            } catch (RemoteException ex) {
            }
            synchronized (r) {
                r.holder = holder;
                r.acquiring = false;
                r.notifyAll();
            }
        } else {
            synchronized (r) {
                while (r.acquiring) {
                    try {
                        r.wait();
                    } catch (InterruptedException e) {
                    }
                }
                holder = r.holder;
            }
        }
        synchronized (mAcquiringProviderMap) {
            if (--r.requests == 0) {
                mAcquiringProviderMap.remove(key);
            }
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + auth);
            return null;
@@ -4792,8 +4830,12 @@ public final class ActivityThread {

    public final IContentProvider acquireExistingProvider(
            Context c, String auth, int userId, boolean stable) {
        return acquireExistingProvider(c, new ProviderKey(auth, userId), stable);
    }

    final IContentProvider acquireExistingProvider(
            Context c, ProviderKey key, boolean stable) {
        synchronized (mProviderMap) {
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord pr = mProviderMap.get(key);
            if (pr == null) {
                return null;
@@ -4804,7 +4846,7 @@ public final class ActivityThread {
            if (!jBinder.isBinderAlive()) {
                // The hosting process of the provider has died; we can't
                // use this one.
                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
                Log.i(TAG, "Acquiring provider " + key.authority + " for user " +  key.userId
                        + ": existing object's process dead");
                handleUnstableProviderDiedLocked(jBinder, true);
                return null;
@@ -5126,18 +5168,12 @@ public final class ActivityThread {
                    if (DEBUG_PROVIDER) {
                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
                    }
                    // We need to transfer our new reference to the existing
                    // ref count, releasing the old one...  but only if
                    // release is needed (that is, it is not running in the
                    // system process).
                    // The provider has already been installed, so we need
                    // to increase reference count to the existing one, but
                    // only if release is needed (that is, it is not running
                    // in the system process or local to the process).
                    if (!noReleaseNeeded) {
                        incProviderRefLocked(prc, stable);
                        try {
                            ActivityManagerNative.getDefault().removeContentProvider(
                                    holder.connection, stable);
                        } catch (RemoteException e) {
                            //do nothing content provider object is dead any way
                        }
                    }
                } else {
                    ProviderClientRecord client = installProviderAuthoritiesLocked(