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