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 android.tools.traces.surfaceflinger.LayersTrace 25 import android.tools.traces.monitors.withSFTracing 26 import android.tools.traces.monitors.PerfettoTraceMonitor 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 import perfetto.protos.PerfettoConfig.SurfaceFlingerLayersConfig 35 36 open class SurfaceTracingTestBase(useBlastAdapter: Boolean) : 37 SurfaceViewBufferTestBase(useBlastAdapter) { 38 @get:Rule 39 var scenarioRule: ActivityScenarioRule<MainActivity> = 40 ActivityScenarioRule<MainActivity>(MainActivity::class.java) 41 42 @Before 43 override fun setup() { 44 super.setup() 45 PerfettoTraceMonitor.stopAllSessions() 46 addSurfaceView() 47 } 48 49 @After 50 override fun teardown() { 51 super.teardown() 52 scenarioRule.getScenario().close() 53 } 54 55 fun withTrace(predicate: (it: MainActivity) -> Unit): LayersTrace { 56 return withSFTracing(TRACE_FLAGS) { 57 scenarioRule.getScenario().onActivity { 58 predicate(it) 59 } 60 } 61 } 62 63 fun withTrace(predicate: () -> Unit): LayersTrace { 64 return withSFTracing(TRACE_FLAGS) { 65 predicate() 66 } 67 } 68 69 fun runOnUiThread(predicate: (it: MainActivity) -> Unit) { 70 scenarioRule.getScenario().onActivity { 71 predicate(it) 72 } 73 } 74 75 private fun addSurfaceView() { 76 lateinit var surfaceReadyLatch: CountDownLatch 77 scenarioRule.getScenario().onActivity { 78 surfaceReadyLatch = it.addSurfaceView(defaultBufferSize) 79 } 80 surfaceReadyLatch.await() 81 // sleep to finish animations 82 instrumentation.waitForIdleSync() 83 } 84 85 fun checkPixels(bounds: Rect, @ColorInt color: Int) { 86 val screenshot = instrumentation.getUiAutomation().takeScreenshot() 87 val pixels = IntArray(screenshot.width * screenshot.height) 88 screenshot.getPixels(pixels, 0, screenshot.width, 0, 0, screenshot.width, screenshot.height) 89 for (i in bounds.left + 10..bounds.right - 10) { 90 for (j in bounds.top + 10..bounds.bottom - 10) { 91 val actualColor = pixels[j * screenshot.width + i] 92 if (actualColor != color) { 93 val screenshotPath = instrumentation.targetContext 94 .getExternalFilesDir(null)?.resolve("screenshot.png") 95 try { 96 FileOutputStream(screenshotPath).use { out -> 97 screenshot.compress(Bitmap.CompressFormat.PNG, 100, out) 98 } 99 Log.e("SurfaceViewBufferTests", "Bitmap written to $screenshotPath") 100 } catch (e: IOException) { 101 Log.e("SurfaceViewBufferTests", "Error writing bitmap to file", e) 102 } 103 } 104 Assert.assertEquals( 105 "Checking $bounds found mismatch $i,$j", 106 Color.valueOf(color), 107 Color.valueOf(actualColor) 108 ) 109 } 110 } 111 } 112 113 private companion object { 114 private val TRACE_FLAGS = listOf( 115 SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_BUFFERS, 116 SurfaceFlingerLayersConfig.TraceFlag.TRACE_FLAG_VIRTUAL_DISPLAYS, 117 ) 118 } 119 }