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

Commit a025037b authored by Song Hu's avatar Song Hu
Browse files

Fix race condition in AbstractMultiplePendingRequestsRemoteService. Make...

Fix race condition in AbstractMultiplePendingRequestsRemoteService. Make mPendingRequests thread safe.

Bug: 159669667
Test: atest com.android.tests.stagedinstallinternal.host.StagedInstallInternalTest
Change-Id: I8f2641e9aa364faddf524e1661422eec079bc2d3
parent 48acf101
Loading
Loading
Loading
Loading
+19 −14
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.util.Slog;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Base class representing a remote service that can queue multiple pending requests while not
@@ -39,7 +40,7 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S

    private final int mInitialCapacity;

    protected ArrayList<BasePendingRequest<S, I>> mPendingRequests;
    protected @NonNull List<BasePendingRequest<S, I>> mPendingRequests;

    public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context,
            @NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
@@ -48,35 +49,36 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S
        super(context, serviceInterface, componentName, userId, callback, handler, bindingFlags,
                verbose);
        mInitialCapacity = initialCapacity;
        mPendingRequests = new ArrayList<>(mInitialCapacity);
    }

    @Override // from AbstractRemoteService
    void handlePendingRequests() {
        if (mPendingRequests != null) {
        synchronized (mPendingRequests) {
            final int size = mPendingRequests.size();
            if (mVerbose) Slog.v(mTag, "Sending " + size + " pending requests");
            for (int i = 0; i < size; i++) {
                mPendingRequests.get(i).run();
            }
            mPendingRequests = null;
            mPendingRequests.clear();
        }
    }

    @Override // from AbstractRemoteService
    protected void handleOnDestroy() {
        if (mPendingRequests != null) {
        synchronized (mPendingRequests) {
            final int size = mPendingRequests.size();
            if (mVerbose) Slog.v(mTag, "Canceling " + size + " pending requests");
            for (int i = 0; i < size; i++) {
                mPendingRequests.get(i).cancel();
            }
            mPendingRequests = null;
            mPendingRequests.clear();
        }
    }

    @Override // from AbstractRemoteService
    final void handleBindFailure() {
        if (mPendingRequests != null) {
        synchronized (mPendingRequests) {
            final int size = mPendingRequests.size();
            if (mVerbose) Slog.v(mTag, "Sending failure to " + size + " pending requests");
            for (int i = 0; i < size; i++) {
@@ -84,7 +86,7 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S
                request.onFailed();
                request.finish();
            }
            mPendingRequests = null;
            mPendingRequests.clear();
        }
    }

@@ -94,18 +96,21 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S

        pw.append(prefix).append("initialCapacity=").append(String.valueOf(mInitialCapacity))
                .println();
        final int size = mPendingRequests == null ? 0 : mPendingRequests.size();
        int size;
        synchronized (mPendingRequests) {
            size = mPendingRequests.size();
        }
        pw.append(prefix).append("pendingRequests=").append(String.valueOf(size)).println();
    }

    @Override // from AbstractRemoteService
    void handlePendingRequestWhileUnBound(@NonNull BasePendingRequest<S, I> pendingRequest) {
        if (mPendingRequests == null) {
            mPendingRequests = new ArrayList<>(mInitialCapacity);
        }
        synchronized (mPendingRequests) {
            mPendingRequests.add(pendingRequest);
            if (mVerbose) {
            Slog.v(mTag, "queued " + mPendingRequests.size() + " requests; last=" + pendingRequest);
                Slog.v(mTag,
                        "queued " + mPendingRequests.size() + " requests; last=" + pendingRequest);
            }
        }
    }
}