Home | History | Annotate | only in /frameworks/native/cmds/surfacereplayer/replayer
Up to higher level directory
NameDateSize
Android.bp21-Aug-20181.2K
BufferQueueScheduler.cpp21-Aug-20183.3K
BufferQueueScheduler.h21-Aug-20182.1K
Color.h21-Aug-20182.6K
Event.cpp21-Aug-20181.4K
Event.h21-Aug-20181.6K
Main.cpp21-Aug-20183.3K
README.md21-Aug-201810K
Replayer.cpp21-Aug-201825.1K
Replayer.h21-Aug-20186.3K
trace_creator/21-Aug-2018

README.md

      1 SurfaceReplayer Documentation
      2 ===================
      3 
      4 [go/SurfaceReplayer](go/SurfaceReplayer)
      5 
      6 SurfaceReplayer is a playback mechanism that allows the replaying of traces recorded by
      7 [SurfaceInterceptor](go/SurfaceInterceptor) from SurfaceFlinger. It specifically replays
      8 
      9 * Creation and deletion of surfaces/displays
     10 * Alterations to the surfaces/displays called Transactions
     11 * Buffer Updates to surfaces
     12 * VSync events
     13 
     14 At their specified times to be as close to the original trace.
     15 
     16 Usage
     17 --------
     18 
     19 ###Creating a trace
     20 
     21 SurfaceInterceptor is the mechanism used to create traces. The device needs to be rooted in order to
     22 utilize it. To allow it to write to the device, run
     23 
     24 `setenforce 0`
     25 
     26 To start recording a trace, run
     27 
     28 `service call SurfaceFlinger 1020 i32 1`
     29 
     30 To stop recording, run
     31 
     32 `service call SurfaceFlinger 1020 i32 0`
     33 
     34 The default location for the trace is `/data/SurfaceTrace.dat`
     35 
     36 ###Executable
     37 
     38 To replay a specific trace, execute
     39 
     40 `/data/local/tmp/surfacereplayer /absolute/path/to/trace`
     41 
     42 inside the android shell. This will replay the full trace and then exit. Running this command
     43 outside of the shell by prepending `adb shell` will not allow for manual control and will not turn
     44 off VSync injections if it interrupted in any way other than fully replaying the trace
     45 
     46 The replay will not fill surfaces with their contents during the capture. Rather they are given a
     47 random color which will be the same every time the trace is replayed. Surfaces modulate their color
     48 at buffer updates.
     49 
     50 **Options:**
     51 
     52 - -m    pause the replayer at the start of the trace for manual replay
     53 - -t [Number of Threads] uses specified number of threads to queue up actions (default is 3)
     54 - -s [Timestamp] switches to manual replay at specified timestamp
     55 - -n    Ignore timestamps and run through trace as fast as possible
     56 - -l    Indefinitely loop the replayer
     57 - -h    displays help menu
     58 
     59 **Manual Replay:**
     60 When replaying, if the user presses CTRL-C, the replay will stop and can be manually controlled
     61 by the user. Pressing CTRL-C again will exit the replayer.
     62 
     63 Manual replaying is similar to debugging in gdb. A prompt is presented and the user is able to
     64 input commands to choose how to proceed by hitting enter after inputting a command. Pressing enter
     65 without inputting a command repeats the previous command.
     66 
     67 - n  - steps the replayer to the next VSync event
     68 - ni - steps the replayer to the next increment
     69 - c  - continues normal replaying
     70 - c [milliseconds] - continue until specified number of milliseconds have passed
     71 - s [timestamp]    - continue and stop at specified timestamp
     72 - l  - list out timestamp of current increment
     73 - h  - displays help menu
     74 
     75 ###Shared Library
     76 
     77 To use the shared library include these shared libraries
     78 
     79 `libsurfacereplayer`
     80 `libprotobuf-cpp-full`
     81 `libutils`
     82 
     83 And the static library
     84 
     85 `libtrace_proto`
     86 
     87 Include the replayer header at the top of your file
     88 
     89 `#include <replayer/Replayer.h>`
     90 
     91 There are two constructors for the replayer
     92 
     93 `Replayer(std::string& filename, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)`
     94 `Replayer(Trace& trace, ... ditto ...)`
     95 
     96 The first constructor takes in the filepath where the trace is located and loads in the trace
     97 object internally.
     98 - replayManually - **True**: if the replayer will immediately switch to manual replay at the start
     99 - numThreads - Number of worker threads the replayer will use.
    100 - wait - **False**: Replayer ignores waits in between increments
    101 - stopHere - Time stamp of where the replayer should run to then switch to manual replay
    102 
    103 The second constructor includes all of the same parameters but takes in a preloaded trace object.
    104 To use add
    105 
    106 `#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>`
    107 
    108 To your file
    109 
    110 After initializing the Replayer call
    111 
    112     replayer.replay();
    113 
    114 And the trace will start replaying. Once the trace is finished replaying, the function will return.
    115 The layers that are visible at the end of the trace will remain on screen until the program
    116 terminates.
    117 
    118 
    119 **If VSyncs are broken after running the replayer** that means `enableVSyncInjections(false)` was
    120 never executed. This can be fixed by executing
    121 
    122 `service call SurfaceFlinger 23 i32 0`
    123 
    124 in the android shell
    125 
    126 Code Breakdown
    127 -------------
    128 
    129 The Replayer is composed of 5 components.
    130 
    131 - The data format of the trace (Trace.proto)
    132 - The Replayer object (Replayer.cpp)
    133 - The synchronization mechanism to signal threads within the Replayer (Event.cpp)
    134 - The scheduler for buffer updates per surface (BufferQueueScheduler.cpp)
    135 - The Main executable (Main.cpp)
    136 
    137 ### Traces
    138 
    139 Traces are represented as a protobuf message located in surfacereplayer/proto/src.
    140 
    141 **Traces** contain *repeated* **Increments** (events that have occurred in SurfaceFlinger).
    142 **Increments** contain the time stamp of when it occurred and a *oneof* which can be a
    143 
    144  - Transaction
    145  - SurfaceCreation
    146  - SurfaceDeletion
    147  - DisplayCreation
    148  - DisplayDeleteion
    149  - BufferUpdate
    150  - VSyncEvent
    151  - PowerModeUpdate
    152 
    153 **Transactions** contain whether the transaction was synchronous or animated and *repeated*
    154 **SurfaceChanges** and **DisplayChanges**
    155 
    156 - **SurfaceChanges** contain an id of the surface being manipulated and can be changes such as
    157 position, alpha, hidden, size, etc.
    158 - **DisplayChanges** contain the id of the display being manipulated and can be changes such as
    159 size, layer stack, projection, etc.
    160 
    161 **Surface/Display Creation** contain the id of the surface/display and the name of the
    162 surface/display
    163 
    164 **Surface/Display Deletion** contain the id of the surface/display to be deleted
    165 
    166 **Buffer Updates** contain the id of the surface who's buffer is being updated, the size of the
    167 buffer, and the frame number.
    168 
    169 **VSyncEvents** contain when the VSync event has occurred.
    170 
    171 **PowerModeUpdates** contain the id of the display being updated and what mode it is being
    172 changed to.
    173 
    174 To output the contents of a trace in a readable format, execute
    175 
    176 `**aprotoc** --decode=Trace \
    177 -I=$ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src \
    178 $ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src/trace.proto \
    179  < **YourTraceFile.dat** > **YourOutputName.txt**`
    180 
    181 
    182 ###Replayer
    183 
    184 Fundamentally the replayer loads a trace and iterates through each increment, waiting the required
    185 amount of time until the increment should be executed, then executing the increment. The first
    186 increment in a trace does not start at 0, rather the replayer treats its time stamp as time 0 and
    187 goes from there.
    188 
    189 Increments from the trace are played asynchronously rather than one by one, being dispatched by
    190 the main thread, queued up in a thread pool and completed when the main thread deems they are
    191 ready to finish execution.
    192 
    193 When an increment is dispatched, it completes as much work as it can before it has to be
    194 synchronized (e.g. prebaking a buffer for a BufferUpdate). When it gets to a critical action
    195 (e.g. locking and pushing a buffer), it waits for the main thread to complete it using an Event
    196 object. The main thread holds a queue of these Event objects and completes the
    197 corresponding Event base on its time stamp. After completing an increment, the main thread will
    198 dispatch another increment and continue.
    199 
    200 The main thread's execution flow is outlined below
    201 
    202     initReplay() //queue up the initial increments
    203     while(!pendingIncrements.empty()) { //while increments remaining
    204         event = pendingIncrement.pop();
    205         wait(event.time_stamp(); //waitUntil it is time to complete this increment
    206 
    207         event.complete() //signal to let event finish
    208         if(increments remaing()) {
    209             dispatchEvent() //queue up another increment
    210         }
    211     }
    212 
    213 A worker thread's flow looks like so
    214 
    215     //dispatched!
    216     Execute non-time sensitive work here
    217     ...
    218     event.readyToExecute() //time sensitive point...waiting for Main Thread
    219     ...
    220     Finish execution
    221 
    222 
    223 ### Event
    224 
    225 An Event is a simple synchronization mechanism used to facilitate communication between the main
    226 and worker threads. Every time an increment is dispatched, an Event object is also created.
    227 
    228 An Event can be in 4 different states:
    229 
    230 - **SettingUp** - The worker is in the process of completing all non-time sensitive work
    231 - **Waiting** - The worker is waiting on the main thread to signal it.
    232 - **Signaled** - The worker has just been signaled by the main thread
    233 - **Running** - The worker is running again and finishing the rest of its work.
    234 
    235 When the main thread wants to finish the execution of a worker, the worker can either still be
    236 **SettingUp**, in which the main thread will wait, or the worker will be **Waiting**, in which the
    237 main thread will **Signal** it to complete. The worker thread changes itself to the **Running**
    238 state once **Signaled**. This last step exists in order to communicate back to the main thread that
    239 the worker thread has actually started completing its execution, rather than being preempted right
    240 after signalling. Once this happens, the main thread schedules the next worker. This makes sure
    241 there is a constant amount of workers running at one time.
    242 
    243 This activity is encapsulated in the `readyToExecute()` and `complete()` functions called by the
    244 worker and main thread respectively.
    245 
    246 ### BufferQueueScheduler
    247 
    248 During a **BuferUpdate**, the worker thread will wait until **Signaled** to unlock and post a
    249 buffer that has been prefilled during the **SettingUp** phase. However if there are two sequential
    250 **BufferUpdates** that act on the same surface, both threads will try to lock a buffer and fill it,
    251 which isn't possible and will cause a deadlock. The BufferQueueScheduler solves this problem by
    252 handling when **BufferUpdates** should be scheduled, making sure that they don't overlap.
    253 
    254 When a surface is created, a BufferQueueScheduler is also created along side it. Whenever a
    255 **BufferUpdate** is read, it schedules the event onto its own internal queue and then schedules one
    256 every time an Event is completed.
    257 
    258 ### Main
    259 
    260 The main exectuable reads in the command line arguments. Creates the Replayer using those
    261 arguments. Executes `replay()` on the Replayer. If there are no errors while replaying it will exit
    262 gracefully, if there are then it will report the error and then exit.
    263