Kill off callback reference as soon as credential is verified

During lockscreen verification, the caller-supplied callback is
strongly-referenced by a binder object passed into system server.
As a result the callback (which can be a heavyweight object like
the activity implementing the callback) cannot be garbage-collected
until the binder object is GC'ed at the system server side, which
the caller have no control over. Mitigate this by cutting the link
between the callback and the binder object as soon as the callback
is invoked.

This helps fixing the issue that we still see password shards
in Settinng's heap, even after credentail verification has long
been completed.

Bug: 144537463
Test: manual
Change-Id: I4dce3237c5e831b2077d5e9bc6f53d2c36064f78
This commit is contained in:
Rubin Xu
2020-06-03 23:10:58 +01:00
parent 83e9ba45a4
commit 83ede34444

View File

@@ -1430,6 +1430,32 @@ public class LockPatternUtils {
== StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
}
private static class WrappedCallback extends ICheckCredentialProgressCallback.Stub {
private Handler mHandler;
private CheckCredentialProgressCallback mCallback;
WrappedCallback(Handler handler, CheckCredentialProgressCallback callback) {
mHandler = handler;
mCallback = callback;
}
@Override
public void onCredentialVerified() throws RemoteException {
if (mHandler == null) {
Log.e(TAG, "Handler is null during callback");
}
// Kill reference immediately to allow early GC at client side independent of
// when system_server decides to lose its reference to the
// ICheckCredentialProgressCallback binder object.
mHandler.post(() -> {
mCallback.onEarlyMatched();
mCallback = null;
});
mHandler = null;
}
}
private ICheckCredentialProgressCallback wrapCallback(
final CheckCredentialProgressCallback callback) {
if (callback == null) {
@@ -1439,13 +1465,7 @@ public class LockPatternUtils {
throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
+ " to use progress callbacks.");
}
return new ICheckCredentialProgressCallback.Stub() {
@Override
public void onCredentialVerified() throws RemoteException {
mHandler.post(callback::onEarlyMatched);
}
};
return new WrappedCallback(mHandler, callback);
}
}