diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 7a8d1a1caf25fdec28338fb4e508d53b3cfe02fe..f66d12a6959445c947e67248ed050504fb9f5123 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -11,6 +11,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
                libs/input/
                services/core/jni/
                services/incremental/
+               tests/
                tools/
 
 [Hook Scripts]
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
new file mode 100644
index 0000000000000000000000000000000000000000..647da2abd213edf2d02daed89c3e3351c2b42f2e
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "SurfaceViewBufferTests",
+    srcs: ["**/*.java","**/*.kt"],
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTest.xml",
+    platform_apis: true,
+    certificate: "platform",
+    use_embedded_native_libs: true,
+    jni_libs: [
+        "libsurface_jni",
+    ],
+
+    static_libs: [
+        "androidx.appcompat_appcompat",
+        "androidx.test.rules",
+        "androidx.test.runner",
+        "androidx.test.ext.junit",
+        "kotlin-stdlib",
+        "kotlinx-coroutines-android",
+        "flickerlib",
+        "truth-prebuilt",
+    ],
+}
+
+cc_library_shared {
+    name: "libsurface_jni",
+    srcs: [
+        "cpp/SurfaceProxy.cpp",
+    ],
+    shared_libs: [
+        "libutils",
+        "libgui",
+        "liblog",
+        "libandroid",
+    ],
+    include_dirs: [
+        "system/core/include"
+    ],
+    stl: "libc++_static",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+}
diff --git a/tests/SurfaceViewBufferTests/AndroidManifest.xml b/tests/SurfaceViewBufferTests/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..95885c1ca635faf615496be74bf8864a532d9743
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+     package="com.android.test">
+
+    <uses-sdk android:minSdkVersion="29"
+         android:targetSdkVersion="29"/>
+    <!-- Enable / Disable tracing !-->
+    <uses-permission android:name="android.permission.DUMP" />
+    <!-- Enable / Disable sv blast adapter !-->
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+    <application android:allowBackup="false"
+         android:supportsRtl="true">
+        <activity android:name=".MainActivity"
+                  android:taskAffinity="com.android.test.MainActivity"
+                  android:theme="@style/AppTheme"
+                  android:label="SurfaceViewBufferTestApp"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.test"
+                     android:label="SurfaceViewBufferTests">
+    </instrumentation>
+</manifest>
diff --git a/tests/SurfaceViewBufferTests/AndroidTest.xml b/tests/SurfaceViewBufferTests/AndroidTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b73fe4853ecfa7012c9b5e24e2ed77f5ef0075ce
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs SurfaceView Buffer Tests">
+    <option name="test-tag" value="SurfaceViewBufferTests" />
+    <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- keeps the screen on during tests -->
+        <option name="screen-always-on" value="on" />
+        <!-- prevents the phone from restarting -->
+        <option name="force-skip-system-props" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="false"/>
+        <option name="test-file-name" value="SurfaceViewBufferTests.apk"/>
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.test"/>
+        <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" />
+        <option name="shell-timeout" value="6600s" />
+        <option name="test-timeout" value="6000s" />
+        <option name="hidden-api-checks" value="false" />
+    </test>
+</configuration>
diff --git a/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp b/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c86524293e772f7e17dde1ffa312cdadbdab6c6
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/cpp/SurfaceProxy.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/log.h>
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+#include <android/window.h>
+#include <gui/Surface.h>
+#include <jni.h>
+#include <system/window.h>
+#include <utils/RefBase.h>
+#include <cassert>
+#include <chrono>
+#include <thread>
+
+#define TAG "SurfaceViewBufferTests"
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
+
+extern "C" {
+int i = 0;
+static ANativeWindow* sAnw;
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_setSurface(JNIEnv* env, jclass,
+                                                                     jobject surfaceObject) {
+    sAnw = ANativeWindow_fromSurface(env, surfaceObject);
+    assert(sAnw);
+    android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+    surface->enableFrameTimestamps(true);
+    return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_waitUntilBufferDisplayed(
+        JNIEnv*, jclass, jint jFrameNumber, jint timeoutSec) {
+    using namespace std::chrono_literals;
+    assert(sAnw);
+    android::sp<android::Surface> surface = static_cast<android::Surface*>(sAnw);
+
+    uint64_t frameNumber = static_cast<uint64_t>(jFrameNumber);
+    nsecs_t outRequestedPresentTime, outAcquireTime, outLatchTime, outFirstRefreshStartTime;
+    nsecs_t outLastRefreshStartTime, outGlCompositionDoneTime, outDequeueReadyTime;
+    nsecs_t outDisplayPresentTime = -1;
+    nsecs_t outReleaseTime;
+
+    auto start = std::chrono::steady_clock::now();
+    while (outDisplayPresentTime < 0) {
+        std::this_thread::sleep_for(8ms);
+        surface->getFrameTimestamps(frameNumber, &outRequestedPresentTime, &outAcquireTime,
+                                    &outLatchTime, &outFirstRefreshStartTime,
+                                    &outLastRefreshStartTime, &outGlCompositionDoneTime,
+                                    &outDisplayPresentTime, &outDequeueReadyTime, &outReleaseTime);
+        if (outDisplayPresentTime < 0) {
+            auto end = std::chrono::steady_clock::now();
+            if (std::chrono::duration_cast<std::chrono::seconds>(end - start).count() >
+                timeoutSec) {
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_draw(JNIEnv*, jclass) {
+    assert(sAnw);
+    ANativeWindow_Buffer outBuffer;
+    ANativeWindow_lock(sAnw, &outBuffer, nullptr);
+    return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_ANativeWindowLock(JNIEnv*, jclass) {
+    assert(sAnw);
+    ANativeWindow_Buffer outBuffer;
+    ANativeWindow_lock(sAnw, &outBuffer, nullptr);
+    return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_ANativeWindowUnlockAndPost(JNIEnv*,
+                                                                                     jclass) {
+    assert(sAnw);
+    ANativeWindow_unlockAndPost(sAnw);
+    return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_test_SurfaceProxy_ANativeWindowSetBuffersGeometry(
+        JNIEnv* /* env */, jclass /* clazz */, jobject /* surfaceObject */, jint w, jint h,
+        jint format) {
+    assert(sAnw);
+    return ANativeWindow_setBuffersGeometry(sAnw, w, h, format);
+}
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/res/values/styles.xml b/tests/SurfaceViewBufferTests/res/values/styles.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8b50738a06de2b2fda0ec672afebe2b89ad86a4e
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/res/values/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+    <item name="windowNoTitle">true</item>
+    <item name="windowActionBar">false</item>
+    <item name="android:windowFullscreen">true</item>
+    <item name="android:windowContentOverlay">@null</item>
+    <item name="android:windowDisablePreview">true</item>
+</style>
+</resources>
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1e1336c4f6d5740060dbe2bc2e13b6598fa6a1f
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.app.Activity
+import android.content.Context
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.os.Bundle
+import android.view.Gravity
+import android.view.Surface
+import android.view.SurfaceHolder
+import android.view.SurfaceView
+import android.widget.FrameLayout
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.locks.ReentrantLock
+import kotlin.concurrent.withLock
+
+class MainActivity : Activity() {
+    val mSurfaceProxy = SurfaceProxy()
+    private var mSurfaceHolder: SurfaceHolder? = null
+    private val mDrawLock = ReentrantLock()
+
+    val surface: Surface? get() = mSurfaceHolder?.surface
+
+    public override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        addSurfaceView(Rect(0, 0, 500, 200))
+    }
+
+    fun addSurfaceView(size: Rect): CountDownLatch {
+        val layout = findViewById<FrameLayout>(android.R.id.content)
+        val surfaceReadyLatch = CountDownLatch(1)
+        val surfaceView = createSurfaceView(applicationContext, size, surfaceReadyLatch)
+        layout.addView(surfaceView,
+                FrameLayout.LayoutParams(size.width(), size.height(), Gravity.TOP or Gravity.LEFT)
+                        .also { it.setMargins(100, 100, 0, 0) })
+        return surfaceReadyLatch
+    }
+
+    private fun createSurfaceView(
+        context: Context,
+        size: Rect,
+        surfaceReadyLatch: CountDownLatch
+    ): SurfaceView {
+        val surfaceView = SurfaceView(context)
+        surfaceView.setWillNotDraw(false)
+        surfaceView.holder.setFixedSize(size.width(), size.height())
+        surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                mDrawLock.withLock {
+                    mSurfaceHolder = holder
+                    mSurfaceProxy.setSurface(holder.surface)
+                }
+                surfaceReadyLatch.countDown()
+            }
+
+            override fun surfaceChanged(
+                holder: SurfaceHolder,
+                format: Int,
+                width: Int,
+                height: Int
+            ) {
+            }
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                mDrawLock.withLock {
+                    mSurfaceHolder = null
+                }
+            }
+        })
+        return surfaceView
+    }
+
+    fun drawFrame(): Rect {
+        mDrawLock.withLock {
+            val holder = mSurfaceHolder ?: return Rect()
+            val canvas = holder.lockCanvas()
+            val canvasSize = Rect(0, 0, canvas.width, canvas.height)
+            canvas.drawColor(Color.GREEN)
+            val p = Paint()
+            p.color = Color.RED
+            canvas.drawRect(canvasSize, p)
+            holder.unlockCanvasAndPost(canvas)
+            return canvasSize
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..884aae41446cb0bf6c684c463b0a7848e8fab244
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceProxy.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test
+
+class SurfaceProxy {
+    init {
+        System.loadLibrary("surface_jni")
+    }
+
+    external fun setSurface(surface: Any)
+    external fun waitUntilBufferDisplayed(frameNumber: Int, timeoutSec: Int)
+    external fun draw()
+
+    // android/native_window.h functions
+    external fun ANativeWindowLock()
+    external fun ANativeWindowUnlockAndPost()
+    external fun ANativeWindowSetBuffersGeometry(surface: Any, width: Int, height: Int, format: Int)
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b48a91d49b91819d9ac6918f3d59dd5fc61fcb4a
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTest.kt
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test
+
+import android.app.Instrumentation
+import android.graphics.Rect
+import android.provider.Settings
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.wm.flicker.monitor.LayersTraceMonitor
+import com.android.server.wm.flicker.monitor.withSFTracing
+import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import java.util.concurrent.CountDownLatch
+import kotlin.properties.Delegates
+
+@RunWith(Parameterized::class)
+class SurfaceViewBufferTest(val useBlastAdapter: Boolean) {
+    private var mInitialUseBlastConfig by Delegates.notNull<Int>()
+
+    @get:Rule
+    var scenarioRule: ActivityScenarioRule<MainActivity> =
+            ActivityScenarioRule<MainActivity>(MainActivity::class.java)
+
+    protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    val defaultBufferSize = Rect(0, 0, 640, 480)
+
+    @Before
+    fun setup() {
+        mInitialUseBlastConfig = Settings.Global.getInt(instrumentation.context.contentResolver,
+                "use_blast_adapter_sv", 0)
+        val enable = if (useBlastAdapter) 1 else 0
+        Settings.Global.putInt(instrumentation.context.contentResolver, "use_blast_adapter_sv",
+                enable)
+        val tmpDir = instrumentation.targetContext.dataDir.toPath()
+        LayersTraceMonitor(tmpDir).stop()
+
+        lateinit var surfaceReadyLatch: CountDownLatch
+        scenarioRule.getScenario().onActivity {
+            surfaceReadyLatch = it.addSurfaceView(defaultBufferSize)
+        }
+        surfaceReadyLatch.await()
+    }
+
+    @After
+    fun teardown() {
+        scenarioRule.getScenario().close()
+        Settings.Global.putInt(instrumentation.context.contentResolver,
+                "use_blast_adapter_sv", mInitialUseBlastConfig)
+    }
+
+    @Test
+    fun testSetBuffersGeometry_0x0_resetsBufferSize() {
+        val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+            scenarioRule.getScenario().onActivity {
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0,
+                        R8G8B8A8_UNORM)
+                it.mSurfaceProxy.ANativeWindowLock()
+                it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+                it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
+            }
+        }
+
+        // verify buffer size is reset to default buffer size
+        assertThat(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
+    }
+
+    @Test
+    fun testSetBuffersGeometry_0x0_rejectsBuffer() {
+        val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+            scenarioRule.getScenario().onActivity {
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
+                        R8G8B8A8_UNORM)
+                it.mSurfaceProxy.ANativeWindowLock()
+                it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+                it.mSurfaceProxy.ANativeWindowLock()
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0, R8G8B8A8_UNORM)
+                // Submit buffer one with a different size which should be rejected
+                it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+
+                // submit a buffer with the default buffer size
+                it.mSurfaceProxy.ANativeWindowLock()
+                it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+                it.mSurfaceProxy.waitUntilBufferDisplayed(3, 1 /* sec */)
+            }
+        }
+        // Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
+        assertThat(trace).layer("SurfaceView", 2).doesNotExist()
+
+        // Verify the next buffer is submitted with the correct size
+        assertThat(trace).layer("SurfaceView", 3).also {
+            it.hasBufferSize(defaultBufferSize)
+            it.hasScalingMode(0 /* NATIVE_WINDOW_SCALING_MODE_FREEZE */)
+        }
+    }
+
+    @Test
+    fun testSetBuffersGeometry_smallerThanBuffer() {
+        val bufferSize = Rect(0, 0, 300, 200)
+        val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+            scenarioRule.getScenario().onActivity {
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize.width(),
+                        bufferSize.height(), R8G8B8A8_UNORM)
+                it.drawFrame()
+                it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
+            }
+        }
+
+        assertThat(trace).layer("SurfaceView", 1).also {
+            it.hasBufferSize(bufferSize)
+            it.hasLayerSize(defaultBufferSize)
+            it.hasScalingMode(1 /* NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW */)
+        }
+    }
+
+    @Test
+    fun testSetBuffersGeometry_largerThanBuffer() {
+        val bufferSize = Rect(0, 0, 3000, 2000)
+        val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+            scenarioRule.getScenario().onActivity {
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize.width(),
+                        bufferSize.height(), R8G8B8A8_UNORM)
+                it.drawFrame()
+                it.mSurfaceProxy.waitUntilBufferDisplayed(1, 1 /* sec */)
+            }
+        }
+
+        assertThat(trace).layer("SurfaceView", 1).also {
+            it.hasBufferSize(bufferSize)
+            it.hasLayerSize(defaultBufferSize)
+            it.hasScalingMode(1 /* NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW */)
+        }
+    }
+
+    /** Submit buffers as fast as possible and make sure they are queued */
+    @Test
+    fun testQueueBuffers() {
+        val trace = withSFTracing(instrumentation, TRACE_FLAGS) {
+            scenarioRule.getScenario().onActivity {
+                it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
+                        R8G8B8A8_UNORM)
+                for (i in 0..100) {
+                    it.mSurfaceProxy.ANativeWindowLock()
+                    it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+                }
+                it.mSurfaceProxy.waitUntilBufferDisplayed(100, 1 /* sec */)
+            }
+        }
+        for (frameNumber in 1..100) {
+            assertThat(trace).layer("SurfaceView", frameNumber.toLong())
+        }
+    }
+
+    companion object {
+        private const val TRACE_FLAGS = 0x1 // TRACE_CRITICAL
+        private const val R8G8B8A8_UNORM = 1
+
+        @JvmStatic
+        @Parameterized.Parameters(name = "blast={0}")
+        fun data(): Collection<Array<Any>> {
+            return listOf(
+                    arrayOf(false), // First test:  submit buffers via bufferqueue
+                    arrayOf(true)   // Second test: submit buffers via blast adapter
+            )
+        }
+    }
+}
\ No newline at end of file