blob: 950ebbba5d606bc5d3a7eaab19b69fa95a25604b [file] [log] [blame]
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -07001/* 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/ISurfaceComposer.h>
26#include <gui/Surface.h>
27#include <private/gui/ComposerService.h>
28#include <private/gui/LayerState.h>
29
30#include <ui/DisplayInfo.h>
31#include <utils/Log.h>
32#include <utils/String8.h>
33#include <utils/Trace.h>
34
35#include <chrono>
36#include <cmath>
37#include <condition_variable>
38#include <cstdlib>
39#include <fstream>
40#include <functional>
41#include <iostream>
42#include <mutex>
43#include <string>
44#include <thread>
45
46using namespace android;
47
48std::atomic_bool Replayer::sReplayingManually(false);
49
50Replayer::Replayer(const std::string& filename, bool replayManually, int numThreads)
51 : mTrace(), mLoaded(false), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
52 srand(RAND_COLOR_SEED);
53
54 std::fstream input(filename, std::ios::in | std::ios::binary);
55
56 mLoaded = mTrace.ParseFromIstream(&input);
57 if (!mLoaded) {
58 std::cerr << "Trace did not load. Does " << filename << " exist?" << std::endl;
59 abort();
60 }
61
62 mCurrentTime = mTrace.increment(0).time_stamp();
63
64 sReplayingManually.store(replayManually);
65}
66
67Replayer::Replayer(const Trace& t, bool replayManually, int numThreads)
68 : mTrace(t), mLoaded(true), mIncrementIndex(0), mCurrentTime(0), mNumThreads(numThreads) {
69 srand(RAND_COLOR_SEED);
70 mCurrentTime = mTrace.increment(0).time_stamp();
71
72 sReplayingManually.store(replayManually);
73}
74
75status_t Replayer::replay() {
76 // for manual control
77 signal(SIGINT, Replayer::stopAutoReplayHandler);
78
79 ALOGV("There are %d increments.", mTrace.increment_size());
80
81 status_t status = loadSurfaceComposerClient();
82
83 if (status != NO_ERROR) {
84 ALOGE("Couldn't create SurfaceComposerClient (%d)", status);
85 return status;
86 }
87
88 SurfaceComposerClient::enableVSyncInjections(true);
89
90 initReplay();
91
92 ALOGV("Starting actual Replay!");
93 while (!mPendingIncrements.empty()) {
94 waitForConsoleCommmand();
95
96 auto pastIncrement = mTrace.increment(mIncrementIndex);
97
98 waitUntilTimestamp(pastIncrement.time_stamp());
99
100 auto event = mPendingIncrements.front();
101 mPendingIncrements.pop();
102
103 event->complete();
104
105 if (event->getIncrementType() == Increment::kVsyncEvent) {
106 mWaitingForNextVSync = false;
107 }
108
109 if (mIncrementIndex + mNumThreads < mTrace.increment_size()) {
110 status = dispatchEvent(mIncrementIndex + mNumThreads);
111
112 if (status != NO_ERROR) {
113 SurfaceComposerClient::enableVSyncInjections(false);
114 return status;
115 }
116 }
117
118 mIncrementIndex++;
119 mCurrentTime = pastIncrement.time_stamp();
120 }
121
122 SurfaceComposerClient::enableVSyncInjections(false);
123
124 return status;
125}
126
127status_t Replayer::initReplay() {
128 for (int i = 0; i < mNumThreads && i < mTrace.increment_size(); i++) {
129 status_t status = dispatchEvent(i);
130
131 if (status != NO_ERROR) {
132 ALOGE("Unable to dispatch event (%d)", status);
133 return status;
134 }
135 }
136
137 return NO_ERROR;
138}
139
140void Replayer::stopAutoReplayHandler(int /*signal*/) {
141 if (sReplayingManually) {
142 SurfaceComposerClient::enableVSyncInjections(false);
143 exit(0);
144 }
145
146 sReplayingManually.store(true);
147}
148
149void Replayer::waitForConsoleCommmand() {
150 if (!sReplayingManually || mWaitingForNextVSync) {
151 return;
152 }
153
154 while (true) {
155 std::string input = "";
156 std::cout << "> ";
157 getline(std::cin, input);
158
159 if (input.empty()) {
160 input = mLastInput;
161 }
162
163 input = mLastInput;
164 if (input == "n") { // next vsync
165 mWaitingForNextVSync = true;
166 break;
167 } else if (input == "c") { // continue
168 sReplayingManually.store(false);
169 mWaitingForNextVSync = false;
170 break;
171 } else if (input == "h") { // help
172 // add help menu
173 }
174
175 std::cout << "Invalid Command" << std::endl;
176 }
177}
178
179status_t Replayer::dispatchEvent(int index) {
180 auto increment = mTrace.increment(index);
181 std::shared_ptr<Event> event = std::make_shared<Event>(increment.increment_case());
182 mPendingIncrements.push(event);
183
184 status_t status = NO_ERROR;
185 switch (increment.increment_case()) {
186 case increment.kTransaction: {
187 std::thread(&Replayer::doTransaction, this, increment.transaction(), event).detach();
188 } break;
189 case increment.kCreate: {
190 std::thread(&Replayer::createSurfaceControl, this, increment.create(), event).detach();
191 } break;
192 case increment.kDelete: {
193 std::thread(&Replayer::deleteSurfaceControl, this, increment.delete_(), event).detach();
194 } break;
195 case increment.kBufferUpdate: {
196 std::lock_guard<std::mutex> lock1(mLayerLock);
197 std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
198
199 Dimensions dimensions(increment.buffer_update().w(), increment.buffer_update().h());
200 BufferEvent bufferEvent(event, dimensions);
201
202 auto layerId = increment.buffer_update().id();
203 if (mBufferQueueSchedulers.count(layerId) == 0) {
204 mBufferQueueSchedulers[layerId] = std::make_shared<BufferQueueScheduler>(
205 mLayers[layerId], mColors[layerId], layerId);
206 mBufferQueueSchedulers[layerId]->addEvent(bufferEvent);
207
208 std::thread(&BufferQueueScheduler::startScheduling,
209 mBufferQueueSchedulers[increment.buffer_update().id()].get())
210 .detach();
211 } else {
212 auto bqs = mBufferQueueSchedulers[increment.buffer_update().id()];
213 bqs->addEvent(bufferEvent);
214 }
215 } break;
216 case increment.kVsyncEvent: {
217 std::thread(&Replayer::injectVSyncEvent, this, increment.vsync_event(), event).detach();
218 } break;
219 default:
220 ALOGE("Unknown Increment Type: %d", increment.increment_case());
221 status = BAD_VALUE;
222 break;
223 }
224
225 return status;
226}
227
228status_t Replayer::doTransaction(const Transaction& t, const std::shared_ptr<Event>& event) {
229 ALOGV("Started Transaction");
230
231 if (t.change_size() == 0) {
232 event->readyToExecute();
233 return NO_ERROR;
234 }
235
236 Change change = t.change(0);
237
238 std::unique_lock<std::mutex> lock(mLayerLock);
239 if (mLayers[change.id()] == nullptr) {
240 mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
241 }
242 lock.unlock();
243
244 SurfaceComposerClient::openGlobalTransaction();
245
246 status_t status = NO_ERROR;
247
248 for (const Change& change : t.change()) {
249 std::unique_lock<std::mutex> lock(mLayerLock);
250 if (mLayers[change.id()] == nullptr) {
251 mLayerCond.wait(lock, [&] { return (mLayers[change.id()] != nullptr); });
252 }
253
254 switch (change.Change_case()) {
255 case Change::ChangeCase::kPosition:
256 status = setPosition(change.id(), change.position());
257 break;
258 case Change::ChangeCase::kSize:
259 status = setSize(change.id(), change.size());
260 break;
261 case Change::ChangeCase::kAlpha:
262 status = setAlpha(change.id(), change.alpha());
263 break;
264 case Change::ChangeCase::kLayer:
265 status = setLayer(change.id(), change.layer());
266 break;
267 case Change::ChangeCase::kCrop:
268 status = setCrop(change.id(), change.crop());
269 break;
270 case Change::ChangeCase::kMatrix:
271 status = setMatrix(change.id(), change.matrix());
272 break;
273 case Change::ChangeCase::kFinalCrop:
274 status = setFinalCrop(change.id(), change.final_crop());
275 break;
276 case Change::ChangeCase::kOverrideScalingMode:
277 status = setOverrideScalingMode(change.id(), change.override_scaling_mode());
278 break;
279 case Change::ChangeCase::kTransparentRegionHint:
280 status = setTransparentRegionHint(change.id(), change.transparent_region_hint());
281 break;
282 case Change::ChangeCase::kLayerStack:
283 status = setLayerStack(change.id(), change.layer_stack());
284 break;
285 case Change::ChangeCase::kHiddenFlag:
286 status = setHiddenFlag(change.id(), change.hidden_flag());
287 break;
288 case Change::ChangeCase::kOpaqueFlag:
289 status = setOpaqueFlag(change.id(), change.opaque_flag());
290 break;
291 case Change::ChangeCase::kSecureFlag:
292 status = setSecureFlag(change.id(), change.secure_flag());
293 break;
294 case Change::ChangeCase::kDeferredTransaction:
295 waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock);
296 status = setDeferredTransaction(change.id(), change.deferred_transaction());
297 break;
298 default:
299 status = NO_ERROR;
300 break;
301 }
302
303 if (status != NO_ERROR) {
304 ALOGE("SET TRANSACTION FAILED");
305 return status;
306 }
307 }
308
309 if (t.animation()) {
310 SurfaceComposerClient::setAnimationTransaction();
311 }
312
313 event->readyToExecute();
314
315 SurfaceComposerClient::closeGlobalTransaction(t.synchronous());
316
317 ALOGV("Ended Transaction");
318
319 return status;
320}
321
322status_t Replayer::setPosition(uint32_t id, const PositionChange& pc) {
323 ALOGV("Layer %d: Setting Position -- x=%f, y=%f", id, pc.x(), pc.y());
324 return mLayers[id]->setPosition(pc.x(), pc.y());
325}
326
327status_t Replayer::setSize(uint32_t id, const SizeChange& sc) {
328 ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
329 return mLayers[id]->setSize(sc.w(), sc.h());
330}
331
332status_t Replayer::setLayer(uint32_t id, const LayerChange& lc) {
333 ALOGV("Layer %d: Setting Layer -- layer=%d", id, lc.layer());
334 return mLayers[id]->setLayer(lc.layer());
335}
336
337status_t Replayer::setAlpha(uint32_t id, const AlphaChange& ac) {
338 ALOGV("Layer %d: Setting Alpha -- alpha=%f", id, ac.alpha());
339 return mLayers[id]->setAlpha(ac.alpha());
340}
341
342status_t Replayer::setCrop(uint32_t id, const CropChange& cc) {
343 ALOGV("Layer %d: Setting Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
344 cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
345 cc.rectangle().bottom());
346
347 Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(),
348 cc.rectangle().bottom());
349 return mLayers[id]->setCrop(r);
350}
351
352status_t Replayer::setFinalCrop(uint32_t id, const FinalCropChange& fcc) {
353 ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
354 fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
355 fcc.rectangle().bottom());
356 Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
357 fcc.rectangle().bottom());
358 return mLayers[id]->setFinalCrop(r);
359}
360
361status_t Replayer::setMatrix(uint32_t id, const MatrixChange& mc) {
362 ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
363 mc.dtdx(), mc.dsdy(), mc.dtdy());
364 return mLayers[id]->setMatrix(mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy());
365}
366
367status_t Replayer::setOverrideScalingMode(uint32_t id, const OverrideScalingModeChange& osmc) {
368 ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode());
369 return mLayers[id]->setOverrideScalingMode(osmc.override_scaling_mode());
370}
371
372status_t Replayer::setTransparentRegionHint(uint32_t id, const TransparentRegionHintChange& trhc) {
373 ALOGV("Setting Transparent Region Hint");
374 Region re = Region();
375
376 for (auto r : trhc.region()) {
377 Rect rect = Rect(r.left(), r.top(), r.right(), r.bottom());
378 re.merge(rect);
379 }
380
381 return mLayers[id]->setTransparentRegionHint(re);
382}
383
384status_t Replayer::setLayerStack(uint32_t id, const LayerStackChange& lsc) {
385 ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
386 return mLayers[id]->setLayerStack(lsc.layer_stack());
387}
388
389status_t Replayer::setHiddenFlag(uint32_t id, const HiddenFlagChange& hfc) {
390 ALOGV("Layer %d: Setting Hidden Flag -- hidden_flag=%d", id, hfc.hidden_flag());
391 uint32_t flag = hfc.hidden_flag() ? layer_state_t::eLayerHidden : 0;
392
393 return mLayers[id]->setFlags(flag, layer_state_t::eLayerHidden);
394}
395
396status_t Replayer::setOpaqueFlag(uint32_t id, const OpaqueFlagChange& ofc) {
397 ALOGV("Layer %d: Setting Opaque Flag -- opaque_flag=%d", id, ofc.opaque_flag());
398 uint32_t flag = ofc.opaque_flag() ? layer_state_t::eLayerOpaque : 0;
399
400 return mLayers[id]->setFlags(flag, layer_state_t::eLayerOpaque);
401}
402
403status_t Replayer::setSecureFlag(uint32_t id, const SecureFlagChange& sfc) {
404 ALOGV("Layer %d: Setting Secure Flag -- secure_flag=%d", id, sfc.secure_flag());
405 uint32_t flag = sfc.secure_flag() ? layer_state_t::eLayerSecure : 0;
406
407 return mLayers[id]->setFlags(flag, layer_state_t::eLayerSecure);
408}
409
410status_t Replayer::setDeferredTransaction(uint32_t id, const DeferredTransactionChange& dtc) {
411 ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, "
412 "frame_number=%llu",
413 id, dtc.layer_id(), dtc.frame_number());
414 if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
415 ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id());
416 return BAD_VALUE;
417 }
418
419 auto handle = mLayers[dtc.layer_id()]->getHandle();
420
421 return mLayers[id]->deferTransactionUntil(handle, dtc.frame_number());
422}
423
424status_t Replayer::createSurfaceControl(const Create& create, const std::shared_ptr<Event>& event) {
425 event->readyToExecute();
426
427 ALOGV("Creating Surface Control: ID: %d", create.id());
428 sp<SurfaceControl> surfaceControl = mComposerClient->createSurface(
429 String8(create.name().c_str()), create.w(), create.h(), PIXEL_FORMAT_RGBA_8888, 0);
430
431 if (surfaceControl == nullptr) {
432 ALOGE("CreateSurfaceControl: unable to create surface control");
433 return BAD_VALUE;
434 }
435
436 std::lock_guard<std::mutex> lock1(mLayerLock);
437 auto& layer = mLayers[create.id()];
438 layer = surfaceControl;
439
440 mColors[create.id()] = HSVToRGB(HSV(rand() % 360, 1, 1));
441
442 mLayerCond.notify_all();
443
444 std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
445 if (mBufferQueueSchedulers.count(create.id()) != 0) {
446 mBufferQueueSchedulers[create.id()]->setSurfaceControl(
447 mLayers[create.id()], mColors[create.id()]);
448 }
449
450 return NO_ERROR;
451}
452
453status_t Replayer::deleteSurfaceControl(
454 const Delete& delete_, const std::shared_ptr<Event>& event) {
455 ALOGV("Deleting %d Surface Control", delete_.id());
456 event->readyToExecute();
457
458 std::lock_guard<std::mutex> lock1(mPendingLayersLock);
459
460 mLayersPendingRemoval.push_back(delete_.id());
461
462 auto iterator = mBufferQueueSchedulers.find(delete_.id());
463 if (iterator != mBufferQueueSchedulers.end()) {
464 (*iterator).second->stopScheduling();
465 }
466
467 std::lock_guard<std::mutex> lock2(mLayerLock);
468 mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
469
470 return NO_ERROR;
471}
472
473void Replayer::doDeleteSurfaceControls() {
474 std::lock_guard<std::mutex> lock1(mPendingLayersLock);
475 std::lock_guard<std::mutex> lock2(mLayerLock);
476 if (!mLayersPendingRemoval.empty()) {
477 for (int id : mLayersPendingRemoval) {
478 mLayers.erase(id);
479 mColors.erase(id);
480 mBufferQueueSchedulers.erase(id);
481 }
482 mLayersPendingRemoval.clear();
483 }
484}
485
486status_t Replayer::injectVSyncEvent(
487 const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) {
488 ALOGV("Injecting VSync Event");
489
490 doDeleteSurfaceControls();
491
492 event->readyToExecute();
493
494 SurfaceComposerClient::injectVSync(vSyncEvent.when());
495
496 return NO_ERROR;
497}
498
499void Replayer::waitUntilTimestamp(int64_t timestamp) {
500 ALOGV("Waiting for %lld nanoseconds...", static_cast<int64_t>(timestamp - mCurrentTime));
501 std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime));
502}
503
504void Replayer::waitUntilDeferredTransactionLayerExists(
505 const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock) {
506 if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) {
507 mLayerCond.wait(lock, [&] { return (mLayers[dtc.layer_id()] != nullptr); });
508 }
509}
510
511status_t Replayer::loadSurfaceComposerClient() {
512 mComposerClient = new SurfaceComposerClient;
513 return mComposerClient->initCheck();
514}