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

Commit 41e3d35e authored by Yu-Ting Tseng's avatar Yu-Ting Tseng Committed by Android (Google) Code Review
Browse files

Merge "Use WeakReference in RemoteFillService." into main

parents b4d3b80e 99844534
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -34,3 +34,10 @@ flag {
  description: "Mitigation for autofill providers miscalculating view visibility"
  bug: "291795358"
}

flag {
  name: "remote_fill_service_use_weak_reference"
  namespace: "autofill"
  description: "Use weak reference to address binder leak problem"
  bug: "307972253"
}
+137 −48
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.autofill;

import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.service.autofill.Flags.remoteFillServiceUseWeakReference;

import static com.android.server.autofill.Helper.sVerbose;

@@ -44,6 +45,7 @@ import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.infra.ServiceConnector;
import com.android.internal.os.IResultReceiver;

import java.lang.ref.WeakReference;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -65,6 +67,8 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
    private final Object mLock = new Object();
    private CompletableFuture<FillResponse> mPendingFillRequest;
    private int mPendingFillRequestId = INVALID_REQUEST_ID;
    private AtomicReference<IFillCallback> mFillCallback;
    private AtomicReference<ISaveCallback> mSaveCallback;
    private final ComponentName mComponentName;

    private final boolean mIsCredentialAutofillService;
@@ -150,6 +154,89 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
        }
    }

    static class IFillCallbackDelegate extends IFillCallback.Stub {
        private WeakReference<IFillCallback> mCallbackWeakRef;

        IFillCallbackDelegate(IFillCallback callback) {
            mCallbackWeakRef = new WeakReference(callback);
        }

        @Override
        public void onCancellable(ICancellationSignal cancellation) throws RemoteException {
            IFillCallback callback = mCallbackWeakRef.get();
            if (callback != null) {
                callback.onCancellable(cancellation);
            }
        }

        @Override
        public void onSuccess(FillResponse response) throws RemoteException {
            IFillCallback callback = mCallbackWeakRef.get();
            if (callback != null) {
                callback.onSuccess(response);
            }
        }

        @Override
        public void onFailure(int requestId, CharSequence message) throws RemoteException {
            IFillCallback callback = mCallbackWeakRef.get();
            if (callback != null) {
                callback.onFailure(requestId, message);
            }
        }
    }

    static class ISaveCallbackDelegate extends ISaveCallback.Stub {

        private WeakReference<ISaveCallback> mCallbackWeakRef;

        ISaveCallbackDelegate(ISaveCallback callback) {
            mCallbackWeakRef = new WeakReference(callback);
        }

        @Override
        public void onSuccess(IntentSender intentSender) throws RemoteException {
            ISaveCallback callback = mCallbackWeakRef.get();
            if (callback != null) {
                callback.onSuccess(intentSender);
            }
        }

        @Override
        public void onFailure(CharSequence message) throws RemoteException {
            ISaveCallback callback = mCallbackWeakRef.get();
            if (callback != null) {
                callback.onFailure(message);
            }
        }
    }

    /**
     * Wraps an {@link IFillCallback} object using weak reference.
     *
     * This prevents lingering allocation issue by breaking the chain of strong references from
     * Binder to {@link callback}. Since {@link callback} is not held by Binder anymore, it needs
     * to be held by {@link mFillCallback} so it's not deallocated prematurely.
     */
    private IFillCallback maybeWrapWithWeakReference(IFillCallback callback) {
        if (remoteFillServiceUseWeakReference()) {
            mFillCallback = new AtomicReference<>(callback);
            return new IFillCallbackDelegate(callback);
        }
        return callback;
    }

    /**
     * Wraps an {@link ISaveCallback} object using weak reference.
     */
    private ISaveCallback maybeWrapWithWeakReference(ISaveCallback callback) {
        if (remoteFillServiceUseWeakReference()) {
            mSaveCallback = new AtomicReference<>(callback);
            return new ISaveCallbackDelegate(callback);
        }
        return callback;
    }

    public void onFillCredentialRequest(@NonNull FillRequest request,
            IAutoFillManagerClient autofillCallback) {
        if (sVerbose) {
@@ -164,7 +251,8 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
            }

            CompletableFuture<FillResponse> fillRequest = new CompletableFuture<>();
            remoteService.onFillCredentialRequest(request, new IFillCallback.Stub() {
            remoteService.onFillCredentialRequest(
                    request, maybeWrapWithWeakReference(new IFillCallback.Stub() {
                        @Override
                        public void onCancellable(ICancellationSignal cancellation) {
                            CompletableFuture<FillResponse> future = futureRef.get();
@@ -186,7 +274,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
                            fillRequest.completeExceptionally(
                                    new RuntimeException(errorMessage));
                        }
            }, autofillCallback);
                    }), autofillCallback);
            return fillRequest;
        }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
        futureRef.set(connectThenFillRequest);
@@ -235,7 +323,8 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
            }

            CompletableFuture<FillResponse> fillRequest = new CompletableFuture<>();
            remoteService.onFillRequest(request, new IFillCallback.Stub() {
            remoteService.onFillRequest(
                    request, maybeWrapWithWeakReference(new IFillCallback.Stub() {
                        @Override
                        public void onCancellable(ICancellationSignal cancellation) {
                            CompletableFuture<FillResponse> future = futureRef.get();
@@ -257,7 +346,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
                            fillRequest.completeExceptionally(
                                    new RuntimeException(errorMessage));
                        }
            });
                    }));
            return fillRequest;
        }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
        futureRef.set(connectThenFillRequest);
@@ -294,7 +383,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
            if (sVerbose) Slog.v(TAG, "calling onSaveRequest()");

            CompletableFuture<IntentSender> save = new CompletableFuture<>();
            service.onSaveRequest(request, new ISaveCallback.Stub() {
            service.onSaveRequest(request, maybeWrapWithWeakReference(new ISaveCallback.Stub() {
                @Override
                public void onSuccess(IntentSender intentSender) {
                    save.complete(intentSender);
@@ -304,7 +393,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
                public void onFailure(CharSequence message) {
                    save.completeExceptionally(new RuntimeException(String.valueOf(message)));
                }
            });
            }));
            return save;
        }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS)
                .whenComplete((res, err) -> Handler.getMain().post(() -> {