Uses autofill callback to throttle performance tests.

Currently the Autofill performance tests work fine, but if we change IAutofillManager
to make oneway binder calls, the tests will crash because of the excessive number of
unfinished binder transactions.

We can fix this issue by using the autofill callbacks that are shown when the UI is shown
or hidden.

Test: mmma -j ./frameworks/base/apct-tests/perftests/autofill/ && \
  adb install -r $OUT/data/app/AutofillPerfTests/AutofillPerfTests.apk && \
  adb shell am instrument -w -e class android.view.autofill.LoginTest \
  com.android.perftests.autofill/android.support.test.runner.AndroidJUnitRunner

Bug: 73536867

Change-Id: I216e67ca97cab059851b0873601e82b368a6abea
This commit is contained in:
Felipe Leme
2018-06-14 10:23:31 -07:00
parent 292b08ff87
commit b251b7f091

View File

@@ -69,7 +69,13 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
public void testFocus_noService() throws Throwable {
resetService();
focusTest(false);
mActivityRule.runOnUiThread(() -> {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mUsername.requestFocus();
mPassword.requestFocus();
}
});
}
/**
@@ -81,7 +87,20 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
MyAutofillService.newCannedResponse().reply();
setService();
focusTest(true);
// Must first focus in a field to trigger autofill and wait for service response
// outside the loop
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
MyAutofillService.getLastFillRequest();
// Then focus on password so loop start with focus away from username
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
mActivityRule.runOnUiThread(() -> {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mUsername.requestFocus();
mPassword.requestFocus();
}
});
}
/**
@@ -95,7 +114,45 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
.reply();
setService();
focusTest(true);
// Callback is used to slow down the calls made to the autofill server so the
// app is not crashed due to binder exhaustion. But the time spent waiting for the callbacks
// is not measured here...
MyAutofillCallback callback = new MyAutofillCallback();
mAfm.registerCallback(callback);
// Must first trigger autofill and wait for service response outside the loop
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
MyAutofillService.getLastFillRequest();
callback.expectEvent(mUsername, EVENT_INPUT_SHOWN);
// Then focus on password so loop start with focus away from username
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
callback.expectEvent(mUsername, EVENT_INPUT_HIDDEN);
callback.expectEvent(mPassword, EVENT_INPUT_SHOWN);
// NOTE: we cannot run the whole loop inside the UI thread, because the autofill callback
// is called on it, which would cause a deadlock on expectEvent().
try {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
state.pauseTiming(); // Ignore time spent waiting for callbacks
callback.expectEvent(mPassword, EVENT_INPUT_HIDDEN);
callback.expectEvent(mUsername, EVENT_INPUT_SHOWN);
state.resumeTiming();
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
state.pauseTiming(); // Ignore time spent waiting for callbacks
callback.expectEvent(mUsername, EVENT_INPUT_HIDDEN);
callback.expectEvent(mPassword, EVENT_INPUT_SHOWN);
state.resumeTiming();
}
// Sanity check
callback.assertNoAsyncErrors();
} finally {
mAfm.unregisterCallback(callback);
}
}
/**
@@ -110,23 +167,41 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
.reply();
setService();
focusTest(true);
}
// Callback is used to slow down the calls made to the autofill server so the
// app is not crashed due to binder exhaustion. But the time spent waiting for the callbacks
// is not measured here...
MyAutofillCallback callback = new MyAutofillCallback();
mAfm.registerCallback(callback);
private void focusTest(boolean waitForService) throws Throwable {
// Must first focus in a field to trigger autofill and wait for service response
// outside the loop
// Must first trigger autofill and wait for service response outside the loop
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
if (waitForService) {
MyAutofillService.getLastFillRequest();
}
mActivityRule.runOnUiThread(() -> {
MyAutofillService.getLastFillRequest();
callback.expectEvent(mUsername, EVENT_INPUT_SHOWN);
// Then focus on password so loop start with focus away from username
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
callback.expectEvent(mUsername, EVENT_INPUT_HIDDEN);
// NOTE: we cannot run the whole loop inside the UI thread, because the autofill callback
// is called on it, which would cause a deadlock on expectEvent().
try {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mUsername.requestFocus();
mPassword.requestFocus();
mActivityRule.runOnUiThread(() -> mUsername.requestFocus());
state.pauseTiming(); // Ignore time spent waiting for callbacks
callback.expectEvent(mUsername, EVENT_INPUT_SHOWN);
state.resumeTiming();
mActivityRule.runOnUiThread(() -> mPassword.requestFocus());
state.pauseTiming(); // Ignore time spent waiting for callbacks
callback.expectEvent(mUsername, EVENT_INPUT_HIDDEN);
state.resumeTiming();
}
});
// Sanity check
callback.assertNoAsyncErrors();
} finally {
mAfm.unregisterCallback(callback);
}
}
/**