| Kalle Raita | a099a24 | 2017-01-11 11:17:29 -0800 | [diff] [blame] | 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 |