Merge "Eliminate non interested parts of content capture perf test"

This commit is contained in:
Riddle Hsu
2022-12-15 07:07:30 +00:00
committed by Android (Google) Code Review
4 changed files with 94 additions and 25 deletions

View File

@@ -18,6 +18,8 @@
<application>
<uses-library android:name="android.test.runner" />
<activity android:name="android.perftests.utils.PerfTestActivity"
android:exported="true" />
<activity android:name="android.view.contentcapture.CustomTestActivity"
android:exported="true">
</activity>

View File

@@ -22,18 +22,20 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
import android.app.Activity;
import android.app.Application;
import android.app.Instrumentation;
import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.os.UserHandle;
import android.perftests.utils.PerfStatusReporter;
import android.perftests.utils.PerfTestActivity;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.ActivitiesWatcher;
import com.android.compatibility.common.util.ActivitiesWatcher.ActivityWatcher;
@@ -53,18 +55,18 @@ import org.junit.runners.model.Statement;
public abstract class AbstractContentCapturePerfTestCase {
private static final String TAG = AbstractContentCapturePerfTestCase.class.getSimpleName();
private static final long GENERIC_TIMEOUT_MS = 10_000;
protected static final long GENERIC_TIMEOUT_MS = 5_000;
private static int sOriginalStayOnWhilePluggedIn;
private static Context sContext = getInstrumentation().getTargetContext();
protected static final Instrumentation sInstrumentation = getInstrumentation();
protected static final Context sContext = sInstrumentation.getTargetContext();
protected ActivitiesWatcher mActivitiesWatcher;
private MyContentCaptureService.ServiceWatcher mServiceWatcher;
/** A simple activity as the task root to reduce the noise of pause and animation time. */
protected Activity mEntryActivity;
@Rule
public ActivityTestRule<CustomTestActivity> mActivityRule =
new ActivityTestRule<>(CustomTestActivity.class, false, false);
private MyContentCaptureService.ServiceWatcher mServiceWatcher;
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@@ -220,6 +222,17 @@ public abstract class AbstractContentCapturePerfTestCase {
}
}
@Before
public void setUp() {
mEntryActivity = sInstrumentation.startActivitySync(
PerfTestActivity.createLaunchIntent(sInstrumentation.getContext()));
}
@After
public void tearDown() {
mEntryActivity.finishAndRemoveTask();
}
/**
* Sets {@link MyContentCaptureService} as the service for the current user and waits until
* its created, then add the perf test package into allow list.
@@ -247,21 +260,25 @@ public abstract class AbstractContentCapturePerfTestCase {
return launchActivity(R.layout.test_login_activity, 0);
}
/**
* Returns the intent which will launch CustomTestActivity.
*/
protected Intent getLaunchIntent(int layoutId, int numViews) {
final Intent intent = new Intent(sContext, CustomTestActivity.class)
// Use NEW_TASK because the context is not activity. It is still in the same task
// of PerfTestActivity because of the same task affinity. Use NO_ANIMATION because
// this test focuses on launch time instead of animation duration.
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.putExtra(INTENT_EXTRA_LAYOUT_ID, layoutId);
intent.putExtra(INTENT_EXTRA_CUSTOM_VIEWS, numViews);
return intent;
}
/**
* Launch test activity with give layout and parameter
*/
protected CustomTestActivity launchActivity(int layoutId, int numViews) {
final Intent intent = new Intent(sContext, CustomTestActivity.class);
intent.putExtra(INTENT_EXTRA_LAYOUT_ID, layoutId);
intent.putExtra(INTENT_EXTRA_CUSTOM_VIEWS, numViews);
return mActivityRule.launchActivity(intent);
}
protected void finishActivity() {
try {
mActivityRule.finishActivity();
} catch (IllegalStateException e) {
// no op
}
final Intent intent = getLaunchIntent(layoutId, numViews);
return (CustomTestActivity) sInstrumentation.startActivitySync(intent);
}
}

