1 /* 2 * Copyright 2017 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 17 #define LOG_NDEBUG 0 18 #undef LOG_TAG 19 #define LOG_TAG "FakeHwcUtil" 20 #include <log/log.h> 21 22 #include "FakeComposerUtils.h" 23 #include "RenderState.h" 24 25 #include "SurfaceFlinger.h" // Get the name of the service... 26 27 #include <binder/IServiceManager.h> 28 29 #include <cutils/properties.h> 30 31 #include <iomanip> 32 #include <thread> 33 34 using android::String16; 35 using android::sp; 36 using namespace std::chrono_literals; 37 using namespace sftest; 38 using std::setw; 39 40 namespace sftest { 41 42 // clang-format off 43 inline void printSourceRectAligned(::std::ostream& os, const hwc_frect_t& sourceRect, int align) { 44 os << std::fixed << std::setprecision(1) << "(" 45 << setw(align) << sourceRect.left << setw(0) << "," 46 << setw(align) << sourceRect.top << setw(0) << "," 47 << setw(align) << sourceRect.right << setw(0) << "," 48 << setw(align) << sourceRect.bottom << setw(0) << ")"; 49 } 50 51 inline void printDisplayRectAligned(::std::ostream& os, const hwc_rect_t& displayRect, int align) { 52 os << "(" 53 << setw(align) << displayRect.left << setw(0) << "," 54 << setw(align) << displayRect.top << setw(0) << "," 55 << setw(align) << displayRect.right << setw(0) << "," 56 << setw(align) << displayRect.bottom << setw(0) << ")"; 57 } 58 // clang-format on 59 60 inline ::std::ostream& operator<<(::std::ostream& os, const sftest::RenderState& state) { 61 printSourceRectAligned(os, state.mSourceCrop, 7); 62 os << "->"; 63 printDisplayRectAligned(os, state.mDisplayFrame, 5); 64 return os << " Swaps:" << state.mSwapCount << " Alpha:" << std::setprecision(3) 65 << state.mPlaneAlpha << " Xform:" << state.mTransform; 66 } 67 68 // Helper for verifying the parts of the RenderState 69 template <typename T> 70 bool valuesMatch(::testing::AssertionResult& message, const T& ref, const T& val, 71 const char* name) { 72 if (ref != val) { 73 message = message << "Expected " << name << ":" << ref << ", got:" << val << "."; 74 return false; 75 } 76 return true; 77 } 78 79 ::testing::AssertionResult rectsAreSame(const RenderState& ref, const RenderState& val) { 80 // TODO: Message could start as success and be assigned as failure. 81 // Only problem is that utility assumes it to be failure and just adds stuff. Would 82 // need still special case the initial failure in the utility? 83 // TODO: ... or would it be possible to break this back to gtest primitives? 84 ::testing::AssertionResult message = ::testing::AssertionFailure(); 85 bool passes = true; 86 87 // The work here is mostly about providing good log strings for differences 88 passes &= valuesMatch(message, ref.mDisplayFrame, val.mDisplayFrame, "display frame"); 89 passes &= valuesMatch(message, ref.mPlaneAlpha, val.mPlaneAlpha, "alpha"); 90 passes &= valuesMatch(message, ref.mSwapCount, val.mSwapCount, "swap count"); 91 passes &= valuesMatch(message, ref.mSourceCrop, val.mSourceCrop, "source crop"); 92 // ... add more 93 if (passes) { 94 return ::testing::AssertionSuccess(); 95 } 96 return message; 97 } 98 99 ::testing::AssertionResult framesAreSame(const std::vector<RenderState>& ref, 100 const std::vector<RenderState>& val) { 101 ::testing::AssertionResult message = ::testing::AssertionFailure(); 102 bool passed = true; 103 if (ref.size() != val.size()) { 104 message << "Expected " << ref.size() << " rects, got " << val.size() << "."; 105 passed = false; 106 } 107 for (size_t rectIndex = 0; rectIndex < std::min(ref.size(), val.size()); rectIndex++) { 108 ::testing::AssertionResult rectResult = rectsAreSame(ref[rectIndex], val[rectIndex]); 109 if (rectResult == false) { 110 message << "First different rect at " << rectIndex << ": " << rectResult.message(); 111 passed = false; 112 break; 113 } 114 } 115 116 if (passed) { 117 return ::testing::AssertionSuccess(); 118 } else { 119 message << "\nReference:"; 120 for (auto state = ref.begin(); state != ref.end(); ++state) { 121 message << "\n" << *state; 122 } 123 message << "\nActual:"; 124 for (auto state = val.begin(); state != val.end(); ++state) { 125 message << "\n" << *state; 126 } 127 } 128 return message; 129 } 130 131 void startSurfaceFlinger() { 132 ALOGI("Start SurfaceFlinger"); 133 system("start surfaceflinger"); 134 135 sp<android::IServiceManager> sm(android::defaultServiceManager()); 136 sp<android::IBinder> sf; 137 while (sf == nullptr) { 138 std::this_thread::sleep_for(10ms); 139 sf = sm->checkService(String16(android::SurfaceFlinger::getServiceName())); 140 } 141 ALOGV("SurfaceFlinger running"); 142 } 143 144 void stopSurfaceFlinger() { 145 ALOGI("Stop SurfaceFlinger"); 146 system("stop surfaceflinger"); 147 sp<android::IServiceManager> sm(android::defaultServiceManager()); 148 sp<android::IBinder> sf; 149 while (sf != nullptr) { 150 std::this_thread::sleep_for(10ms); 151 sf = sm->checkService(String16(android::SurfaceFlinger::getServiceName())); 152 } 153 ALOGV("SurfaceFlinger stopped"); 154 } 155 156 //////////////////////////////////////////////// 157 158 void FakeHwcEnvironment::SetUp() { 159 ALOGI("Test env setup"); 160 system("setenforce 0"); 161 system("stop"); 162 property_set("debug.sf.nobootanimation", "1"); 163 { 164 char value[PROPERTY_VALUE_MAX]; 165 property_get("debug.sf.nobootanimation", value, "0"); 166 LOG_FATAL_IF(atoi(value) != 1, "boot skip not set"); 167 } 168 // TODO: Try registering the mock as the default service instead. 169 property_set("debug.sf.hwc_service_name", "mock"); 170 // This allows the SurfaceFlinger to load a HIDL service not listed in manifest files. 171 property_set("debug.sf.treble_testing_override", "true"); 172 } 173 174 void FakeHwcEnvironment::TearDown() { 175 ALOGI("Test env tear down"); 176 system("stop"); 177 // Wait for mock call signaling teardown? 178 property_set("debug.sf.nobootanimation", "0"); 179 property_set("debug.sf.hwc_service_name", "default"); 180 ALOGI("Test env tear down - done"); 181 } 182 183 } // namespace sftest 184