Added Display increments, more controls, and a readme to the replayer
Change-Id: Id21144b7f808858149772de511951546fddfb252
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 950ebbb..ace10d1 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -22,6 +22,7 @@
#include <binder/IMemory.h>
+#include <gui/BufferQueue.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <private/gui/ComposerService.h>
@@ -40,15 +41,24 @@
#include <functional>
#include <iostream>
#include <mutex>
+#include <sstream>
#include <string>
#include <thread>
+#include <vector>
using namespace android;
std::atomic_bool Replayer::sReplayingManually(false);
-Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads)
- : mTrace(), mLoaded(false), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
+Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads, bool wait,
+ nsecs_t stopHere)
+ : mTrace(),
+ mLoaded(false),
+ mIncrementIndex(0),
+ mCurrentTime(0),
+ mNumThreads(numThreads),
+ mWaitForTimeStamps(wait),
+ mStopTimeStamp(stopHere) {
srand(RAND_COLOR_SEED);
std::fstream input(filename, std::ios::in | std::ios::binary);
@@ -62,19 +72,32 @@
mCurrentTime = mTrace.increment(0).time_stamp();
sReplayingManually.store(replayManually);
+
+ if (stopHere < 0) {
+ mHasStopped = true;
+ }
}
-Replayer::Replayer(const Trace& t, bool replayManually, int numThreads)
- : mTrace(t), mLoaded(true), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
+Replayer::Replayer(const Trace& t, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)
+ : mTrace(t),
+ mLoaded(true),
+ mIncrementIndex(0),
+ mCurrentTime(0),
+ mNumThreads(numThreads),
+ mWaitForTimeStamps(wait),
+ mStopTimeStamp(stopHere) {
srand(RAND_COLOR_SEED);
mCurrentTime = mTrace.increment(0).time_stamp();
sReplayingManually.store(replayManually);
+
+ if (stopHere < 0) {
+ mHasStopped = true;
+ }
}
status_t Replayer::replay() {
- // for manual control
- signal(SIGINT, Replayer::stopAutoReplayHandler);
+ signal(SIGINT, Replayer::stopAutoReplayHandler); //for manual control
ALOGV("There are %d increments.", mTrace.increment_size());
@@ -91,11 +114,18 @@
ALOGV("Starting actual Replay!");
while (!mPendingIncrements.empty()) {
+ mCurrentIncrement = mTrace.increment(mIncrementIndex);
+
+ if (mHasStopped == false && mCurrentIncrement.time_stamp() >= mStopTimeStamp) {
+ mHasStopped = true;
+ sReplayingManually.store(true);
+ }
+
waitForConsoleCommmand();
- auto pastIncrement = mTrace.increment(mIncrementIndex);
-
- waitUntilTimestamp(pastIncrement.time_stamp());
+ if (mWaitForTimeStamps) {
+ waitUntilTimestamp(mCurrentIncrement.time_stamp());
+ }
auto event = mPendingIncrements.front();
mPendingIncrements.pop();
@@ -116,7 +146,7 @@
}
mIncrementIndex++;
- mCurrentTime = pastIncrement.time_stamp();
+ mCurrentTime = mCurrentIncrement.time_stamp();
}
SurfaceComposerClient::enableVSyncInjections(false);
@@ -146,6 +176,21 @@
sReplayingManually.store(true);
}
+std::vector<std::string> split(const std::string& s, const char delim) {
+ std::vector<std::string> elems;
+ std::stringstream ss(s);
+ std::string item;
+ while (getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+
+bool isNumber(const std::string& s) {
+ return !s.empty() &&
+ std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
+}
+
void Replayer::waitForConsoleCommmand() {
if (!sReplayingManually || mWaitingForNextVSync) {
return;
@@ -158,18 +203,65 @@
if (input.empty()) {
input = mLastInput;
+ } else {
+ mLastInput = input;
}
- input = mLastInput;
- if (input == "n") { // next vsync
+ if (mLastInput.empty()) {
+ continue;
+ }
+
+ std::vector<std::string> inputs = split(input, ' ');
+
+ if (inputs[0] == "n") { // next vsync
mWaitingForNextVSync = true;
break;
- } else if (input == "c") { // continue
+
+ } else if (inputs[0] == "ni") { // next increment
+ break;
+
+ } else if (inputs[0] == "c") { // continue
+ if (inputs.size() > 1 && isNumber(inputs[1])) {
+ long milliseconds = stoi(inputs[1]);
+ std::thread([&] {
+ std::cout << "Started!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
+ sReplayingManually.store(true);
+ std::cout << "Should have stopped!" << std::endl;
+ }).detach();
+ }
sReplayingManually.store(false);
mWaitingForNextVSync = false;
break;
- } else if (input == "h") { // help
- // add help menu
+
+ } else if (inputs[0] == "s") { // stop at this timestamp
+ if (inputs.size() < 1) {
+ std::cout << "No time stamp given" << std::endl;
+ continue;
+ }
+ sReplayingManually.store(false);
+ mStopTimeStamp = stol(inputs[1]);
+ mHasStopped = false;
+ break;
+ } else if (inputs[0] == "l") { // list
+ std::cout << "Time stamp: " << mCurrentIncrement.time_stamp() << "\n";
+ continue;
+ } else if (inputs[0] == "q") { // quit
+ SurfaceComposerClient::enableVSyncInjections(false);
+ exit(0);
+
+ } else if (inputs[0] == "h") { // help
+ // add help menu
+ std::cout << "Manual Replay options:\n";
+ std::cout << " n - Go to next VSync\n";
+ std::cout << " ni - Go to next increment\n";
+ std::cout << " c - Continue\n";
+ std::cout << " c [milliseconds] - Continue until specified number of milliseconds\n";
+ std::cout << " s [timestamp] - Continue and stop at specified timestamp\n";
+ std::cout << " l - List out timestamp of current increment\n";
+ std::cout << " h - Display help menu\n";
+ std::cout << std::endl;
+ continue;
}
std::cout << "Invalid Command" << std::endl;
@@ -186,11 +278,13 @@
case increment.kTransaction: {
std::thread(&Replayer::doTransaction, this, increment.transaction(), event).detach();
} break;
- case increment.kCreate: {
- std::thread(&Replayer::createSurfaceControl, this, increment.create(), event).detach();
+ case increment.kSurfaceCreation: {
+ std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
+ .detach();
} break;
- case increment.kDelete: {
- std::thread(&Replayer::deleteSurfaceControl, this, increment.delete_(), event).detach();
+ case increment.kSurfaceDeletion: {
+ std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event)
+ .detach();
} break;
case increment.kBufferUpdate: {
std::lock_guard<std::mutex> lock1(mLayerLock);
@@ -216,6 +310,18 @@
case increment.kVsyncEvent: {
std::thread(&Replayer::injectVSyncEvent, this, increment.vsync_event(), event).detach();
} break;
+ case increment.kDisplayCreation: {
+ std::thread(&Replayer::createDisplay, this, increment.display_creation(), event)
+ .detach();
+ } break;
+ case increment.kDisplayDeletion: {
+ std::thread(&Replayer::deleteDisplay, this, increment.display_deletion(), event)
+ .detach();
+ } break;
+ case increment.kPowerModeUpdate: {
+ std::thread(&Replayer::updatePowerMode, this, increment.power_mode_update(), event)
+ .detach();
+ } break;
default:
ALOGE("Unknown Increment Type: %d", increment.increment_case());
status = BAD_VALUE;
@@ -228,83 +334,12 @@
status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
ALOGV("Started Transaction");
- if (t.change_size() == 0) {
- event->readyToExecute();
- return NO_ERROR;
- }
-
- Change change = t.change(0);
-
- std::unique_lock<std::mutex> lock(mLayerLock);
- if (mLayers[change.id()] == nullptr) {
- mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
- }
- lock.unlock();
-
SurfaceComposerClient::openGlobalTransaction();
status_t status = NO_ERROR;
- for (const Change& change : t.change()) {
- std::unique_lock<std::mutex> lock(mLayerLock);
- if (mLayers[change.id()] == nullptr) {
- mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
- }
-
- switch (change.Change_case()) {
- case Change::ChangeCase::kPosition:
- status = setPosition(change.id(), change.position());
- break;
- case Change::ChangeCase::kSize:
- status = setSize(change.id(), change.size());
- break;
- case Change::ChangeCase::kAlpha:
- status = setAlpha(change.id(), change.alpha());
- break;
- case Change::ChangeCase::kLayer:
- status = setLayer(change.id(), change.layer());
- break;
- case Change::ChangeCase::kCrop:
- status = setCrop(change.id(), change.crop());
- break;
- case Change::ChangeCase::kMatrix:
- status = setMatrix(change.id(), change.matrix());
- break;
- case Change::ChangeCase::kFinalCrop:
- status = setFinalCrop(change.id(), change.final_crop());
- break;
- case Change::ChangeCase::kOverrideScalingMode:
- status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
- break;
- case Change::ChangeCase::kTransparentRegionHint:
- status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
- break;
- case Change::ChangeCase::kLayerStack:
- status = setLayerStack(change.id(), change.layer_stack());
- break;
- case Change::ChangeCase::kHiddenFlag:
- status = setHiddenFlag(change.id(), change.hidden_flag());
- break;
- case Change::ChangeCase::kOpaqueFlag:
- status = setOpaqueFlag(change.id(), change.opaque_flag());
- break;
- case Change::ChangeCase::kSecureFlag:
- status = setSecureFlag(change.id(), change.secure_flag());
- break;
- case Change::ChangeCase::kDeferredTransaction:
- waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
- status = setDeferredTransaction(change.id(), change.deferred_transaction());
- break;
- default:
- status = NO_ERROR;
- break;
- }
-
- if (status != NO_ERROR) {
- ALOGE("SET TRANSACTION FAILED");
- return status;
- }
- }
+ status = doSurfaceTransaction(t.surface_change());
+ doDisplayTransaction(t.display_change());
if (t.animation()) {
SurfaceComposerClient::setAnimationTransaction();
@@ -319,27 +354,120 @@
return status;
}
-status_t Replayer::setPosition(uint32_t id, const PositionChange& pc) {
+status_t Replayer::doSurfaceTransaction(const SurfaceChanges& surfaceChanges) {
+ status_t status = NO_ERROR;
+
+ for (const SurfaceChange& change : surfaceChanges) {
+ std::unique_lock<std::mutex> lock(mLayerLock);
+ if (mLayers[change.id()] == nullptr) {
+ mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
+ }
+
+ switch (change.SurfaceChange_case()) {
+ case SurfaceChange::SurfaceChangeCase::kPosition:
+ status = setPosition(change.id(), change.position());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kSize:
+ status = setSize(change.id(), change.size());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kAlpha:
+ status = setAlpha(change.id(), change.alpha());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kLayer:
+ status = setLayer(change.id(), change.layer());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kCrop:
+ status = setCrop(change.id(), change.crop());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kMatrix:
+ status = setMatrix(change.id(), change.matrix());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kFinalCrop:
+ status = setFinalCrop(change.id(), change.final_crop());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
+ status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
+ status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kLayerStack:
+ status = setLayerStack(change.id(), change.layer_stack());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
+ status = setHiddenFlag(change.id(), change.hidden_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
+ status = setOpaqueFlag(change.id(), change.opaque_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kSecureFlag:
+ status = setSecureFlag(change.id(), change.secure_flag());
+ break;
+ case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
+ waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
+ status = setDeferredTransaction(change.id(), change.deferred_transaction());
+ break;
+ default:
+ status = NO_ERROR;
+ break;
+ }
+
+ if (status != NO_ERROR) {
+ ALOGE("SET TRANSACTION FAILED");
+ return status;
+ }
+ }
+ return status;
+}
+
+void Replayer::doDisplayTransaction(const DisplayChanges& displayChanges) {
+ for (const DisplayChange& change : displayChanges) {
+ ALOGV("Doing display transaction");
+ std::unique_lock<std::mutex> lock(mDisplayLock);
+ if (mDisplays[change.id()] == nullptr) {
+ mDisplayCond.wait(lock, [&] { return (mDisplays[change.id()] != nullptr); });
+ }
+
+ switch (change.DisplayChange_case()) {
+ case DisplayChange::DisplayChangeCase::kSurface:
+ setDisplaySurface(change.id(), change.surface());
+ break;
+ case DisplayChange::DisplayChangeCase::kLayerStack:
+ setDisplayLayerStack(change.id(), change.layer_stack());
+ break;
+ case DisplayChange::DisplayChangeCase::kSize:
+ setDisplaySize(change.id(), change.size());
+ break;
+ case DisplayChange::DisplayChangeCase::kProjection:
+ setDisplayProjection(change.id(), change.projection());
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+status_t Replayer::setPosition(layer_id id, const PositionChange& pc) {
ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
return mLayers[id]->setPosition(pc.x(), pc.y());
}
-status_t Replayer::setSize(uint32_t id, const SizeChange& sc) {
+status_t Replayer::setSize(layer_id id, const SizeChange& sc) {
ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
return mLayers[id]->setSize(sc.w(), sc.h());
}
-status_t Replayer::setLayer(uint32_t id, const LayerChange& lc) {
+status_t Replayer::setLayer(layer_id id, const LayerChange& lc) {
ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
return mLayers[id]->setLayer(lc.layer());
}
-status_t Replayer::setAlpha(uint32_t id, const AlphaChange& ac) {
+status_t Replayer::setAlpha(layer_id id, const AlphaChange& ac) {
ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
return mLayers[id]->setAlpha(ac.alpha());
}
-status_t Replayer::setCrop(uint32_t id, const CropChange& cc) {
+status_t Replayer::setCrop(layer_id id, const CropChange& cc) {
ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
cc.rectangle().bottom());
@@ -349,7 +477,7 @@
return mLayers[id]->setCrop(r);
}
-status_t Replayer::setFinalCrop(uint32_t id, const FinalCropChange& fcc) {
+status_t Replayer::setFinalCrop(layer_id id, const FinalCropChange& fcc) {
ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
fcc.rectangle().bottom());
@@ -358,18 +486,18 @@
return mLayers[id]->setFinalCrop(r);
}
-status_t Replayer::setMatrix(uint32_t id, const MatrixChange& mc) {
+status_t Replayer::setMatrix(layer_id id, const MatrixChange& mc) {
ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
mc.dtdx(), mc.dsdy(), mc.dtdy());
return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
}
-status_t Replayer::setOverrideScalingMode(uint32_t id, const OverrideScalingModeChange& osmc) {
+status_t Replayer::setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc) {
ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
}
-status_t Replayer::setTransparentRegionHint(uint32_t id, const TransparentRegionHintChange& trhc) {
+status_t Replayer::setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trhc) {
ALOGV("Setting Transparent Region Hint");
Region re = Region();
@@ -381,33 +509,33 @@
return mLayers[id]->setTransparentRegionHint(re);
}
-status_t Replayer::setLayerStack(uint32_t id, const LayerStackChange& lsc) {
+status_t Replayer::setLayerStack(layer_id id, const LayerStackChange& lsc) {
ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
return mLayers[id]->setLayerStack(lsc.layer_stack());
}
-status_t Replayer::setHiddenFlag(uint32_t id, const HiddenFlagChange& hfc) {
+status_t Replayer::setHiddenFlag(layer_id id, const HiddenFlagChange& hfc) {
ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
- uint32_t flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
+ layer_id flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
}
-status_t Replayer::setOpaqueFlag(uint32_t id, const OpaqueFlagChange& ofc) {
+status_t Replayer::setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc) {
ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
- uint32_t flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
+ layer_id flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
}
-status_t Replayer::setSecureFlag(uint32_t id, const SecureFlagChange& sfc) {
+status_t Replayer::setSecureFlag(layer_id id, const SecureFlagChange& sfc) {
ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
- uint32_t flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
+ layer_id flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
}
-status_t Replayer::setDeferredTransaction(uint32_t id, const DeferredTransactionChange& dtc) {
+status_t Replayer::setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc) {
ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
"frame_number=%llu",
id, dtc.layer_id(), dtc.frame_number());
@@ -421,7 +549,32 @@
return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
}
-status_t Replayer::createSurfaceControl(const Create& create, const std::shared_ptr<Event>& event) {
+void Replayer::setDisplaySurface(display_id id, const DispSurfaceChange& /*dsc*/) {
+ sp<IGraphicBufferProducer> outProducer;
+ sp<IGraphicBufferConsumer> outConsumer;
+ BufferQueue::createBufferQueue(&outProducer, &outConsumer);
+
+ SurfaceComposerClient::setDisplaySurface(mDisplays[id], outProducer);
+}
+
+void Replayer::setDisplayLayerStack(display_id id, const LayerStackChange& lsc) {
+ SurfaceComposerClient::setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
+}
+
+void Replayer::setDisplaySize(display_id id, const SizeChange& sc) {
+ SurfaceComposerClient::setDisplaySize(mDisplays[id], sc.w(), sc.h());
+}
+
+void Replayer::setDisplayProjection(display_id id, const ProjectionChange& pc) {
+ Rect viewport = Rect(pc.viewport().left(), pc.viewport().top(), pc.viewport().right(),
+ pc.viewport().bottom());
+ Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom());
+
+ SurfaceComposerClient::setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame);
+}
+
+status_t Replayer::createSurfaceControl(
+ const SurfaceCreation& create, const std::shared_ptr<Event>& event) {
event->readyToExecute();
ALOGV("Creating Surface Control: ID: %d", create.id());
@@ -437,7 +590,7 @@
auto& layer = mLayers[create.id()];
layer = surfaceControl;
- mColors[create.id()] = HSVToRGB(HSV(rand() % 360, 1, 1));
+ mColors[create.id()] = HSV(rand() % 360, 1, 1);
mLayerCond.notify_all();
@@ -451,7 +604,7 @@
}
status_t Replayer::deleteSurfaceControl(
- const Delete& delete_, const std::shared_ptr<Event>& event) {
+ const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) {
ALOGV("Deleting %d Surface Control", delete_.id());
event->readyToExecute();
@@ -459,13 +612,15 @@
mLayersPendingRemoval.push_back(delete_.id());
- auto iterator = mBufferQueueSchedulers.find(delete_.id());
+ const auto& iterator = mBufferQueueSchedulers.find(delete_.id());
if (iterator != mBufferQueueSchedulers.end()) {
(*iterator).second->stopScheduling();
}
std::lock_guard<std::mutex> lock2(mLayerLock);
- mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
+ if (mLayers[delete_.id()] != nullptr) {
+ mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
+ }
return NO_ERROR;
}
@@ -496,6 +651,35 @@
return NO_ERROR;
}
+void Replayer::createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event) {
+ ALOGV("Creating display");
+ event->readyToExecute();
+
+ std::lock_guard<std::mutex> lock(mDisplayLock);
+ sp<IBinder> display = SurfaceComposerClient::createDisplay(
+ String8(create.name().c_str()), create.is_secure());
+ mDisplays[create.id()] = display;
+
+ mDisplayCond.notify_all();
+
+ ALOGV("Done creating display");
+}
+
+void Replayer::deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event) {
+ ALOGV("Delete display");
+ event->readyToExecute();
+
+ std::lock_guard<std::mutex> lock(mDisplayLock);
+ SurfaceComposerClient::destroyDisplay(mDisplays[delete_.id()]);
+ mDisplays.erase(delete_.id());
+}
+
+void Replayer::updatePowerMode(const PowerModeUpdate& pmu, const std::shared_ptr<Event>& event) {
+ ALOGV("Updating power mode");
+ event->readyToExecute();
+ SurfaceComposerClient::setDisplayPowerMode(mDisplays[pmu.id()], pmu.mode());
+}
+
void Replayer::waitUntilTimestamp(int64_t timestamp) {
ALOGV("Waiting for %lld nanoseconds...", static_cast<int64_t>(timestamp - mCurrentTime));
std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));