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

Commit ccec6a6a authored by Koji Fukui's avatar Koji Fukui Committed by Felipe Leme
Browse files

Remove AutofillManagerClient after AutofillManager is finalized

Symptom:
Global reference table overflow happens on system_server.

Root cause:
If a process repeatedly create a context and get AutofillManager
from the context, each BinderProxy of AutofillManagerClient are
registered to AutofillManagerServiceImpl. They aren't removed until
the process is died. BinderProxy consumes global reference and finally
causes crash on system_server.

Solution:
Remove AutofillManagerClient from AutofillManagerServiceImpl after
AutofillManager is finalized.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAutoFillServiceTestCases

Bug: 68747744
Change-Id: I8b76c5368b54317b8696cac470cc390b36e910e7
parent bbaa19ca
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.os;
import android.util.ArrayMap;
import android.util.Slog;

import java.io.PrintWriter;
import java.util.function.Consumer;

/**
@@ -399,6 +400,13 @@ public class RemoteCallbackList<E extends IInterface> {
        }
    }

    /** @hide */
    public void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("callbacks: "); pw.println(mCallbacks.size());
        pw.print(prefix); pw.print("killed: "); pw.println(mKilled);
        pw.print(prefix); pw.print("broadcasts count: "); pw.println(mBroadcastCount);
    }

    private void logExcessiveCallbacks() {
        final long size = mCallbacks.size();
        final long TOO_MANY = 3000;
+20 −1
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

// TODO: use java.lang.ref.Cleaner once Android supports Java 9
import sun.misc.Cleaner;

/**
 * The {@link AutofillManager} provides ways for apps and custom views to integrate with the
 * Autofill Framework lifecycle.
@@ -224,6 +227,9 @@ public final class AutofillManager {
    @GuardedBy("mLock")
    private IAutoFillManagerClient mServiceClient;

    @GuardedBy("mLock")
    private Cleaner mServiceClientCleaner;

    @GuardedBy("mLock")
    private AutofillCallback mCallback;

@@ -958,10 +964,19 @@ public final class AutofillManager {
        if (mServiceClient == null) {
            mServiceClient = new AutofillManagerClient(this);
            try {
                final int flags = mService.addClient(mServiceClient, mContext.getUserId());
                final int userId = mContext.getUserId();
                final int flags = mService.addClient(mServiceClient, userId);
                mEnabled = (flags & FLAG_ADD_CLIENT_ENABLED) != 0;
                sDebug = (flags & FLAG_ADD_CLIENT_DEBUG) != 0;
                sVerbose = (flags & FLAG_ADD_CLIENT_VERBOSE) != 0;
                final IAutoFillManager service = mService;
                final IAutoFillManagerClient serviceClient = mServiceClient;
                mServiceClientCleaner = Cleaner.create(this, () -> {
                    try {
                        service.removeClient(serviceClient, userId);
                    } catch (RemoteException e) {
                    }
                });
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -1068,6 +1083,10 @@ public final class AutofillManager {
            if (resetClient) {
                // Reset connection to system
                mServiceClient = null;
                if (mServiceClientCleaner != null) {
                    mServiceClientCleaner.clean();
                    mServiceClientCleaner = null;
                }
            }
        }
    }
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.autofill.IAutoFillManagerClient;
interface IAutoFillManager {
    // Returns flags: FLAG_ADD_CLIENT_ENABLED | FLAG_ADD_CLIENT_DEBUG | FLAG_ADD_CLIENT_VERBOSE
    int addClient(in IAutoFillManagerClient client, int userId);
    void removeClient(in IAutoFillManagerClient client, int userId);
    int startSession(IBinder activityToken, in IBinder appCallback, in AutofillId autoFillId,
            in Rect bounds, in AutofillValue value, int userId, boolean hasCallback, int flags,
            String packageName);
+10 −0
Original line number Diff line number Diff line
@@ -498,6 +498,16 @@ public final class AutofillManagerService extends SystemService {
            }
        }

        @Override
        public void removeClient(IAutoFillManagerClient client, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.removeClientLocked(client);
                }
            }
        }

        @Override
        public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId,
                int userId) {
+13 −0
Original line number Diff line number Diff line
@@ -261,6 +261,12 @@ final class AutofillManagerServiceImpl {
        return isEnabled();
    }

    void removeClientLocked(IAutoFillManagerClient client) {
        if (mClients != null) {
            mClients.unregister(client);
        }
    }

    void setAuthenticationResultLocked(Bundle data, int sessionId, int authenticationId, int uid) {
        if (!isEnabled()) {
            return;
@@ -478,6 +484,10 @@ final class AutofillManagerServiceImpl {
        }

        sendStateToClients(true);
        if (mClients != null) {
            mClients.kill();
            mClients = null;
        }
    }

    CharSequence getServiceLabel() {
@@ -605,6 +615,9 @@ final class AutofillManagerServiceImpl {
            }
        }

        pw.print(prefix); pw.println("Clients");
        mClients.dump(pw, prefix2);

        if (mEventHistory == null || mEventHistory.getEvents() == null
                || mEventHistory.getEvents().size() == 0) {
            pw.print(prefix); pw.println("No event on last fill response");