Add async mode tests for BLAST

Add some tests to validate dequeue blocking behavior when the IGBP
is configured in async mode. We want to validate that in this mode,
with or without blast, the client will not be blocked when dequeuing
a buffer. Instead, when the client tries to queue a buffer, the
bufferqueue will drop the queued buffer if it exists.

In async mode, the bufferqueue in the will have an additional buffer
so for blast: one buffer will be acquired and presented, one buffer
will be acquired in the queue, and the client will have two buffers
left for non blocking dequeue. When queuing a buffer, the BQ in the
adapter will drop the last queued buffer if available.

Test: atest BufferPresentationTests
Bug: 176916466

Change-Id: I6ff45c24d6529cc7cd4169f962eb2ca9cbc09943
This commit is contained in:
Vishnu Nair 2021-03-09 16:16:38 -08:00
parent cebc566145
commit 3afbfad181
3 changed files with 109 additions and 1 deletions

View File

@ -130,6 +130,9 @@ JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceDequeueBuffer(J
return result;
}
sBuffers[slot] = anb;
if (timeoutMs == 0) {
return android::OK;
}
android::sp<android::Fence> fence(new android::Fence(fenceFd));
int waitResult = fence->wait(timeoutMs);
if (waitResult != android::OK) {
@ -197,6 +200,28 @@ JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceQueueBuffer(JNI
return result;
}
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceSetAsyncMode(JNIEnv* /* env */,
jclass /* clazz */,
jboolean async) {
assert(sAnw);
android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
return surface->setAsyncMode(async);
}
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceSetDequeueTimeout(
JNIEnv* /* env */, jclass /* clazz */, jlong timeoutMs) {
assert(sAnw);
android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
return surface->setDequeueTimeout(timeoutMs);
}
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_SurfaceSetMaxDequeuedBufferCount(
JNIEnv* /* env */, jclass /* clazz */, jint maxDequeuedBuffers) {
assert(sAnw);
android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
return surface->setMaxDequeuedBufferCount(maxDequeuedBuffers);
}
JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_NativeWindowSetBufferCount(
JNIEnv* /* env */, jclass /* clazz */, jint count) {
assert(sAnw);

View File

@ -17,6 +17,7 @@ package com.android.test
import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@ -93,4 +94,80 @@ class BufferPresentationTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase
assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
}
@Test
// Leave IGBP in sync mode, try to dequeue and queue as fast as possible. Check that we
// occasionally get timeout errors.
fun testSyncMode_dequeueWithoutBlockingFails() {
val numFrames = 1000L
runOnUiThread { activity ->
assertEquals(0, activity.mSurfaceProxy.SurfaceSetDequeueTimeout(3L))
var failures = false
for (i in 1..numFrames) {
if (activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 0 /* ms */) != 0) {
failures = true
break
}
activity.mSurfaceProxy.SurfaceQueueBuffer(0)
}
assertTrue(failures)
}
}
@Test
// Set IGBP to be in async mode, try to dequeue and queue as fast as possible. Client should be
// able to dequeue and queue buffers without being blocked.
fun testAsyncMode_dequeueWithoutBlocking() {
val numFrames = 1000L
runOnUiThread { activity ->
assertEquals(0, activity.mSurfaceProxy.SurfaceSetDequeueTimeout(3L))
assertEquals(0, activity.mSurfaceProxy.SurfaceSetAsyncMode(async = true))
for (i in 1..numFrames) {
assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 0 /* ms */))
activity.mSurfaceProxy.SurfaceQueueBuffer(0)
}
}
}
@Test
// Disable triple buffering in the system and leave IGBP in sync mode. Check that we
// occasionally get timeout errors.
fun testSyncModeWithDisabledTripleBuffering_dequeueWithoutBlockingFails() {
val numFrames = 1000L
runOnUiThread { activity ->
assertEquals(0, activity.mSurfaceProxy.SurfaceSetMaxDequeuedBufferCount(1))
assertEquals(0, activity.mSurfaceProxy.SurfaceSetDequeueTimeout(3L))
var failures = false
for (i in 1..numFrames) {
if (activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 0 /* ms */) != 0) {
failures = true
break
}
activity.mSurfaceProxy.SurfaceQueueBuffer(0)
}
assertTrue(failures)
}
}
@Test
// Disable triple buffering in the system and set IGBP to be in async mode. Try to dequeue and
// queue as fast as possible. Without triple buffering, the client does not have an extra buffer
// to dequeue and will not be able to dequeue and queue buffers without being blocked.
fun testAsyncModeWithDisabledTripleBuffering_dequeueWithoutBlockingFails() {
val numFrames = 1000L
runOnUiThread { activity ->
assertEquals(0, activity.mSurfaceProxy.SurfaceSetMaxDequeuedBufferCount(1))
assertEquals(0, activity.mSurfaceProxy.SurfaceSetDequeueTimeout(3L))
assertEquals(0, activity.mSurfaceProxy.SurfaceSetAsyncMode(async = true))
var failures = false
for (i in 1..numFrames) {
if (activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 0 /* ms */) != 0) {
failures = true
break
}
activity.mSurfaceProxy.SurfaceQueueBuffer(0)
}
assertTrue(failures)
}
}
}

View File

@ -54,7 +54,13 @@ class SurfaceProxy {
external fun SurfaceSetScalingMode(scalingMode: Int)
external fun SurfaceDequeueBuffer(slot: Int, timeoutMs: Int): Int
external fun SurfaceCancelBuffer(slot: Int)
external fun SurfaceQueueBuffer(slot: Int, freeSlot: Boolean = true)
external fun SurfaceQueueBuffer(slot: Int, freeSlot: Boolean = true): Int
external fun SurfaceSetAsyncMode(async: Boolean): Int
external fun SurfaceSetDequeueTimeout(timeout: Long): Int
external fun SurfaceQuery(what: Int): Int
external fun SurfaceSetMaxDequeuedBufferCount(maxDequeuedBuffers: Int): Int
// system/native_window.h functions
external fun NativeWindowSetBufferCount(count: Int): Int
external fun NativeWindowSetSharedBufferMode(shared: Boolean): Int
external fun NativeWindowSetAutoRefresh(autoRefresh: Boolean): Int