blob: 07b8cc0b0d9f0c13927916747f6d572bef4af8f4 [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
Chia-I Wu41b98d42017-12-11 11:04:36 -0800160bool FakeComposerClient::hasCapability(hwc2_capability_t /*capability*/) {
161 return false;
162}
163
Kalle Raitaa099a242017-01-11 11:17:29 -0800164void FakeComposerClient::removeClient() {
165 ALOGV("removeClient");
166 // TODO: Ahooga! Only thing current lifetime management choices in
167 // APIs make possible. Sad.
168 delete this;
169}
170
171void FakeComposerClient::enableCallback(bool enable) {
172 ALOGV("enableCallback");
173 mCallbacksOn = enable;
174 if (mCallbacksOn) {
175 mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
176 }
177}
178
179void FakeComposerClient::hotplugDisplay(Display display, IComposerCallback::Connection state) {
180 if (mCallbacksOn) {
181 mClient->onHotplug(display, state);
182 }
183}
184
185uint32_t FakeComposerClient::getMaxVirtualDisplayCount() {
186 ALOGV("getMaxVirtualDisplayCount");
187 return 1;
188}
189
190Error FakeComposerClient::createVirtualDisplay(uint32_t /*width*/, uint32_t /*height*/,
191 PixelFormat* /*format*/, Display* /*outDisplay*/) {
192 ALOGV("createVirtualDisplay");
193 return Error::NONE;
194}
195
196Error FakeComposerClient::destroyVirtualDisplay(Display /*display*/) {
197 ALOGV("destroyVirtualDisplay");
198 return Error::NONE;
199}
200
201Error FakeComposerClient::createLayer(Display /*display*/, Layer* outLayer) {
202 ALOGV("createLayer");
203 *outLayer = mLayers.size();
204 auto newLayer = std::make_unique<LayerImpl>();
205 mLayers.push_back(std::move(newLayer));
206 return Error::NONE;
207}
208
209Error FakeComposerClient::destroyLayer(Display /*display*/, Layer layer) {
210 ALOGV("destroyLayer");
211 mLayers[layer]->mValid = false;
212 return Error::NONE;
213}
214
215Error FakeComposerClient::getActiveConfig(Display /*display*/, Config* outConfig) {
216 ALOGV("getActiveConfig");
217
218 // TODO Assert outConfig != nullptr
219
220 // TODO This is my reading of the
221 // IComposerClient::getActiveConfig, but returning BAD_CONFIG
222 // seems to not fit SurfaceFlinger plans. See version 2 below.
223 // if (mCurrentConfig == NULL_DISPLAY_CONFIG) {
224 // return Error::BAD_CONFIG;
225 // }
226 //*outConfig = mCurrentConfig;
227 *outConfig = 1; // Very special config for you my friend
228 return Error::NONE;
229}
230
231Error FakeComposerClient::getClientTargetSupport(Display /*display*/, uint32_t /*width*/,
232 uint32_t /*height*/, PixelFormat /*format*/,
233 Dataspace /*dataspace*/) {
234 ALOGV("getClientTargetSupport");
235 return Error::NONE;
236}
237
238Error FakeComposerClient::getColorModes(Display /*display*/, hidl_vec<ColorMode>* /*outModes*/) {
239 ALOGV("getColorModes");
240 return Error::NONE;
241}
242
243Error FakeComposerClient::getDisplayAttribute(Display display, Config config,
244 IComposerClient::Attribute attribute,
245 int32_t* outValue) {
246 ALOGV("getDisplayAttribute (%d, %d, %d, %p)", static_cast<int>(display),
247 static_cast<int>(config), static_cast<int>(attribute), outValue);
248
249 // TODO: SOOO much fun to be had with these alone
250 switch (attribute) {
251 case IComposerClient::Attribute::WIDTH:
252 *outValue = 1920;
253 break;
254 case IComposerClient::Attribute::HEIGHT:
255 *outValue = 1080;
256 break;
257 case IComposerClient::Attribute::VSYNC_PERIOD:
258 *outValue = 1666666666;
259 break; // TOOD: Tests break down if lowered to 16ms?
260 case IComposerClient::Attribute::DPI_X:
261 *outValue = 240;
262 break;
263 case IComposerClient::Attribute::DPI_Y:
264 *outValue = 240;
265 break;
266 default:
267 LOG_ALWAYS_FATAL("Say what!?! New attribute");
268 }
269
270 return Error::NONE;
271}
272
273Error FakeComposerClient::getDisplayConfigs(Display /*display*/, hidl_vec<Config>* outConfigs) {
274 ALOGV("getDisplayConfigs");
275 // TODO assert display == 1, outConfigs != nullptr
276
277 outConfigs->resize(1);
278 (*outConfigs)[0] = 1;
279
280 return Error::NONE;
281}
282
283Error FakeComposerClient::getDisplayName(Display /*display*/, hidl_string* /*outName*/) {
284 ALOGV("getDisplayName");
285 return Error::NONE;
286}
287
288Error FakeComposerClient::getDisplayType(Display /*display*/,
289 IComposerClient::DisplayType* outType) {
290 ALOGV("getDisplayType");
291 // TODO: This setting nothing on the output had no effect on initial trials. Is first display
292 // assumed to be physical?
293 *outType = static_cast<IComposerClient::DisplayType>(HWC2_DISPLAY_TYPE_PHYSICAL);
294 return Error::NONE;
295}
296
297Error FakeComposerClient::getDozeSupport(Display /*display*/, bool* /*outSupport*/) {
298 ALOGV("getDozeSupport");
299 return Error::NONE;
300}
301
302Error FakeComposerClient::getHdrCapabilities(Display /*display*/, hidl_vec<Hdr>* /*outTypes*/,
303 float* /*outMaxLuminance*/,
304 float* /*outMaxAverageLuminance*/,
305 float* /*outMinLuminance*/) {
306 ALOGV("getHdrCapabilities");
307 return Error::NONE;
308}
309
310Error FakeComposerClient::setActiveConfig(Display /*display*/, Config config) {
311 ALOGV("setActiveConfig");
312 mCurrentConfig = config;
313 return Error::NONE;
314}
315
316Error FakeComposerClient::setColorMode(Display /*display*/, ColorMode /*mode*/) {
317 ALOGV("setColorMode");
318 return Error::NONE;
319}
320
321Error FakeComposerClient::setPowerMode(Display /*display*/, IComposerClient::PowerMode /*mode*/) {
322 ALOGV("setPowerMode");
323 return Error::NONE;
324}
325
326Error FakeComposerClient::setVsyncEnabled(Display /*display*/, IComposerClient::Vsync enabled) {
327 mVsyncEnabled = (enabled == IComposerClient::Vsync::ENABLE);
328 ALOGV("setVsyncEnabled(%s)", mVsyncEnabled ? "ENABLE" : "DISABLE");
329 return Error::NONE;
330}
331
332Error FakeComposerClient::setColorTransform(Display /*display*/, const float* /*matrix*/,
333 int32_t /*hint*/) {
334 ALOGV("setColorTransform");
335 return Error::NONE;
336}
337
338Error FakeComposerClient::setClientTarget(Display /*display*/, buffer_handle_t /*target*/,
339 int32_t /*acquireFence*/, int32_t /*dataspace*/,
340 const std::vector<hwc_rect_t>& /*damage*/) {
341 ALOGV("setClientTarget");
342 return Error::NONE;
343}
344
345Error FakeComposerClient::setOutputBuffer(Display /*display*/, buffer_handle_t /*buffer*/,
346 int32_t /*releaseFence*/) {
347 ALOGV("setOutputBuffer");
348 return Error::NONE;
349}
350
351Error FakeComposerClient::validateDisplay(
352 Display /*display*/, std::vector<Layer>* /*outChangedLayers*/,
353 std::vector<IComposerClient::Composition>* /*outCompositionTypes*/,
354 uint32_t* /*outDisplayRequestMask*/, std::vector<Layer>* /*outRequestedLayers*/,
355 std::vector<uint32_t>* /*outRequestMasks*/) {
356 ALOGV("validateDisplay");
357 // TODO: Assume touching nothing means All Korrekt!
358 return Error::NONE;
359}
360
361Error FakeComposerClient::acceptDisplayChanges(Display /*display*/) {
362 ALOGV("acceptDisplayChanges");
363 // Didn't ask for changes because software is omnipotent.
364 return Error::NONE;
365}
366
367bool layerZOrdering(const std::unique_ptr<FrameRect>& a, const std::unique_ptr<FrameRect>& b) {
368 return a->z <= b->z;
369}
370
371Error FakeComposerClient::presentDisplay(Display /*display*/, int32_t* /*outPresentFence*/,
372 std::vector<Layer>* /*outLayers*/,
373 std::vector<int32_t>* /*outReleaseFences*/) {
374 ALOGV("presentDisplay");
375 // TODO Leaving layers and their fences out for now. Doing so
376 // means that we've already processed everything. Important to
377 // test that the fences are respected, though. (How?)
378
379 std::unique_ptr<Frame> newFrame(new Frame);
380 for (uint64_t layer = 0; layer < mLayers.size(); layer++) {
381 const LayerImpl& layerImpl = *mLayers[layer];
382
383 if (!layerImpl.mValid) continue;
384
385 auto rect = std::make_unique<FrameRect>(layer, layerImpl.mRenderState, layerImpl.mZ);
386 newFrame->rectangles.push_back(std::move(rect));
387 }
388 std::sort(newFrame->rectangles.begin(), newFrame->rectangles.end(), layerZOrdering);
389 {
390 Mutex::Autolock _l(mStateMutex);
391 mFrames.push_back(std::move(newFrame));
392 mFramesAvailable.broadcast();
393 }
394 return Error::NONE;
395}
396
397Error FakeComposerClient::setLayerCursorPosition(Display /*display*/, Layer /*layer*/,
398 int32_t /*x*/, int32_t /*y*/) {
399 ALOGV("setLayerCursorPosition");
400 return Error::NONE;
401}
402
403Error FakeComposerClient::setLayerBuffer(Display /*display*/, Layer layer, buffer_handle_t buffer,
404 int32_t acquireFence) {
405 ALOGV("setLayerBuffer");
406 LayerImpl& l = getLayerImpl(layer);
407 if (buffer != l.mRenderState.mBuffer) {
408 l.mRenderState.mSwapCount++; // TODO: Is setting to same value a swap or not?
409 }
410 l.mRenderState.mBuffer = buffer;
411 l.mRenderState.mAcquireFence = acquireFence;
412
413 return Error::NONE;
414}
415
416Error FakeComposerClient::setLayerSurfaceDamage(Display /*display*/, Layer /*layer*/,
417 const std::vector<hwc_rect_t>& /*damage*/) {
418 ALOGV("setLayerSurfaceDamage");
419 return Error::NONE;
420}
421
422Error FakeComposerClient::setLayerBlendMode(Display /*display*/, Layer layer, int32_t mode) {
423 ALOGV("setLayerBlendMode");
424 getLayerImpl(layer).mRenderState.mBlendMode = static_cast<hwc2_blend_mode_t>(mode);
425 return Error::NONE;
426}
427
428Error FakeComposerClient::setLayerColor(Display /*display*/, Layer layer,
429 IComposerClient::Color color) {
430 ALOGV("setLayerColor");
431 getLayerImpl(layer).mRenderState.mLayerColor.r = color.r;
432 getLayerImpl(layer).mRenderState.mLayerColor.g = color.g;
433 getLayerImpl(layer).mRenderState.mLayerColor.b = color.b;
434 getLayerImpl(layer).mRenderState.mLayerColor.a = color.a;
435 return Error::NONE;
436}
437
438Error FakeComposerClient::setLayerCompositionType(Display /*display*/, Layer /*layer*/,
439 int32_t /*type*/) {
440 ALOGV("setLayerCompositionType");
441 return Error::NONE;
442}
443
444Error FakeComposerClient::setLayerDataspace(Display /*display*/, Layer /*layer*/,
445 int32_t /*dataspace*/) {
446 ALOGV("setLayerDataspace");
447 return Error::NONE;
448}
449
450Error FakeComposerClient::setLayerDisplayFrame(Display /*display*/, Layer layer,
451 const hwc_rect_t& frame) {
452 ALOGV("setLayerDisplayFrame (%d, %d, %d, %d)", frame.left, frame.top, frame.right,
453 frame.bottom);
454 getLayerImpl(layer).mRenderState.mDisplayFrame = frame;
455 return Error::NONE;
456}
457
458Error FakeComposerClient::setLayerPlaneAlpha(Display /*display*/, Layer layer, float alpha) {
459 ALOGV("setLayerPlaneAlpha");
460 getLayerImpl(layer).mRenderState.mPlaneAlpha = alpha;
461 return Error::NONE;
462}
463
464Error FakeComposerClient::setLayerSidebandStream(Display /*display*/, Layer /*layer*/,
465 buffer_handle_t /*stream*/) {
466 ALOGV("setLayerSidebandStream");
467 return Error::NONE;
468}
469
470Error FakeComposerClient::setLayerSourceCrop(Display /*display*/, Layer layer,
471 const hwc_frect_t& crop) {
472 ALOGV("setLayerSourceCrop");
473 getLayerImpl(layer).mRenderState.mSourceCrop = crop;
474 return Error::NONE;
475}
476
477Error FakeComposerClient::setLayerTransform(Display /*display*/, Layer layer, int32_t transform) {
478 ALOGV("setLayerTransform");
479 getLayerImpl(layer).mRenderState.mTransform = static_cast<hwc_transform_t>(transform);
480 return Error::NONE;
481}
482
483Error FakeComposerClient::setLayerVisibleRegion(Display /*display*/, Layer layer,
484 const std::vector<hwc_rect_t>& visible) {
485 ALOGV("setLayerVisibleRegion");
486 getLayerImpl(layer).mRenderState.mVisibleRegion = visible;
487 return Error::NONE;
488}
489
490Error FakeComposerClient::setLayerZOrder(Display /*display*/, Layer layer, uint32_t z) {
491 ALOGV("setLayerZOrder");
492 getLayerImpl(layer).mZ = z;
493 return Error::NONE;
494}
495
496//////////////////////////////////////////////////////////////////
497
498void FakeComposerClient::setClient(ComposerClient* client) {
499 mClient = client;
500}
501
502void FakeComposerClient::requestVSync(uint64_t vsyncTime) {
503 if (mCallbacksOn) {
504 uint64_t timestamp = vsyncTime;
505 ALOGV("Vsync");
506 if (timestamp == 0) {
507 struct timespec ts;
508 clock_gettime(CLOCK_MONOTONIC, &ts);
509 timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
510 }
511 if (mSurfaceComposer != nullptr) {
512 mSurfaceComposer->injectVSync(timestamp);
513 } else {
514 mClient->onVsync(DEFAULT_DISPLAY, timestamp);
515 }
516 }
517}
518
519void FakeComposerClient::runVSyncAfter(std::chrono::nanoseconds wait) {
520 mDelayedEventGenerator->wakeAfter(wait);
521}
522
523LayerImpl& FakeComposerClient::getLayerImpl(Layer handle) {
524 // TODO Change these to an internal state check that can be
525 // invoked from the gtest? GTest macros do not seem all that safe
526 // when used outside the test class
527 EXPECT_GE(handle, static_cast<Layer>(0));
528 EXPECT_LT(handle, mLayers.size());
529 return *(mLayers[handle]);
530}
531
532int FakeComposerClient::getFrameCount() const {
533 return mFrames.size();
534}
535
536static std::vector<RenderState> extractRenderState(
537 const std::vector<std::unique_ptr<FrameRect>>& internalRects) {
538 std::vector<RenderState> result;
539 result.reserve(internalRects.size());
540 for (const std::unique_ptr<FrameRect>& rect : internalRects) {
541 result.push_back(rect->renderState);
542 }
543 return result;
544}
545
546std::vector<RenderState> FakeComposerClient::getFrameRects(int frame) const {
547 Mutex::Autolock _l(mStateMutex);
548 return extractRenderState(mFrames[frame]->rectangles);
549}
550
551std::vector<RenderState> FakeComposerClient::getLatestFrame() const {
552 Mutex::Autolock _l(mStateMutex);
553 return extractRenderState(mFrames[mFrames.size() - 1]->rectangles);
554}
555
556void FakeComposerClient::runVSyncAndWait(std::chrono::nanoseconds maxWait) {
557 int currentFrame = 0;
558 {
559 Mutex::Autolock _l(mStateMutex); // I hope this is ok...
560 currentFrame = static_cast<int>(mFrames.size());
561 requestVSync();
562 }
563 waitUntilFrame(currentFrame + 1, maxWait);
564}
565
566void FakeComposerClient::waitUntilFrame(int targetFrame, std::chrono::nanoseconds maxWait) const {
567 Mutex::Autolock _l(mStateMutex);
568 while (mFrames.size() < static_cast<size_t>(targetFrame)) {
569 android::status_t result = mFramesAvailable.waitRelative(mStateMutex, maxWait.count());
570 if (result == android::TIMED_OUT) {
571 ALOGE("Waiting for frame %d (at frame %zu now) timed out after %lld ns", targetFrame,
572 mFrames.size(), maxWait.count());
573 return;
574 }
575 }
576}
577
578void FakeComposerClient::clearFrames() {
579 Mutex::Autolock _l(mStateMutex);
580 mFrames.clear();
581 for (const std::unique_ptr<LayerImpl>& layer : mLayers) {
582 if (layer->mValid) {
583 layer->mRenderState.mSwapCount = 0;
584 }
585 }
586}
587
588void FakeComposerClient::onSurfaceFlingerStart() {
Chih-Hung Hsieh53d76f12017-12-05 11:36:23 -0800589 mSurfaceComposer = nullptr;
Kalle Raitaa099a242017-01-11 11:17:29 -0800590 do {
591 mSurfaceComposer = new android::SurfaceComposerClient;
592 android::status_t initResult = mSurfaceComposer->initCheck();
593 if (initResult != android::NO_ERROR) {
594 ALOGD("Init result: %d", initResult);
595 mSurfaceComposer = nullptr;
596 std::this_thread::sleep_for(10ms);
597 }
598 } while (mSurfaceComposer == nullptr);
599 ALOGD("SurfaceComposerClient created");
600 mSurfaceComposer->enableVSyncInjections(true);
601}
602
603void FakeComposerClient::onSurfaceFlingerStop() {
604 mSurfaceComposer->dispose();
605 mSurfaceComposer.clear();
606}
607
608// Includes destroyed layers, stored in order of creation.
609int FakeComposerClient::getLayerCount() const {
610 return mLayers.size();
611}
612
613Layer FakeComposerClient::getLayer(size_t index) const {
614 // NOTE: If/when passing calls through to actual implementation,
615 // this might get more involving.
616 return static_cast<Layer>(index);
617}