Replayer.cpp revision 01041fe22aead67520962b534134b3e3291b1622
1/* Copyright 2016 The Android Open Source Project
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *      http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16//#define LOG_NDEBUG 0
17#define LOG_TAG "SurfaceReplayer"
18
19#include "Replayer.h"
20
21#include <android/native_window.h>
22
23#include <binder/IMemory.h>
24
25#include <gui/BufferQueue.h>
26#include <gui/ISurfaceComposer.h>
27#include <gui/Surface.h>
28#include <private/gui/ComposerService.h>
29#include <private/gui/LayerState.h>
30
31#include <ui/DisplayInfo.h>
32#include <utils/Log.h>
33#include <utils/String8.h>
34#include <utils/Trace.h>
35
36#include <chrono>
37#include <cmath>
38#include <condition_variable>
39#include <cstdlib>
40#include <fstream>
41#include <functional>
42#include <iostream>
43#include <mutex>
44#include <sstream>
45#include <string>
46#include <thread>
47#include <vector>
48
49using namespace android;
50
51std::atomic_bool Replayer::sReplayingManually(false);
52
53Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads, bool wait,
54        nsecs_t stopHere)
55      : mTrace(),
56        mLoaded(false),
57        mIncrementIndex(0),
58        mCurrentTime(0),
59        mNumThreads(numThreads),
60        mWaitForTimeStamps(wait),
61        mStopTimeStamp(stopHere) {
62    srand(RAND_COLOR_SEED);
63
64    std::fstream input(filename, std::ios::in | std::ios::binary);
65
66    mLoaded = mTrace.ParseFromIstream(&input);
67    if (!mLoaded) {
68        std::cerr << "Trace did not load. Does " << filename << " exist?" << std::endl;
69        abort();
70    }
71
72    mCurrentTime = mTrace.increment(0).time_stamp();
73
74    sReplayingManually.store(replayManually);
75
76    if (stopHere < 0) {
77        mHasStopped = true;
78    }
79}
80
81Replayer::Replayer(const Trace& t, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)
82      : mTrace(t),
83        mLoaded(true),
84        mIncrementIndex(0),
85        mCurrentTime(0),
86        mNumThreads(numThreads),
87        mWaitForTimeStamps(wait),
88        mStopTimeStamp(stopHere) {
89    srand(RAND_COLOR_SEED);
90    mCurrentTime = mTrace.increment(0).time_stamp();
91
92    sReplayingManually.store(replayManually);
93
94    if (stopHere < 0) {
95        mHasStopped = true;
96    }
97}
98
99status_t Replayer::replay() {
100    signal(SIGINT, Replayer::stopAutoReplayHandler); //for manual control
101
102    ALOGV("There are %d increments.", mTrace.increment_size());
103
104    status_t status = loadSurfaceComposerClient();
105
106    if (status != NO_ERROR) {
107        ALOGE("Couldn't create SurfaceComposerClient (%d)", status);
108        return status;
109    }
110
111    SurfaceComposerClient::enableVSyncInjections(true);
112
113    initReplay();
114
115    ALOGV("Starting actual Replay!");
116    while (!mPendingIncrements.empty()) {
117        mCurrentIncrement = mTrace.increment(mIncrementIndex);
118
119        if (mHasStopped == false && mCurrentIncrement.time_stamp() >= mStopTimeStamp) {
120            mHasStopped = true;
121            sReplayingManually.store(true);
122        }
123
124        waitForConsoleCommmand();
125
126        if (mWaitForTimeStamps) {
127            waitUntilTimestamp(mCurrentIncrement.time_stamp());
128        }
129
130        auto event = mPendingIncrements.front();
131        mPendingIncrements.pop();
132
133        event->complete();
134
135        if (event->getIncrementType() == Increment::kVsyncEvent) {
136            mWaitingForNextVSync = false;
137        }
138
139        if (mIncrementIndex + mNumThreads < mTrace.increment_size()) {
140            status = dispatchEvent(mIncrementIndex + mNumThreads);
141
142            if (status != NO_ERROR) {
143                SurfaceComposerClient::enableVSyncInjections(false);
144                return status;
145            }
146        }
147
148        mIncrementIndex++;
149        mCurrentTime = mCurrentIncrement.time_stamp();
150    }
151
152    SurfaceComposerClient::enableVSyncInjections(false);
153
154    return status;
155}
156
157status_t Replayer::initReplay() {
158    for (int i = 0; i < mNumThreads && i < mTrace.increment_size(); i++) {
159        status_t status = dispatchEvent(i);
160
161        if (status != NO_ERROR) {
162            ALOGE("Unable to dispatch event (%d)", status);
163            return status;
164        }
165    }
166
167    return NO_ERROR;
168}
169
170void Replayer::stopAutoReplayHandler(int /*signal*/) {
171    if (sReplayingManually) {
172        SurfaceComposerClient::enableVSyncInjections(false);
173        exit(0);
174    }
175
176    sReplayingManually.store(true);
177}
178
179std::vector<std::string> split(const std::string& s, const char delim) {
180    std::vector<std::string> elems;
181    std::stringstream ss(s);
182    std::string item;
183    while (getline(ss, item, delim)) {
184        elems.push_back(item);
185    }
186    return elems;
187}
188
189bool isNumber(const std::string& s) {
190    return !s.empty() &&
191           std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
192}
193
194void Replayer::waitForConsoleCommmand() {
195    if (!sReplayingManually || mWaitingForNextVSync) {
196        return;
197    }
198
199    while (true) {
200        std::string input = "";
201        std::cout << "> ";
202        getline(std::cin, input);
203
204        if (input.empty()) {
205            input = mLastInput;
206        } else {
207            mLastInput = input;
208        }
209
210        if (mLastInput.empty()) {
211            continue;
212        }
213
214        std::vector<std::string> inputs = split(input, ' ');
215
216        if (inputs[0] == "n") {  // next vsync
217            mWaitingForNextVSync = true;
218            break;
219
220        } else if (inputs[0] == "ni") {  // next increment
221            break;
222
223        } else if (inputs[0] == "c") {  // continue
224            if (inputs.size() > 1 && isNumber(inputs[1])) {
225                long milliseconds = stoi(inputs[1]);
226                std::thread([&] {
227                    std::cout << "Started!" << std::endl;
228                    std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
229                    sReplayingManually.store(true);
230                    std::cout << "Should have stopped!" << std::endl;
231                }).detach();
232            }
233            sReplayingManually.store(false);
234            mWaitingForNextVSync = false;
235            break;
236
237        } else if (inputs[0] == "s") {  // stop at this timestamp
238            if (inputs.size() < 1) {
239                std::cout << "No time stamp given" << std::endl;
240                continue;
241            }
242            sReplayingManually.store(false);
243            mStopTimeStamp = stol(inputs[1]);
244            mHasStopped = false;
245            break;
246        } else if (inputs[0] == "l") {  // list
247            std::cout << "Time stamp: " << mCurrentIncrement.time_stamp() << "\n";
248            continue;
249        } else if (inputs[0] == "q") {  // quit
250            SurfaceComposerClient::enableVSyncInjections(false);
251            exit(0);
252
253        } else if (inputs[0] == "h") {  // help
254                                        // add help menu
255            std::cout << "Manual Replay options:\n";
256            std::cout << " n  - Go to next VSync\n";
257            std::cout << " ni - Go to next increment\n";
258            std::cout << " c  - Continue\n";
259            std::cout << " c [milliseconds] - Continue until specified number of milliseconds\n";
260            std::cout << " s [timestamp]    - Continue and stop at specified timestamp\n";
261            std::cout << " l  - List out timestamp of current increment\n";
262            std::cout << " h  - Display help menu\n";
263            std::cout << std::endl;
264            continue;
265        }
266
267        std::cout << "Invalid Command" << std::endl;
268    }
269}
270
271status_t Replayer::dispatchEvent(int index) {
272    auto increment = mTrace.increment(index);
273    std::shared_ptr<Event> event = std::make_shared<Event>(increment.increment_case());
274    mPendingIncrements.push(event);
275
276    status_t status = NO_ERROR;
277    switch (increment.increment_case()) {
278        case increment.kTransaction: {
279            std::thread(&Replayer::doTransaction, this, increment.transaction(), event).detach();
280        } break;
281        case increment.kSurfaceCreation: {
282            std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
283                    .detach();
284        } break;
285        case increment.kSurfaceDeletion: {
286            std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event)
287                    .detach();
288        } break;
289        case increment.kBufferUpdate: {
290            std::lock_guard<std::mutex> lock1(mLayerLock);
291            std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
292
293            Dimensions dimensions(increment.buffer_update().w(), increment.buffer_update().h());
294            BufferEvent bufferEvent(event, dimensions);
295
296            auto layerId = increment.buffer_update().id();
297            if (mBufferQueueSchedulers.count(layerId) == 0) {
298                mBufferQueueSchedulers[layerId] = std::make_shared<BufferQueueScheduler>(
299                        mLayers[layerId], mColors[layerId], layerId);
300                mBufferQueueSchedulers[layerId]->addEvent(bufferEvent);
301
302                std::thread(&BufferQueueScheduler::startScheduling,
303                        mBufferQueueSchedulers[increment.buffer_update().id()].get())
304                        .detach();
305            } else {
306                auto bqs = mBufferQueueSchedulers[increment.buffer_update().id()];
307                bqs->addEvent(bufferEvent);
308            }
309        } break;
310        case increment.kVsyncEvent: {
311            std::thread(&Replayer::injectVSyncEvent, this, increment.vsync_event(), event).detach();
312        } break;
313        case increment.kDisplayCreation: {
314            std::thread(&Replayer::createDisplay, this, increment.display_creation(), event)
315                    .detach();
316        } break;
317        case increment.kDisplayDeletion: {
318            std::thread(&Replayer::deleteDisplay, this, increment.display_deletion(), event)
319                    .detach();
320        } break;
321        case increment.kPowerModeUpdate: {
322            std::thread(&Replayer::updatePowerMode, this, increment.power_mode_update(), event)
323                    .detach();
324        } break;
325        default:
326            ALOGE("Unknown Increment Type: %d", increment.increment_case());
327            status = BAD_VALUE;
328            break;
329    }
330
331    return status;
332}
333
334status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
335    ALOGV("Started Transaction");
336
337    SurfaceComposerClient::openGlobalTransaction();
338
339    status_t status = NO_ERROR;
340
341    status = doSurfaceTransaction(t.surface_change());
342    doDisplayTransaction(t.display_change());
343
344    if (t.animation()) {
345        SurfaceComposerClient::setAnimationTransaction();
346    }
347
348    event->readyToExecute();
349
350    SurfaceComposerClient::closeGlobalTransaction(t.synchronous());
351
352    ALOGV("Ended Transaction");
353
354    return status;
355}
356
357status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) {
358    status_t status = NO_ERROR;
359
360    for (const SurfaceChange& change : surfaceChanges) {
361        std::unique_lock<std::mutex> lock(mLayerLock);
362        if (mLayers[change.id()] == nullptr) {
363            mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
364        }
365
366        switch (change.SurfaceChange_case()) {
367            case SurfaceChange::SurfaceChangeCase::kPosition:
368                status = setPosition(change.id(), change.position());
369                break;
370            case SurfaceChange::SurfaceChangeCase::kSize:
371                status = setSize(change.id(), change.size());
372                break;
373            case SurfaceChange::SurfaceChangeCase::kAlpha:
374                status = setAlpha(change.id(), change.alpha());
375                break;
376            case SurfaceChange::SurfaceChangeCase::kLayer:
377                status = setLayer(change.id(), change.layer());
378                break;
379            case SurfaceChange::SurfaceChangeCase::kCrop:
380                status = setCrop(change.id(), change.crop());
381                break;
382            case SurfaceChange::SurfaceChangeCase::kMatrix:
383                status = setMatrix(change.id(), change.matrix());
384                break;
385            case SurfaceChange::SurfaceChangeCase::kFinalCrop:
386                status = setFinalCrop(change.id(), change.final_crop());
387                break;
388            case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
389                status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
390                break;
391            case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
392                status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
393                break;
394            case SurfaceChange::SurfaceChangeCase::kLayerStack:
395                status = setLayerStack(change.id(), change.layer_stack());
396                break;
397            case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
398                status = setHiddenFlag(change.id(), change.hidden_flag());
399                break;
400            case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
401                status = setOpaqueFlag(change.id(), change.opaque_flag());
402                break;
403            case SurfaceChange::SurfaceChangeCase::kSecureFlag:
404                status = setSecureFlag(change.id(), change.secure_flag());
405                break;
406            case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
407                waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
408                status = setDeferredTransaction(change.id(), change.deferred_transaction());
409                break;
410            default:
411                status = NO_ERROR;
412                break;
413        }
414
415        if (status != NO_ERROR) {
416            ALOGE("SET TRANSACTION FAILED");
417            return status;
418        }
419    }
420    return status;
421}
422
423void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) {
424    for (const DisplayChange& change : displayChanges) {
425        ALOGV("Doing display transaction");
426        std::unique_lock<std::mutex> lock(mDisplayLock);
427        if (mDisplays[change.id()] == nullptr) {
428            mDisplayCond.wait(lock, [&] { return (mDisplays[change.id()] != nullptr); });
429        }
430
431        switch (change.DisplayChange_case()) {
432            case DisplayChange::DisplayChangeCase::kSurface:
433                setDisplaySurface(change.id(), change.surface());
434                break;
435            case DisplayChange::DisplayChangeCase::kLayerStack:
436                setDisplayLayerStack(change.id(), change.layer_stack());
437                break;
438            case DisplayChange::DisplayChangeCase::kSize:
439                setDisplaySize(change.id(), change.size());
440                break;
441            case DisplayChange::DisplayChangeCase::kProjection:
442                setDisplayProjection(change.id(), change.projection());
443                break;
444            default:
445                break;
446        }
447    }
448}
449
450status_t Replayer::setPosition(layer_id id, const PositionChange& pc) {
451    ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
452    return mLayers[id]->setPosition(pc.x(), pc.y());
453}
454
455status_t Replayer::setSize(layer_id id, const SizeChange& sc) {
456    ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
457    return mLayers[id]->setSize(sc.w(), sc.h());
458}
459
460status_t Replayer::setLayer(layer_id id, const LayerChange& lc) {
461    ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
462    return mLayers[id]->setLayer(lc.layer());
463}
464
465status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) {
466    ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
467    return mLayers[id]->setAlpha(ac.alpha());
468}
469
470status_t Replayer::setCrop(layer_id id, const CropChange& cc) {
471    ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
472            cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
473            cc.rectangle().bottom());
474
475    Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
476            cc.rectangle().bottom());
477    return mLayers[id]->setCrop(r);
478}
479
480status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) {
481    ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
482            fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
483            fcc.rectangle().bottom());
484    Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
485            fcc.rectangle().bottom());
486    return mLayers[id]->setFinalCrop(r);
487}
488
489status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) {
490    ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
491            mc.dtdx(), mc.dsdy(), mc.dtdy());
492    return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
493}
494
495status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) {
496    ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
497    return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
498}
499
500status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) {
501    ALOGV("Setting Transparent Region Hint");
502    Region re = Region();
503
504    for (auto r : trhc.region()) {
505        Rect rect = Rect(r.left(), r.top(), r.right(), r.bottom());
506        re.merge(rect);
507    }
508
509    return mLayers[id]->setTransparentRegionHint(re);
510}
511
512status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) {
513    ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
514    return mLayers[id]->setLayerStack(lsc.layer_stack());
515}
516
517status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) {
518    ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
519    layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
520
521    return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
522}
523
524status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) {
525    ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
526    layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
527
528    return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
529}
530
531status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) {
532    ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
533    layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
534
535    return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
536}
537
538status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) {
539    ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
540          "frame_number=%llu",
541            id, dtc.layer_id(), dtc.frame_number());
542    if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
543        ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id());
544        return BAD_VALUE;
545    }
546
547    auto handle = mLayers[dtc.layer_id()]->getHandle();
548
549    return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
550}
551
552void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) {
553    sp<IGraphicBufferProducer> outProducer;
554    sp<IGraphicBufferConsumer> outConsumer;
555    BufferQueue::createBufferQueue(&outProducer, &outConsumer);
556
557    SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer);
558}
559
560void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) {
561    SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
562}
563
564void Replayer::setDisplaySize(display_id id, const SizeChange& sc) {
565    SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h());
566}
567
568void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) {
569    Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
570            pc.viewport().bottom());
571    Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
572
573    SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
574}
575
576status_t Replayer::createSurfaceControl(
577        const SurfaceCreation& create, const std::shared_ptr<Event>& event) {
578    event->readyToExecute();
579
580    ALOGV("Creating Surface Control: ID: %d", create.id());
581    sp<SurfaceControl> surfaceControl = mComposerClient->createSurface(
582            String8(create.name().c_str()), create.w(), create.h(), PIXEL_FORMAT_RGBA_8888, 0);
583
584    if (surfaceControl == nullptr) {
585        ALOGE("CreateSurfaceControl: unable to create surface control");
586        return BAD_VALUE;
587    }
588
589    std::lock_guard<std::mutex> lock1(mLayerLock);
590    auto& layer = mLayers[create.id()];
591    layer = surfaceControl;
592
593    mColors[create.id()] = HSV(rand() % 360, 1, 1);
594
595    mLayerCond.notify_all();
596
597    std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
598    if (mBufferQueueSchedulers.count(create.id()) != 0) {
599        mBufferQueueSchedulers[create.id()]->setSurfaceControl(
600                mLayers[create.id()], mColors[create.id()]);
601    }
602
603    return NO_ERROR;
604}
605
606status_t Replayer::deleteSurfaceControl(
607        const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) {
608    ALOGV("Deleting %d Surface Control", delete_.id());
609    event->readyToExecute();
610
611    std::lock_guard<std::mutex> lock1(mPendingLayersLock);
612
613    mLayersPendingRemoval.push_back(delete_.id());
614
615    const auto& iterator = mBufferQueueSchedulers.find(delete_.id());
616    if (iterator != mBufferQueueSchedulers.end()) {
617        (*iterator).second->stopScheduling();
618    }
619
620    std::lock_guard<std::mutex> lock2(mLayerLock);
621    if (mLayers[delete_.id()] != nullptr) {
622        mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
623    }
624
625    return NO_ERROR;
626}
627
628void Replayer::doDeleteSurfaceControls() {
629    std::lock_guard<std::mutex> lock1(mPendingLayersLock);
630    std::lock_guard<std::mutex> lock2(mLayerLock);
631    if (!mLayersPendingRemoval.empty()) {
632        for (int id : mLayersPendingRemoval) {
633            mLayers.erase(id);
634            mColors.erase(id);
635            mBufferQueueSchedulers.erase(id);
636        }
637        mLayersPendingRemoval.clear();
638    }
639}
640
641status_t Replayer::injectVSyncEvent(
642        const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) {
643    ALOGV("Injecting VSync Event");
644
645    doDeleteSurfaceControls();
646
647    event->readyToExecute();
648
649    SurfaceComposerClient::injectVSync(vSyncEvent.when());
650
651    return NO_ERROR;
652}
653
654void Replayer::createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event) {
655    ALOGV("Creating display");
656    event->readyToExecute();
657
658    std::lock_guard<std::mutex> lock(mDisplayLock);
659    sp<IBinder> display = SurfaceComposerClient::createDisplay(
660            String8(create.name().c_str()), create.is_secure());
661    mDisplays[create.id()] = display;
662
663    mDisplayCond.notify_all();
664
665    ALOGV("Done creating display");
666}
667
668void Replayer::deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event) {
669    ALOGV("Delete display");
670    event->readyToExecute();
671
672    std::lock_guard<std::mutex> lock(mDisplayLock);
673    SurfaceComposerClient::destroyDisplay(mDisplays[delete_.id()]);
674    mDisplays.erase(delete_.id());
675}
676
677void Replayer::updatePowerMode(const PowerModeUpdate& pmu, const std::shared_ptr<Event>& event) {
678    ALOGV("Updating power mode");
679    event->readyToExecute();
680    SurfaceComposerClient::setDisplayPowerMode(mDisplays[pmu.id()], pmu.mode());
681}
682
683void Replayer::waitUntilTimestamp(int64_t timestamp) {
684    ALOGV("Waiting for %lld nanoseconds...", static_cast<int64_t>(timestamp - mCurrentTime));
685    std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));
686}
687
688void Replayer::waitUntilDeferredTransactionLayerExists(
689        const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock) {
690    if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
691        mLayerCond.wait(lock, [&] { return (mLayers[dtc.layer_id()] != nullptr); });
692    }
693}
694
695status_t Replayer::loadSurfaceComposerClient() {
696    mComposerClient = new SurfaceComposerClient;
697    return mComposerClient->initCheck();
698}
699