blob: 561db8dd0d4c0c3b57fd9a87d45086cbec200bb3 [file] [log] [blame]
Kalle Raitaa099a242017-01-11 11:17:29 -08001/*
2 * Copyright (C) 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 "FakeComposer"
20
21#include "FakeComposerClient.h"
22
23#include <gui/SurfaceComposerClient.h>
24
25#include <log/log.h>
26
27#include <gtest/gtest.h>
28
29#include <inttypes.h>
30#include <time.h>
31#include <algorithm>
32#include <condition_variable>
33#include <iostream>
34#include <mutex>
35#include <set>
36#include <thread>
37
38constexpr Config NULL_DISPLAY_CONFIG = static_cast<Config>(0);
39constexpr Display DEFAULT_DISPLAY = static_cast<Display>(1);
40
41using namespace sftest;
42
43using android::Condition;
44using android::Mutex;
45
46using Clock = std::chrono::steady_clock;
47using TimePoint = std::chrono::time_point<Clock>;
48
49namespace {
50
51// Internal state of a layer in the HWC API.
52class LayerImpl {
53public:
54 LayerImpl() = default;
55
56 bool mValid = true;
57 RenderState mRenderState;
58 uint32_t mZ = 0;
59};
60
61// Struct for storing per frame rectangle state. Contains the render
62// state shared to the test case. Basically a snapshot and a subset of
63// LayerImpl sufficient to re-create the pixels of a layer for the
64// frame.
65struct FrameRect {
66public:
67 FrameRect(Layer layer_, const RenderState& state, uint32_t z_)
68 : layer(layer_), renderState(state), z(z_) {}
69
70 const Layer layer;
71 const RenderState renderState;
72 const uint32_t z;
73};
74
75// Collection of FrameRects forming one rendered frame. Could store
76// related fences and other data in the future.
77class Frame {
78public:
79 Frame() = default;
80 std::vector<std::unique_ptr<FrameRect>> rectangles;
81};
82
83class DelayedEventGenerator {
84public:
85 DelayedEventGenerator(std::function<void()> onTimerExpired)
86 : mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}
87
88 ~DelayedEventGenerator() {
89 ALOGI("DelayedEventGenerator exiting.");
90 {
91 std::unique_lock<std::mutex> lock(mMutex);
92 mRunning = false;
93 mWakeups.clear();
94 mCondition.notify_one();
95 }
96 mThread.join();
97 ALOGI("DelayedEventGenerator exited.");
98 }
99
100 void wakeAfter(std::chrono::nanoseconds waitTime) {
101 std::unique_lock<std::mutex> lock(mMutex);
102 mWakeups.insert(Clock::now() + waitTime);
103 mCondition.notify_one();
104 }
105
106private:
107 void loop() {
108 while (true) {
109 // Lock scope
110 {
111 std::unique_lock<std::mutex> lock(mMutex);
112 mCondition.wait(lock, [this]() { return !mRunning || !mWakeups.empty(); });
113 if (!mRunning && mWakeups.empty()) {
114 // This thread should only exit once the destructor has been called and all
115 // wakeups have been processed
116 return;
117 }
118
119 // At this point, mWakeups will not be empty
120
121 TimePoint target = *(mWakeups.begin());
122 auto status = mCondition.wait_until(lock, target);
123 while (status == std::cv_status::no_timeout) {
124 // This was either a spurious wakeup or another wakeup was added, so grab the
125 // oldest point and wait again
126 target = *(mWakeups.begin());
127 status = mCondition.wait_until(lock, target);
128 }
129
130 // status must have been timeout, so we can finally clear this point
131 mWakeups.erase(target);
132 }
133 // Callback *without* locks!
134 mOnTimerExpired();
135 }
136 }
137
138 std::function<void()> mOnTimerExpired;
139 std::thread mThread;
140 std::mutex mMutex;
141 std::condition_variable mCondition;
142 bool mRunning = true;
143 std::set<TimePoint> mWakeups;
144};
145
146} // namespace
147
148FakeComposerClient::FakeComposerClient()
149 : mCallbacksOn(false),
150 mClient(nullptr),
151 mCurrentConfig(NULL_DISPLAY_CONFIG),
152 mVsyncEnabled(false),
153 mLayers(),
154 mDelayedEventGenerator(
155 std::make_unique<DelayedEventGenerator>([this]() { this->requestVSync(); })),
156 mSurfaceComposer(nullptr) {}
157
158FakeComposerClient::~FakeComposerClient() {}
159
160void FakeComposerClient::removeClient() {
161 ALOGV("removeClient");
162 // TODO: Ahooga! Only thing current lifetime management choices in
163 // APIs make possible. Sad.
164 delete this;
165}
166
167void FakeComposerClient::enableCallback(bool enable) {
168 ALOGV("enableCallback");
169 mCallbacksOn = enable;
170 if (mCallbacksOn) {
171 mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
172 }
173}
174
175void FakeComposerClient::hotplugDisplay(Display display, IComposerCallback::Connection state) {
176 if (mCallbacksOn) {
177 mClient->onHotplug(display, state);
178 }
179}
180
181uint32_t FakeComposerClient::getMaxVirtualDisplayCount() {
182 ALOGV("getMaxVirtualDisplayCount");
183 return 1;
184}
185
186Error FakeComposerClient::createVirtualDisplay(uint32_t /*width*/, uint32_t /*height*/,
187 PixelFormat* /*format*/, Display* /*outDisplay*/) {
188 ALOGV("createVirtualDisplay");
189 return Error::NONE;
190}
191
192Error FakeComposerClient::destroyVirtualDisplay(Display /*display*/) {
193 ALOGV("destroyVirtualDisplay");
194 return Error::NONE;
195}
196
197Error FakeComposerClient::createLayer(Display /*display*/, Layer* outLayer) {
198 ALOGV("createLayer");
199 *outLayer = mLayers.size();
200 auto newLayer = std::make_unique<LayerImpl>();
201 mLayers.push_back(std::move(newLayer));
202 return Error::NONE;
203}
204
205Error FakeComposerClient::destroyLayer(Display /*display*/, Layer layer) {
206 ALOGV("destroyLayer");
207 mLayers[layer]->mValid = false;
208 return Error::NONE;
209}
210
211Error FakeComposerClient::getActiveConfig(Display /*display*/, Config* outConfig) {
212 ALOGV("getActiveConfig");
213
214 // TODO Assert outConfig != nullptr
215
216 // TODO This is my reading of the
217 // IComposerClient::getActiveConfig, but returning BAD_CONFIG
218 // seems to not fit SurfaceFlinger plans. See version 2 below.
219 // if (mCurrentConfig == NULL_DISPLAY_CONFIG) {
220 // return Error::BAD_CONFIG;
221 // }
222 //*outConfig = mCurrentConfig;
223 *outConfig = 1; // Very special config for you my friend
224 return Error::NONE;
225}
226
227Error FakeComposerClient::getClientTargetSupport(Display /*display*/, uint32_t /*width*/,
228 uint32_t /*height*/, PixelFormat /*format*/,
229 Dataspace /*dataspace*/) {
230 ALOGV("getClientTargetSupport");
231 return Error::NONE;
232}
233
234Error FakeComposerClient::getColorModes(Display /*display*/, hidl_vec<ColorMode>* /*outModes*/) {
235 ALOGV("getColorModes");
236 return Error::NONE;
237}
238
239Error FakeComposerClient::getDisplayAttribute(Display display, Config config,
240 IComposerClient::Attribute attribute,
241 int32_t* outValue) {
242 ALOGV("getDisplayAttribute (%d, %d, %d, %p)", static_cast<int>(display),
243 static_cast<int>(config), static_cast<int>(attribute), outValue);
244
245 // TODO: SOOO much fun to be had with these alone
246 switch (attribute) {
247 case IComposerClient::Attribute::WIDTH:
248 *outValue = 1920;
249 break;
250 case IComposerClient::Attribute::HEIGHT:
251 *outValue = 1080;
252 break;
253 case IComposerClient::Attribute::VSYNC_PERIOD:
254 *outValue = 1666666666;
255 break; // TOOD: Tests break down if lowered to 16ms?
256 case IComposerClient::Attribute::DPI_X:
257 *outValue = 240;
258 break;
259 case IComposerClient::Attribute::DPI_Y:
260 *outValue = 240;
261 break;
262 default:
263 LOG_ALWAYS_FATAL("Say what!?! New attribute");
264 }
265
266 return Error::NONE;
267}
268
269Error FakeComposerClient::getDisplayConfigs(Display /*display*/, hidl_vec<Config>* outConfigs) {
270 ALOGV("getDisplayConfigs");
271 // TODO assert display == 1, outConfigs != nullptr
272
273 outConfigs->resize(1);
274 (*outConfigs)[0] = 1;
275
276 return Error::NONE;
277}
278
279Error FakeComposerClient::getDisplayName(Display /*display*/, hidl_string* /*outName*/) {
280 ALOGV("getDisplayName");
281 return Error::NONE;
282}
283
284Error FakeComposerClient::getDisplayType(Display /*display*/,
285 IComposerClient::DisplayType* outType) {
286 ALOGV("getDisplayType");
287 // TODO: This setting nothing on the output had no effect on initial trials. Is first display
288 // assumed to be physical?
289 *outType = static_cast<IComposerClient::DisplayType>(HWC2_DISPLAY_TYPE_PHYSICAL);
290 return Error::NONE;
291}
292
293Error FakeComposerClient::getDozeSupport(Display /*display*/, bool* /*outSupport*/) {
294 ALOGV("getDozeSupport");
295 return Error::NONE;
296}
297
298Error FakeComposerClient::getHdrCapabilities(Display /*display*/, hidl_vec<Hdr>* /*outTypes*/,
299 float* /*outMaxLuminance*/,
300 float* /*outMaxAverageLuminance*/,
301 float* /*outMinLuminance*/) {
302 ALOGV("getHdrCapabilities");
303 return Error::NONE;
304}
305
306Error FakeComposerClient::setActiveConfig(Display /*display*/, Config config) {
307 ALOGV("setActiveConfig");
308 mCurrentConfig = config;
309 return Error::NONE;
310}
311
312Error FakeComposerClient::setColorMode(Display /*display*/, ColorMode /*mode*/) {
313 ALOGV("setColorMode");
314 return Error::NONE;
315}
316
317Error FakeComposerClient::setPowerMode(Display /*display*/, IComposerClient::PowerMode /*mode*/) {
318 ALOGV("setPowerMode");
319 return Error::NONE;
320}
321
322Error FakeComposerClient::setVsyncEnabled(Display /*display*/, IComposerClient::Vsync enabled) {
323 mVsyncEnabled = (enabled == IComposerClient::Vsync::ENABLE);
324 ALOGV("setVsyncEnabled(%s)", mVsyncEnabled ? "ENABLE" : "DISABLE");
325 return Error::NONE;
326}
327
328Error FakeComposerClient::setColorTransform(Display /*display*/, const float* /*matrix*/,
329 int32_t /*hint*/) {
330 ALOGV("setColorTransform");
331 return Error::NONE;
332}
333
334Error FakeComposerClient::setClientTarget(Display /*display*/, buffer_handle_t /*target*/,
335 int32_t /*acquireFence*/, int32_t /*dataspace*/,
336 const std::vector<hwc_rect_t>& /*damage*/) {
337 ALOGV("setClientTarget");
338 return Error::NONE;
339}
340
341Error FakeComposerClient::setOutputBuffer(Display /*display*/, buffer_handle_t /*buffer*/,
342 int32_t /*releaseFence*/) {
343 ALOGV("setOutputBuffer");
344 return Error::NONE;
345}
346
347Error FakeComposerClient::validateDisplay(
348 Display /*display*/, std::vector<Layer>* /*outChangedLayers*/,
349 std::vector<IComposerClient::Composition>* /*outCompositionTypes*/,
350 uint32_t* /*outDisplayRequestMask*/, std::vector<Layer>* /*outRequestedLayers*/,
351 std::vector<uint32_t>* /*outRequestMasks*/) {
352 ALOGV("validateDisplay");
353 // TODO: Assume touching nothing means All Korrekt!
354 return Error::NONE;
355}
356
357Error FakeComposerClient::acceptDisplayChanges(Display /*display*/) {
358 ALOGV("acceptDisplayChanges");
359 // Didn't ask for changes because software is omnipotent.
360 return Error::NONE;
361}
362
363bool layerZOrdering(const std::unique_ptr<FrameRect>& a, const std::unique_ptr<FrameRect>& b) {
364 return a->z <= b->z;
365}
366
367Error FakeComposerClient::presentDisplay(Display /*display*/, int32_t* /*outPresentFence*/,
368 std::vector<Layer>* /*outLayers*/,
369 std::vector<int32_t>* /*outReleaseFences*/) {
370 ALOGV("presentDisplay");
371 // TODO Leaving layers and their fences out for now. Doing so
372 // means that we've already processed everything. Important to
373 // test that the fences are respected, though. (How?)
374
375 std::unique_ptr<Frame> newFrame(new Frame);
376 for (uint64_t layer = 0; layer < mLayers.size(); layer++) {
377 const LayerImpl& layerImpl = *mLayers[layer];
378
379 if (!layerImpl.mValid) continue;
380
381 auto rect = std::make_unique<FrameRect>(layer, layerImpl.mRenderState, layerImpl.mZ);
382 newFrame->rectangles.push_back(std::move(rect));
383 }
384 std::sort(newFrame->rectangles.begin(), newFrame->rectangles.end(), layerZOrdering);
385 {
386 Mutex::Autolock _l(mStateMutex);
387 mFrames.push_back(std::move(newFrame));
388 mFramesAvailable.broadcast();
389 }
390 return Error::NONE;
391}
392
393Error FakeComposerClient::setLayerCursorPosition(Display /*display*/, Layer /*layer*/,
394 int32_t /*x*/, int32_t /*y*/) {
395 ALOGV("setLayerCursorPosition");
396 return Error::NONE;
397}
398
399Error FakeComposerClient::setLayerBuffer(Display /*display*/, Layer layer, buffer_handle_t buffer,
400 int32_t acquireFence) {
401 ALOGV("setLayerBuffer");
402 LayerImpl& l = getLayerImpl(layer);
403 if (buffer != l.mRenderState.mBuffer) {
404 l.mRenderState.mSwapCount++; // TODO: Is setting to same value a swap or not?
405 }
406 l.mRenderState.mBuffer = buffer;
407 l.mRenderState.mAcquireFence = acquireFence;
408
409 return Error::NONE;
410}
411
412Error FakeComposerClient::setLayerSurfaceDamage(Display /*display*/, Layer /*layer*/,
413 const std::vector<hwc_rect_t>& /*damage*/) {
414 ALOGV("setLayerSurfaceDamage");
415 return Error::NONE;
416}
417
418Error FakeComposerClient::setLayerBlendMode(Display /*display*/, Layer layer, int32_t mode) {
419 ALOGV("setLayerBlendMode");
420 getLayerImpl(layer).mRenderState.mBlendMode = static_cast<hwc2_blend_mode_t>(mode);
421 return Error::NONE;
422}
423
424Error FakeComposerClient::setLayerColor(Display /*display*/, Layer layer,
425 IComposerClient::Color color) {
426 ALOGV("setLayerColor");
427 getLayerImpl(layer).mRenderState.mLayerColor.r = color.r;
428 getLayerImpl(layer).mRenderState.mLayerColor.g = color.g;
429 getLayerImpl(layer).mRenderState.mLayerColor.b = color.b;
430 getLayerImpl(layer).mRenderState.mLayerColor.a = color.a;
431 return Error::NONE;
432}
433
434Error FakeComposerClient::setLayerCompositionType(Display /*display*/, Layer /*layer*/,
435 int32_t /*type*/) {
436 ALOGV("setLayerCompositionType");
437 return Error::NONE;
438}
439
440Error FakeComposerClient::setLayerDataspace(Display /*display*/, Layer /*layer*/,
441 int32_t /*dataspace*/) {
442 ALOGV("setLayerDataspace");
443 return Error::NONE;
444}
445
446Error FakeComposerClient::setLayerDisplayFrame(Display /*display*/, Layer layer,
447 const hwc_rect_t& frame) {
448 ALOGV("setLayerDisplayFrame (%d, %d, %d, %d)", frame.left, frame.top, frame.right,
449 frame.bottom);
450 getLayerImpl(layer).mRenderState.mDisplayFrame = frame;
451 return Error::NONE;
452}
453
454Error FakeComposerClient::setLayerPlaneAlpha(Display /*display*/, Layer layer, float alpha) {
455 ALOGV("setLayerPlaneAlpha");
456 getLayerImpl(layer).mRenderState.mPlaneAlpha = alpha;
457 return Error::NONE;
458}
459
460Error FakeComposerClient::setLayerSidebandStream(Display /*display*/, Layer /*layer*/,
461 buffer_handle_t /*stream*/) {
462 ALOGV("setLayerSidebandStream");
463 return Error::NONE;
464}
465
466Error FakeComposerClient::setLayerSourceCrop(Display /*display*/, Layer layer,
467 const hwc_frect_t& crop) {
468 ALOGV("setLayerSourceCrop");
469 getLayerImpl(layer).mRenderState.mSourceCrop = crop;
470 return Error::NONE;
471}
472
473Error FakeComposerClient::setLayerTransform(Display /*display*/, Layer layer, int32_t transform) {
474 ALOGV("setLayerTransform");
475 getLayerImpl(layer).mRenderState.mTransform = static_cast<hwc_transform_t>(transform);
476 return Error::NONE;
477}
478
479Error FakeComposerClient::setLayerVisibleRegion(Display /*display*/, Layer layer,
480 const std::vector<hwc_rect_t>& visible) {
481 ALOGV("setLayerVisibleRegion");
482 getLayerImpl(layer).mRenderState.mVisibleRegion = visible;
483 return Error::NONE;
484}
485
486Error FakeComposerClient::setLayerZOrder(Display /*display*/, Layer layer, uint32_t z) {
487 ALOGV("setLayerZOrder");
488 getLayerImpl(layer).mZ = z;
489 return Error::NONE;
490}
491
492//////////////////////////////////////////////////////////////////
493
494void FakeComposerClient::setClient(ComposerClient* client) {
495 mClient = client;
496}
497
498void FakeComposerClient::requestVSync(uint64_t vsyncTime) {
499 if (mCallbacksOn) {
500 uint64_t timestamp = vsyncTime;
501 ALOGV("Vsync");
502 if (timestamp == 0) {
503 struct timespec ts;
504 clock_gettime(CLOCK_MONOTONIC, &ts);
505 timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
506 }
507 if (mSurfaceComposer != nullptr) {
508 mSurfaceComposer->injectVSync(timestamp);
509 } else {
510 mClient->onVsync(DEFAULT_DISPLAY, timestamp);
511 }
512 }
513}
514
515void FakeComposerClient::runVSyncAfter(std::chrono::nanoseconds wait) {
516 mDelayedEventGenerator->wakeAfter(wait);
517}
518
519LayerImpl& FakeComposerClient::getLayerImpl(Layer handle) {
520 // TODO Change these to an internal state check that can be
521 // invoked from the gtest? GTest macros do not seem all that safe
522 // when used outside the test class
523 EXPECT_GE(handle, static_cast<Layer>(0));
524 EXPECT_LT(handle, mLayers.size());
525 return *(mLayers[handle]);
526}
527
528int FakeComposerClient::getFrameCount() const {
529 return mFrames.size();
530}
531
532static std::vector<RenderState> extractRenderState(
533 const std::vector<std::unique_ptr<FrameRect>>& internalRects) {
534 std::vector<RenderState> result;
535 result.reserve(internalRects.size());
536 for (const std::unique_ptr<FrameRect>& rect : internalRects) {
537 result.push_back(rect->renderState);
538 }
539 return result;
540}
541
542std::vector<RenderState> FakeComposerClient::getFrameRects(int frame) const {
543 Mutex::Autolock _l(mStateMutex);
544 return extractRenderState(mFrames[frame]->rectangles);
545}
546
547std::vector<RenderState> FakeComposerClient::getLatestFrame() const {
548 Mutex::Autolock _l(mStateMutex);
549 return extractRenderState(mFrames[mFrames.size() - 1]->rectangles);
550}
551
552void FakeComposerClient::runVSyncAndWait(std::chrono::nanoseconds maxWait) {
553 int currentFrame = 0;
554 {
555 Mutex::Autolock _l(mStateMutex); // I hope this is ok...
556 currentFrame = static_cast<int>(mFrames.size());
557 requestVSync();
558 }
559 waitUntilFrame(currentFrame + 1, maxWait);
560}
561
562void FakeComposerClient::waitUntilFrame(int targetFrame, std::chrono::nanoseconds maxWait) const {
563 Mutex::Autolock _l(mStateMutex);
564 while (mFrames.size() < static_cast<size_t>(targetFrame)) {
565 android::status_t result = mFramesAvailable.waitRelative(mStateMutex, maxWait.count());
566 if (result == android::TIMED_OUT) {
567 ALOGE("Waiting for frame %d (at frame %zu now) timed out after %lld ns", targetFrame,
568 mFrames.size(), maxWait.count());
569 return;
570 }
571 }
572}
573
574void FakeComposerClient::clearFrames() {
575 Mutex::Autolock _l(mStateMutex);
576 mFrames.clear();
577 for (const std::unique_ptr<LayerImpl>& layer : mLayers) {
578 if (layer->mValid) {
579 layer->mRenderState.mSwapCount = 0;
580 }
581 }
582}
583
584void FakeComposerClient::onSurfaceFlingerStart() {
Chih-Hung Hsieh53d76f12017-12-05 11:36:23 -0800585 mSurfaceComposer = nullptr;
Kalle Raitaa099a242017-01-11 11:17:29 -0800586 do {
587 mSurfaceComposer = new android::SurfaceComposerClient;
588 android::status_t initResult = mSurfaceComposer->initCheck();
589 if (initResult != android::NO_ERROR) {
590 ALOGD("Init result: %d", initResult);
591 mSurfaceComposer = nullptr;
592 std::this_thread::sleep_for(10ms);
593 }
594 } while (mSurfaceComposer == nullptr);
595 ALOGD("SurfaceComposerClient created");
596 mSurfaceComposer->enableVSyncInjections(true);
597}
598
599void FakeComposerClient::onSurfaceFlingerStop() {
600 mSurfaceComposer->dispose();
601 mSurfaceComposer.clear();
602}
603
604// Includes destroyed layers, stored in order of creation.
605int FakeComposerClient::getLayerCount() const {
606 return mLayers.size();
607}
608
609Layer FakeComposerClient::getLayer(size_t index) const {
610 // NOTE: If/when passing calls through to actual implementation,
611 // this might get more involving.
612 return static_cast<Layer>(index);
613}