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
This commit is contained in:
Koji Fukui
2017-10-18 17:48:40 +09:00
committed by Felipe Leme
parent bbaa19cad3
commit ccec6a6ae8
5 changed files with 52 additions and 1 deletions

View File

@@ -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;

View File

@@ -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;
}
}
}
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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");