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