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 }