1 /* 2 * Copyright (C) 2019 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 #pragma once 17 18 #include <ui/Rect.h> 19 #include <utils/String8.h> 20 #include "TransactionUtils.h" 21 22 namespace android { 23 24 namespace { 25 26 // A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check 27 // individual pixel values for testing purposes. 28 class ScreenCapture : public RefBase { 29 public: captureScreen(std::unique_ptr<ScreenCapture> * sc)30 static void captureScreen(std::unique_ptr<ScreenCapture>* sc) { 31 captureScreen(sc, SurfaceComposerClient::getInternalDisplayToken()); 32 } 33 captureScreen(std::unique_ptr<ScreenCapture> * sc,sp<IBinder> displayToken)34 static void captureScreen(std::unique_ptr<ScreenCapture>* sc, sp<IBinder> displayToken) { 35 const auto sf = ComposerService::getComposerService(); 36 SurfaceComposerClient::Transaction().apply(true); 37 38 sp<GraphicBuffer> outBuffer; 39 ASSERT_EQ(NO_ERROR, sf->captureScreen(displayToken, &outBuffer, Rect(), 0, 0, false)); 40 *sc = std::make_unique<ScreenCapture>(outBuffer); 41 } 42 43 static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle, 44 Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { 45 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); 46 SurfaceComposerClient::Transaction().apply(true); 47 48 sp<GraphicBuffer> outBuffer; 49 ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale)); 50 *sc = std::make_unique<ScreenCapture>(outBuffer); 51 } 52 53 static void captureChildLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle, 54 Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { 55 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); 56 SurfaceComposerClient::Transaction().apply(true); 57 58 sp<GraphicBuffer> outBuffer; 59 ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale, true)); 60 *sc = std::make_unique<ScreenCapture>(outBuffer); 61 } 62 captureChildLayersExcluding(std::unique_ptr<ScreenCapture> * sc,sp<IBinder> & parentHandle,std::unordered_set<sp<IBinder>,ISurfaceComposer::SpHash<IBinder>> excludeLayers)63 static void captureChildLayersExcluding( 64 std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle, 65 std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> excludeLayers) { 66 sp<ISurfaceComposer> sf(ComposerService::getComposerService()); 67 SurfaceComposerClient::Transaction().apply(true); 68 69 sp<GraphicBuffer> outBuffer; 70 ASSERT_EQ(NO_ERROR, 71 sf->captureLayers(parentHandle, &outBuffer, ui::Dataspace::V0_SRGB, 72 ui::PixelFormat::RGBA_8888, Rect::EMPTY_RECT, excludeLayers, 73 1.0f, true)); 74 *sc = std::make_unique<ScreenCapture>(outBuffer); 75 } 76 77 void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) { 78 ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); 79 TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance); 80 } 81 82 void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) { 83 ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); 84 const bool leftBorder = rect.left > 0; 85 const bool topBorder = rect.top > 0; 86 const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth()); 87 const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight()); 88 89 if (topBorder) { 90 Rect top(rect.left, rect.top - 1, rect.right, rect.top); 91 if (leftBorder) { 92 top.left -= 1; 93 } 94 if (rightBorder) { 95 top.right += 1; 96 } 97 expectColor(top, color, tolerance); 98 } 99 if (leftBorder) { 100 Rect left(rect.left - 1, rect.top, rect.left, rect.bottom); 101 expectColor(left, color, tolerance); 102 } 103 if (rightBorder) { 104 Rect right(rect.right, rect.top, rect.right + 1, rect.bottom); 105 expectColor(right, color, tolerance); 106 } 107 if (bottomBorder) { 108 Rect bottom(rect.left, rect.bottom, rect.right, rect.bottom + 1); 109 if (leftBorder) { 110 bottom.left -= 1; 111 } 112 if (rightBorder) { 113 bottom.right += 1; 114 } 115 expectColor(bottom, color, tolerance); 116 } 117 } 118 119 void expectQuadrant(const Rect& rect, const Color& topLeft, const Color& topRight, 120 const Color& bottomLeft, const Color& bottomRight, bool filtered = false, 121 uint8_t tolerance = 0) { 122 ASSERT_TRUE((rect.right - rect.left) % 2 == 0 && (rect.bottom - rect.top) % 2 == 0); 123 124 const int32_t centerX = rect.left + (rect.right - rect.left) / 2; 125 const int32_t centerY = rect.top + (rect.bottom - rect.top) / 2; 126 // avoid checking borders due to unspecified filtering behavior 127 const int32_t offsetX = filtered ? 2 : 0; 128 const int32_t offsetY = filtered ? 2 : 0; 129 expectColor(Rect(rect.left, rect.top, centerX - offsetX, centerY - offsetY), topLeft, 130 tolerance); 131 expectColor(Rect(centerX + offsetX, rect.top, rect.right, centerY - offsetY), topRight, 132 tolerance); 133 expectColor(Rect(rect.left, centerY + offsetY, centerX - offsetX, rect.bottom), bottomLeft, 134 tolerance); 135 expectColor(Rect(centerX + offsetX, centerY + offsetY, rect.right, rect.bottom), 136 bottomRight, tolerance); 137 } 138 checkPixel(uint32_t x,uint32_t y,uint8_t r,uint8_t g,uint8_t b)139 void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { 140 ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat()); 141 const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x)); 142 if (r != pixel[0] || g != pixel[1] || b != pixel[2]) { 143 String8 err(String8::format("pixel @ (%3d, %3d): " 144 "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]", 145 x, y, r, g, b, pixel[0], pixel[1], pixel[2])); 146 EXPECT_EQ(String8(), err) << err.string(); 147 } 148 } 149 expectFGColor(uint32_t x,uint32_t y)150 void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); } 151 expectBGColor(uint32_t x,uint32_t y)152 void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); } 153 expectChildColor(uint32_t x,uint32_t y)154 void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); } 155 ScreenCapture(const sp<GraphicBuffer> & outBuffer)156 explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) { 157 mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels)); 158 } 159 ~ScreenCapture()160 ~ScreenCapture() { mOutBuffer->unlock(); } 161 162 private: 163 sp<GraphicBuffer> mOutBuffer; 164 uint8_t* mPixels = nullptr; 165 }; 166 } // namespace 167 } // namespace android 168