View File

@@ -19,6 +19,10 @@ package android.view.contentcapture;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Looper;
import android.os.RemoteCallback;
import android.view.Choreographer;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -31,6 +35,8 @@ import com.android.perftests.contentcapture.R;
public class CustomTestActivity extends Activity {
public static final String INTENT_EXTRA_LAYOUT_ID = "layout_id";
public static final String INTENT_EXTRA_CUSTOM_VIEWS = "custom_view_number";
static final String INTENT_EXTRA_FINISH_ON_IDLE = "finish";
static final String INTENT_EXTRA_DRAW_CALLBACK = "draw_callback";
public static final int MAX_VIEWS = 500;
private static final int CUSTOM_CONTAINER_LAYOUT_ID = R.layout.test_container_activity;
@@ -47,6 +53,34 @@ public class CustomTestActivity extends Activity {
getIntent().getIntExtra(INTENT_EXTRA_CUSTOM_VIEWS, MAX_VIEWS));
}
}
final RemoteCallback drawCallback = getIntent().getParcelableExtra(
INTENT_EXTRA_DRAW_CALLBACK, RemoteCallback.class);
if (drawCallback != null) {
getWindow().getDecorView().addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
Choreographer.getInstance().postCallback(
Choreographer.CALLBACK_COMMIT,
// Report that the first frame is drawn.
() -> drawCallback.sendResult(null), null /* token */);
}
@Override
public void onViewDetachedFromWindow(View v) {
}
});
}
if (getIntent().getBooleanExtra(INTENT_EXTRA_FINISH_ON_IDLE, false)) {
Looper.myQueue().addIdleHandler(() -> {
// Finish without animation.
finish();
overridePendingTransition(0 /* enterAnim */, 0 /* exitAnim */);
return false;
});
}
}
private void createCustomViews(LinearLayout root, int number) {

View File

@@ -15,9 +15,10 @@
*/
package android.view.contentcapture;
import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.CREATED;
import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.DESTROYED;
import android.content.Intent;
import android.os.RemoteCallback;
import android.perftests.utils.BenchmarkState;
import android.view.View;
@@ -80,17 +81,32 @@ public class LoginTest extends AbstractContentCapturePerfTestCase {
}
private void testActivityLaunchTime(int layoutId, int numViews) throws Throwable {
final Object drawNotifier = new Object();
final Intent intent = getLaunchIntent(layoutId, numViews);
intent.putExtra(CustomTestActivity.INTENT_EXTRA_FINISH_ON_IDLE, true);
intent.putExtra(CustomTestActivity.INTENT_EXTRA_DRAW_CALLBACK,
new RemoteCallback(result -> {
synchronized (drawNotifier) {
drawNotifier.notifyAll();
}
}));
final ActivityWatcher watcher = startWatcher();
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
launchActivity(layoutId, numViews);
mEntryActivity.startActivity(intent);
synchronized (drawNotifier) {
try {
drawNotifier.wait(GENERIC_TIMEOUT_MS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
// Ignore the time to finish the activity
state.pauseTiming();
watcher.waitFor(CREATED);
finishActivity();
watcher.waitFor(DESTROYED);
sInstrumentation.waitForIdleSync();
state.resumeTiming();
}
}
@@ -142,12 +158,12 @@ public class LoginTest extends AbstractContentCapturePerfTestCase {
while (state.keepRunning()) {
// Only count the time of onVisibilityAggregated()
state.pauseTiming();
mActivityRule.runOnUiThread(() -> {
sInstrumentation.runOnMainSync(() -> {
state.resumeTiming();
view.onVisibilityAggregated(false);
state.pauseTiming();
});
mActivityRule.runOnUiThread(() -> {
sInstrumentation.runOnMainSync(() -> {
state.resumeTiming();
view.onVisibilityAggregated(true);
state.pauseTiming();