1 /* <lambda>null2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.test 17 18 import android.annotation.ColorInt 19 import android.graphics.Bitmap 20 import android.graphics.Color 21 import android.graphics.Rect 22 import android.util.Log 23 import androidx.test.ext.junit.rules.ActivityScenarioRule 24 import com.android.server.wm.flicker.monitor.LayersTraceMonitor 25 import com.android.server.wm.flicker.monitor.withSFTracing 26 import com.android.server.wm.traces.common.layers.LayersTrace 27 import junit.framework.Assert 28 import org.junit.After 29 import org.junit.Before 30 import org.junit.Rule 31 import java.io.FileOutputStream 32 import java.io.IOException 33 import java.util.concurrent.CountDownLatch 34 35 open class SurfaceTracingTestBase(useBlastAdapter: Boolean) : 36 SurfaceViewBufferTestBase(useBlastAdapter) { 37 @get:Rule 38 var scenarioRule: ActivityScenarioRule<MainActivity> = 39 ActivityScenarioRule<MainActivity>(MainActivity::class.java) 40 41 @Before 42 override fun setup() { 43 super.setup() 44 stopLayerTrace() 45 addSurfaceView() 46 } 47 48 @After 49 override fun teardown() { 50 super.teardown() 51 scenarioRule.getScenario().close() 52 } 53 54 fun withTrace(predicate: (it: MainActivity) -> Unit): LayersTrace { 55 return withSFTracing(TRACE_FLAGS, 56 outputDir = instrumentation.targetContext.dataDir.toPath()) { 57 scenarioRule.getScenario().onActivity { 58 predicate(it) 59 } 60 } 61 } 62 63 fun withTrace(predicate: () -> Unit): LayersTrace { 64 return withSFTracing(TRACE_FLAGS, 65 outputDir = instrumentation.targetContext.dataDir.toPath()) { 66 predicate() 67 } 68 } 69 70 fun runOnUiThread(predicate: (it: MainActivity) -> Unit) { 71 scenarioRule.getScenario().onActivity { 72 predicate(it) 73 } 74 } 75 76 private fun addSurfaceView() { 77 lateinit var surfaceReadyLatch: CountDownLatch 78 scenarioRule.getScenario().onActivity { 79 surfaceReadyLatch = it.addSurfaceView(defaultBufferSize) 80 } 81 surfaceReadyLatch.await() 82 // sleep to finish animations 83 instrumentation.waitForIdleSync() 84 } 85 86 private fun stopLayerTrace() { 87 val tmpDir = instrumentation.targetContext.dataDir.toPath() 88 LayersTraceMonitor(tmpDir).stop() 89 } 90 91 fun checkPixels(bounds: Rect, @ColorInt color: Int) { 92 val screenshot = instrumentation.getUiAutomation().takeScreenshot() 93 val pixels = IntArray(screenshot.width * screenshot.height) 94 screenshot.getPixels(pixels, 0, screenshot.width, 0, 0, screenshot.width, screenshot.height) 95 for (i in bounds.left + 10..bounds.right - 10) { 96 for (j in bounds.top + 10..bounds.bottom - 10) { 97 val actualColor = pixels[j * screenshot.width + i] 98 if (actualColor != color) { 99 val screenshotPath = instrumentation.targetContext 100 .getExternalFilesDir(null)?.resolve("screenshot.png") 101 try { 102 FileOutputStream(screenshotPath).use { out -> 103 screenshot.compress(Bitmap.CompressFormat.PNG, 100, out) 104 } 105 Log.e("SurfaceViewBufferTests", "Bitmap written to $screenshotPath") 106 } catch (e: IOException) { 107 Log.e("SurfaceViewBufferTests", "Error writing bitmap to file", e) 108 } 109 } 110 Assert.assertEquals("Checking $bounds found mismatch $i,$j", 111 Color.valueOf(color), Color.valueOf(actualColor)) 112 } 113 } 114 } 115 116 private companion object { 117 private const val TRACE_FLAGS = 118 (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC 119 } 120 }