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

Commit 9bd766de authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Move the waiting for the publishing of content provider to client side"

parents fb886799 4dc70f1c
Loading
Loading
Loading
Loading
+58 −16
Original line number Diff line number Diff line
@@ -420,6 +420,8 @@ public final class ActivityThread extends ClientTransactionHandler {
    private static final class ProviderKey {
        final String authority;
        final int userId;
        ContentProviderHolder mHolder; // Temp holder to be used between notifier and waiter
        int mWaiters; // Number of threads waiting on the publishing of the provider

        public ProviderKey(String authority, int userId) {
            this.authority = authority;
@@ -437,7 +439,11 @@ public final class ActivityThread extends ClientTransactionHandler {

        @Override
        public int hashCode() {
            return ((authority != null) ? authority.hashCode() : 0) ^ userId;
            return hashCode(authority, userId);
        }

        public static int hashCode(final String auth, final int userIdent) {
            return ((auth != null) ? auth.hashCode() : 0) ^ userIdent;
        }
    }

@@ -458,9 +464,8 @@ public final class ActivityThread extends ClientTransactionHandler {
    // Mitigation for b/74523247: Used to serialize calls to AM.getContentProvider().
    // Note we never removes items from this map but that's okay because there are only so many
    // users and so many authorities.
    // TODO Remove it once we move CPR.wait() from AMS to the client side.
    @GuardedBy("mGetProviderLocks")
    final ArrayMap<ProviderKey, Object> mGetProviderLocks = new ArrayMap<>();
    @GuardedBy("mGetProviderKeys")
    final SparseArray<ProviderKey> mGetProviderKeys = new SparseArray<>();

    final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
        = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -1751,6 +1756,16 @@ public final class ActivityThread extends ClientTransactionHandler {
                    ActivityThread.this, activityToken, actionId, arguments,
                    cancellationSignal, resultCallback));
        }

        @Override
        public void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder,
                @NonNull String auth, int userId, boolean published) {
            final ProviderKey key = getGetProviderKey(auth, userId);
            synchronized (key) {
                key.mHolder = holder;
                key.notifyAll();
            }
        }
    }

    private @NonNull SafeCancellationTransport createSafeCancellationTransport(
@@ -6796,13 +6811,40 @@ public final class ActivityThread extends ClientTransactionHandler {
        // 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.
        ContentProviderHolder holder = null;
        final ProviderKey key = getGetProviderKey(auth, userId);
        synchronized (key) {
            boolean wasWaiting = false;
            try {
            synchronized (getGetProviderLock(auth, userId)) {
                if (key.mWaiters == 0) {
                    // No other thread is waiting for this provider, let's fetch one by ourselves.
                    // If the returned holder is non-null but its provider is null and it's not
                    // local, we'll need to wait for the publishing of the provider.
                    holder = ActivityManager.getService().getContentProvider(
                            getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
                }
                if ((holder != null && holder.provider == null && !holder.mLocal)
                        || (key.mWaiters > 0 && (holder = key.mHolder) == null)) {
                    try {
                        key.mWaiters++;
                        wasWaiting = true;
                        key.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
                        holder = key.mHolder;
                        if (holder != null && holder.provider == null) {
                            // probably timed out
                            holder = null;
                        }
                    } catch (InterruptedException e) {
                        holder = null;
                    }
                }
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            } finally {
                if (wasWaiting && --key.mWaiters == 0) {
                    // Clear the holder from the key since the key itself is never cleared.
                    key.mHolder = null;
                }
            }
        }
        if (holder == null) {
            if (UserManager.get(c).isUserUnlocked(userId)) {
@@ -6820,13 +6862,13 @@ public final class ActivityThread extends ClientTransactionHandler {
        return holder.provider;
    }

    private Object getGetProviderLock(String auth, int userId) {
        final ProviderKey key = new ProviderKey(auth, userId);
        synchronized (mGetProviderLocks) {
            Object lock = mGetProviderLocks.get(key);
    private ProviderKey getGetProviderKey(String auth, int userId) {
        final int key = ProviderKey.hashCode(auth, userId);
        synchronized (mGetProviderKeys) {
            ProviderKey lock = mGetProviderKeys.get(key);
            if (lock == null) {
                lock = key;
                mGetProviderLocks.put(key, lock);
                lock = new ProviderKey(auth, userId);
                mGetProviderKeys.put(key, lock);
            }
            return lock;
        }
+8 −1
Original line number Diff line number Diff line
@@ -39,6 +39,11 @@ public class ContentProviderHolder implements Parcelable {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public boolean noReleaseNeeded;

    /**
     * Whether the provider here is a local provider or not.
     */
    public boolean mLocal;

    @UnsupportedAppUsage
    public ContentProviderHolder(ProviderInfo _info) {
        info = _info;
@@ -59,6 +64,7 @@ public class ContentProviderHolder implements Parcelable {
        }
        dest.writeStrongBinder(connection);
        dest.writeInt(noReleaseNeeded ? 1 : 0);
        dest.writeInt(mLocal ? 1 : 0);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ContentProviderHolder> CREATOR
@@ -81,5 +87,6 @@ public class ContentProviderHolder implements Parcelable {
                source.readStrongBinder());
        connection = source.readStrongBinder();
        noReleaseNeeded = source.readInt() != 0;
        mLocal = source.readInt() != 0;
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app;

import android.app.ContentProviderHolder;
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
@@ -147,4 +148,6 @@ oneway interface IApplicationThread {
    void performDirectAction(IBinder activityToken, String actionId,
            in Bundle arguments, in RemoteCallback cancellationCallback,
            in RemoteCallback resultCallback);
    void notifyContentProviderPublishStatus(in ContentProviderHolder holder, String auth,
            int userId, boolean published);
}
+6 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.app.servertransaction.TestUtils.resultInfoList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.app.ContentProviderHolder;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
@@ -664,5 +665,10 @@ public class TransactionParcelTests {
        public void performDirectAction(IBinder activityToken, String actionId, Bundle arguments,
                RemoteCallback cancellationCallback, RemoteCallback resultCallback) {
        }

        @Override
        public void notifyContentProviderPublishStatus(ContentProviderHolder holder, String auth,
                int userId, boolean published) {
        }
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -1579,6 +1579,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
    static final int KILL_APP_ZYGOTE_MSG = 71;
    static final int BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG = 72;
    static final int WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG = 73;
    static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1915,6 +1916,11 @@ public class ActivityManagerService extends IActivityManager.Stub
                case BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG: {
                    handleBinderHeavyHitterAutoSamplerTimeOut();
                } break;
                case WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG: {
                    synchronized (ActivityManagerService.this) {
                        ((ContentProviderRecord) msg.obj).onProviderPublishStatusLocked(false);
                    }
                } break;
            }
        }
    }
Loading