Merge "Fix vector read buffer size."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5fe4835..eddb989 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -36,6 +36,7 @@
 
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <android-base/file.h>
 #include <cutils/properties.h>
 
 #include "private/android_filesystem_config.h"
@@ -184,6 +185,118 @@
     closedir(d);
 }
 
+// return pid of a userspace process. If not found or error, return 0.
+static unsigned int pid_of_process(const char* ps_name) {
+    DIR *proc_dir;
+    struct dirent *ps;
+    unsigned int pid;
+    std::string cmdline;
+
+    if (!(proc_dir = opendir("/proc"))) {
+        MYLOGE("Can't open /proc\n");
+        return 0;
+    }
+
+    while ((ps = readdir(proc_dir))) {
+        if (!(pid = atoi(ps->d_name))) {
+            continue;
+        }
+        android::base::ReadFileToString("/proc/"
+                + std::string(ps->d_name) + "/cmdline", &cmdline);
+        if (cmdline.find(ps_name) == std::string::npos) {
+            continue;
+        } else {
+            closedir(proc_dir);
+            return pid;
+        }
+    }
+    closedir(proc_dir);
+    return 0;
+}
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+    unsigned int pid;
+    char buf[50], path[PATH_MAX];
+    struct dirent *trace;
+    struct stat st;
+    DIR *trace_dir;
+    long max_ctime = 0;
+    long long cur_size = 0;
+    const char *trace_path = "/data/misc/anrd/";
+
+    if (!zip_writer) {
+        MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
+        return false;
+    }
+
+    // find anrd's pid if it is running.
+    pid = pid_of_process("/system/xbin/anrd");
+
+    if (pid > 0) {
+        // send SIGUSR1 to the anrd to generate a trace.
+        sprintf(buf, "%u", pid);
+        if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
+            MYLOGE("anrd signal timed out. Please manually collect trace\n");
+            return false;
+        }
+
+        // identify the trace file by its creation time.
+        if (!(trace_dir = opendir(trace_path))) {
+            MYLOGE("Can't open trace file under %s\n", trace_path);
+        }
+        while ((trace = readdir(trace_dir))) {
+            if (strcmp(trace->d_name, ".") == 0
+                    || strcmp(trace->d_name, "..") == 0) {
+                continue;
+            }
+            sprintf(path, "%s%s", trace_path, trace->d_name);
+            if (stat(path, &st) == 0) {
+                if (st.st_ctime > max_ctime) {
+                    max_ctime = st.st_ctime;
+                    sprintf(buf, "%s", trace->d_name);
+                }
+            }
+        }
+        closedir(trace_dir);
+
+        // Wait until the dump completes by checking the size of the trace.
+        if (max_ctime > 0) {
+            sprintf(path, "%s%s", trace_path, buf);
+            while(true) {
+                sleep(1);
+                if (stat(path, &st) == 0) {
+                    if (st.st_size == cur_size) {
+                        break;
+                    } else if (st.st_size > cur_size) {
+                        cur_size = st.st_size;
+                    } else {
+                        return false;
+                    }
+                } else {
+                    MYLOGE("Cant stat() %s anymore\n", path);
+                    return false;
+                }
+            }
+            // Add to the zip file.
+            if (!add_zip_entry("anrd_trace.txt", path)) {
+                MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+            } else {
+                if (remove(path)) {
+                    MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
+                }
+                return true;
+            }
+        } else {
+            MYLOGE("Can't stats any trace file under %s\n", trace_path);
+        }
+    }
+    return false;
+}
+
 static void dump_systrace() {
     if (!zip_writer) {
         MYLOGD("Not dumping systrace because zip_writer is not set\n");
@@ -278,11 +391,12 @@
 
     std::string timeout_string = std::to_string(timeout_seconds);
 
-    const char *dumpsys_args[ARG_MAX] = { "/system/bin/dumpsys", "-t", timeout_string.c_str()};
+    const char *dumpsys_args[MAX_ARGS_ARRAY_SIZE] =
+        { "/system/bin/dumpsys", "-t", timeout_string.c_str()};
 
     int index = 3; // 'dumpsys' '-t' 'TIMEOUT'
     for (const std::string& arg : args) {
-        if (index > ARG_MAX - 2) {
+        if (index > MAX_ARGS_ARRAY_SIZE - 2) {
             MYLOGE("Too many arguments for '%s': %d\n", title.c_str(), (int) args.size());
             return;
         }
@@ -1042,7 +1156,7 @@
     printf("== Final progress (pid %d): %d/%d (originally %d)\n",
             getpid(), progress, weight_total, WEIGHT_TOTAL);
     printf("========================================================\n");
-    printf("== dumpstate: done\n");
+    printf("== dumpstate: done (id %lu)\n", id);
     printf("========================================================\n");
 }
 
@@ -1079,6 +1193,13 @@
  */
 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
         const std::string& log_path, time_t now) {
+    // Final timestamp
+    char date[80];
+    time_t the_real_now_please_stand_up = time(nullptr);
+    strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
+    MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", id, date,
+            the_real_now_please_stand_up - now);
+
     if (!add_zip_entry(bugreport_name, bugreport_path)) {
         MYLOGE("Failed to add text entry to .zip file\n");
         return false;
@@ -1165,7 +1286,7 @@
     int is_remote_mode = 0;
     std::string version = VERSION_DEFAULT;
 
-    now = time(NULL);
+    now = time(nullptr);
 
     MYLOGI("begin\n");
 
@@ -1417,7 +1538,11 @@
     print_header(version);
 
     // Dumps systrace right away, otherwise it will be filled with unnecessary events.
-    dump_systrace();
+    // First try to dump anrd trace if the daemon is running. Otherwise, dump
+    // the raw trace.
+    if (!dump_anrd_trace()) {
+        dump_systrace();
+    }
 
     // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
     dump_raft();
@@ -1567,7 +1692,7 @@
     }
 
     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
-    MYLOGI("done\n");
+    MYLOGI("done (id %lu)\n", id);
 
     if (is_redirecting) {
         fclose(stderr);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 0b87368..2dddda0 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -37,6 +37,11 @@
 
 #define SU_PATH "/system/xbin/su"
 
+// Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
+// std::vector<std::string>
+#define MAX_ARGS_ARRAY_SIZE 1000
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 4076f6a..3e4d343 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -655,7 +655,7 @@
     DurationReporter duration_reporter(title);
     fflush(stdout);
 
-    const char *args[ARG_MAX] = {command};
+    const char *args[MAX_ARGS_ARRAY_SIZE] = {command};
     size_t arg;
     va_list ap;
     va_start(ap, command);
@@ -696,7 +696,7 @@
     DurationReporter duration_reporter(title);
     fflush(stdout);
 
-    const char *args[ARG_MAX] = {command};
+    const char *args[MAX_ARGS_ARRAY_SIZE] = {command};
     size_t arg;
     va_list ap;
     va_start(ap, command);
@@ -888,11 +888,11 @@
         MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
         return;
     }
-    const char *am_args[ARG_MAX] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
+    const char *am_args[MAX_ARGS_ARRAY_SIZE] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
                                      action.c_str() };
     size_t am_index = 5; // Starts at the index of last initial value above.
     for (const std::string& arg : args) {
-        if (am_index > ARG_MAX - 2) {
+        if (am_index > MAX_ARGS_ARRAY_SIZE - 2) {
             MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
             return;
         }
@@ -1416,7 +1416,7 @@
     if (args[1] == nullptr) return;
     string->append(" ");
 
-    for (int arg = 1; arg <= 1000; ++arg) {
+    for (int arg = 1; arg <= MAX_ARGS_ARRAY_SIZE; ++arg) {
         if (args[arg] == nullptr) return;
         string->append(args[arg]);
         if (args[arg+1] != nullptr) {
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index 8af4a90..f950276 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -24,6 +24,19 @@
 # Maximum number of packages/steps.
 MAXIMUM_PACKAGES=1000
 
+# First ensure the system is booted. This is to work around issues when cmd would
+# infinitely loop trying to get a service manager (which will never come up in that
+# mode). b/30797145
+BOOT_PROPERTY_NAME="dev.bootcomplete"
+
+BOOT_COMPLETE=$(getprop $BOOT_PROPERTY_NAME)
+if [ "$BOOT_COMPLETE" != "1" ] ; then
+  echo "Error: boot-complete not detected."
+  # We must return 0 to not block sideload.
+  exit 0
+fi
+
+
 # Compute target slot suffix.
 # TODO: Once bootctl is not restricted, we should query from there. Or get this from
 #       update_engine as a parameter.
diff --git a/cmds/installd/otapreopt_slot.sh b/cmds/installd/otapreopt_slot.sh
index d51ab70..b5786e9 100644
--- a/cmds/installd/otapreopt_slot.sh
+++ b/cmds/installd/otapreopt_slot.sh
@@ -22,10 +22,13 @@
 if test -n "$SLOT_SUFFIX" ; then
   if test -d /data/ota/$SLOT_SUFFIX/dalvik-cache ; then
     log -p i -t otapreopt_slot "Moving A/B artifacts for slot ${SLOT_SUFFIX}."
+    OLD_SIZE=$(du -h -s /data/dalvik-cache)
     rm -rf /data/dalvik-cache/*
+    NEW_SIZE=$(du -h -s /data/ota/$SLOT_SUFFIX/dalvik-cache)
     mv /data/ota/$SLOT_SUFFIX/dalvik-cache/* /data/dalvik-cache/
     rmdir /data/ota/$SLOT_SUFFIX/dalvik-cache
     rmdir /data/ota/$SLOT_SUFFIX
+    log -p i -t otapreopt_slot "Moved ${NEW_SIZE} over ${OLD_SIZE}"
   else
     log -p i -t otapreopt_slot "No A/B artifacts found for slot ${SLOT_SUFFIX}."
   fi
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index ce08ecf..45060af 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -5,42 +5,46 @@
 }
 
 message Increment {
-    required int64 time_stamp       = 1;
+    required int64 time_stamp = 1;
 
     oneof increment {
-        Transaction  transaction    = 2;
-        Create       create         = 3;
-        Delete       delete         = 4;
-        BufferUpdate buffer_update  = 5;
-        VSyncEvent   vsync_event    = 6;
+        Transaction        transaction          = 2;
+        SurfaceCreation    surface_creation     = 3;
+        SurfaceDeletion    surface_deletion     = 4;
+        BufferUpdate       buffer_update        = 5;
+        VSyncEvent         vsync_event          = 6;
+        DisplayCreation    display_creation     = 7;
+        DisplayDeletion    display_deletion     = 8;
+        PowerModeUpdate    power_mode_update    = 9;
     }
 }
 
 message Transaction {
-    repeated Change change      = 1;
+    repeated SurfaceChange surface_change = 1;
+    repeated DisplayChange display_change = 2;
 
-    required bool   synchronous = 2;
-    required bool   animation   = 3;
+    required bool synchronous = 3;
+    required bool animation   = 4;
 }
 
-message Change {
-    required uint32 id = 1;
+message SurfaceChange {
+    required int32 id = 1;
 
-    oneof Change {
-        PositionChange              position                   = 2;
-        SizeChange                  size                       = 3;
-        AlphaChange                 alpha                      = 4;
-        LayerChange                 layer                      = 5;
-        CropChange                  crop                       = 6;
-        FinalCropChange             final_crop                 = 7;
-        MatrixChange                matrix                     = 8;
-        OverrideScalingModeChange   override_scaling_mode      = 9;
-        TransparentRegionHintChange transparent_region_hint    = 10;
-        LayerStackChange            layer_stack                = 11;
-        HiddenFlagChange            hidden_flag                = 12;
-        OpaqueFlagChange            opaque_flag                = 13;
-        SecureFlagChange            secure_flag                = 14;
-        DeferredTransactionChange   deferred_transaction       = 15;
+    oneof SurfaceChange {
+        PositionChange              position                = 2;
+        SizeChange                  size                    = 3;
+        AlphaChange                 alpha                   = 4;
+        LayerChange                 layer                   = 5;
+        CropChange                  crop                    = 6;
+        FinalCropChange             final_crop              = 7;
+        MatrixChange                matrix                  = 8;
+        OverrideScalingModeChange   override_scaling_mode   = 9;
+        TransparentRegionHintChange transparent_region_hint = 10;
+        LayerStackChange            layer_stack             = 11;
+        HiddenFlagChange            hidden_flag             = 12;
+        OpaqueFlagChange            opaque_flag             = 13;
+        SecureFlagChange            secure_flag             = 14;
+        DeferredTransactionChange   deferred_transaction    = 15;
     }
 }
 
@@ -102,10 +106,32 @@
 }
 
 message DeferredTransactionChange {
-    required uint32 layer_id     = 1;
+    required int32  layer_id     = 1;
     required uint64 frame_number = 2;
 }
 
+message DisplayChange {
+    required int32 id = 1;
+
+    oneof DisplayChange {
+        DispSurfaceChange surface     = 2;
+        LayerStackChange  layer_stack = 3;
+        SizeChange        size        = 4;
+        ProjectionChange  projection  = 5;
+    }
+}
+
+message DispSurfaceChange {
+    required uint64 buffer_queue_id   = 1;
+    required string buffer_queue_name = 2;
+}
+
+message ProjectionChange {
+    required int32     orientation = 1;
+    required Rectangle viewport    = 2;
+    required Rectangle frame       = 3;
+}
+
 message Rectangle {
     required int32 left   = 1;
     required int32 top    = 2;
@@ -113,24 +139,40 @@
     required int32 bottom = 4;
 }
 
-message Create {
-    required uint32 id    = 1;
-    required string name  = 2;
-    required uint32 w     = 3;
-    required uint32 h     = 4;
+message SurfaceCreation {
+    required int32  id   = 1;
+    required string name = 2;
+    required uint32 w    = 3;
+    required uint32 h    = 4;
 }
 
-message Delete {
-    required uint32 id = 1;
+message SurfaceDeletion {
+    required int32 id = 1;
 }
 
 message BufferUpdate {
-    required uint32 id            = 1;
-    required uint32 w             = 2;
-    required uint32 h             = 3;
-    required uint64 frame_number  = 4;
+    required int32  id           = 1;
+    required uint32 w            = 2;
+    required uint32 h            = 3;
+    required uint64 frame_number = 4;
 }
 
 message VSyncEvent {
     required int64 when = 1;
 }
+
+message DisplayCreation {
+    required int32     id                = 1;
+    required string    name              = 2;
+    required int32     type              = 3;
+    required bool      is_secure         = 4;
+}
+
+message DisplayDeletion {
+    required int32 id = 1;
+}
+
+message PowerModeUpdate {
+    required int32  id   = 1;
+    required int32  mode = 2;
+}
diff --git a/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp b/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
index cad11a0..77de8dc 100644
--- a/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
+++ b/cmds/surfacereplayer/replayer/BufferQueueScheduler.cpp
@@ -23,7 +23,7 @@
 using namespace android;
 
 BufferQueueScheduler::BufferQueueScheduler(
-        const sp<SurfaceControl>& surfaceControl, const RGB& color, int id)
+        const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
       : mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}
 
 void BufferQueueScheduler::startScheduling() {
@@ -44,6 +44,7 @@
 
             bufferUpdate(event.dimensions);
             fillSurface(event.event);
+            mColor.modulate();
             lock.lock();
             mBufferEvents.pop();
         }
@@ -64,7 +65,7 @@
 }
 
 void BufferQueueScheduler::setSurfaceControl(
-        const sp<SurfaceControl>& surfaceControl, const RGB& color) {
+        const sp<SurfaceControl>& surfaceControl, const HSV& color) {
     std::lock_guard<std::mutex> lock(mMutex);
     mSurfaceControl = surfaceControl;
     mColor = color;
@@ -76,7 +77,7 @@
     s->setBuffersDimensions(dimensions.width, dimensions.height);
 }
 
-void BufferQueueScheduler::fillSurface(std::shared_ptr<Event> event) {
+void BufferQueueScheduler::fillSurface(const std::shared_ptr<Event>& event) {
     ANativeWindow_Buffer outBuffer;
     sp<Surface> s = mSurfaceControl->getSurface();
 
@@ -87,13 +88,15 @@
         return;
     }
 
+    auto color = mColor.getRGB();
+
     auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
     for (int y = 0; y < outBuffer.height; y++) {
         for (int x = 0; x < outBuffer.width; x++) {
             uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
-            pixel[0] = mColor.r;
-            pixel[1] = mColor.g;
-            pixel[2] = mColor.b;
+            pixel[0] = color.r;
+            pixel[1] = color.g;
+            pixel[2] = color.b;
             pixel[3] = LAYER_ALPHA;
         }
     }
diff --git a/cmds/surfacereplayer/replayer/BufferQueueScheduler.h b/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
index fc8e20c..cb20fcc 100644
--- a/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
+++ b/cmds/surfacereplayer/replayer/BufferQueueScheduler.h
@@ -52,23 +52,23 @@
 
 class BufferQueueScheduler {
   public:
-    BufferQueueScheduler(const sp<SurfaceControl>& surfaceControl, const RGB& color, int id);
+    BufferQueueScheduler(const sp<SurfaceControl>& surfaceControl, const HSV& color, int id);
 
     void startScheduling();
     void addEvent(const BufferEvent&);
     void stopScheduling();
 
-    void setSurfaceControl(const sp<SurfaceControl>& surfaceControl, const RGB& color);
+    void setSurfaceControl(const sp<SurfaceControl>& surfaceControl, const HSV& color);
 
   private:
     void bufferUpdate(const Dimensions& dimensions);
 
     // Lock and fill the surface, block until the event is signaled by the main loop,
     // then unlock and post the buffer.
-    void fillSurface(std::shared_ptr<Event>);
+    void fillSurface(const std::shared_ptr<Event>& event);
 
     sp<SurfaceControl> mSurfaceControl;
-    RGB mColor;
+    HSV mColor;
     const int mSurfaceId;
 
     bool mContinueScheduling;
diff --git a/cmds/surfacereplayer/replayer/Color.h b/cmds/surfacereplayer/replayer/Color.h
index d644b8d..ce644be 100644
--- a/cmds/surfacereplayer/replayer/Color.h
+++ b/cmds/surfacereplayer/replayer/Color.h
@@ -22,76 +22,96 @@
 
 namespace android {
 
-typedef struct RGB {
-    RGB() = default;
+constexpr double modulateFactor = .0001;
+constexpr double modulateLimit = .80;
+
+struct RGB {
     RGB(uint8_t rIn, uint8_t gIn, uint8_t bIn) : r(rIn), g(gIn), b(bIn) {}
 
     uint8_t r = 0;
     uint8_t g = 0;
     uint8_t b = 0;
-} RGB;
+};
 
-typedef struct HSV {
+struct HSV {
     HSV() = default;
     HSV(double hIn, double sIn, double vIn) : h(hIn), s(sIn), v(vIn) {}
 
     double h = 0;
     double s = 0;
     double v = 0;
-} HSV;
 
-static inline RGB HSVToRGB(HSV hsv) {
+    RGB getRGB() const;
+
+    bool modulateUp = false;
+
+    void modulate();
+};
+
+void inline HSV::modulate() {
+    if(modulateUp) {
+        v += modulateFactor;
+    } else {
+        v -= modulateFactor;
+    }
+
+    if(v <= modulateLimit || v >= 1) {
+        modulateUp = !modulateUp;
+    }
+}
+
+inline RGB HSV::getRGB() const {
     using namespace std;
     double r = 0, g = 0, b = 0;
 
-    if (hsv.s == 0) {
-        r = hsv.v;
-        g = hsv.v;
-        b = hsv.v;
+    if (s == 0) {
+        r = v;
+        g = v;
+        b = v;
     } else {
-        hsv.h = static_cast<int>(hsv.h) % 360;
-        hsv.h = hsv.h / 60;
+        auto tempHue = static_cast<int>(h) % 360;
+        tempHue = tempHue / 60;
 
-        int i = static_cast<int>(trunc(hsv.h));
-        double f = hsv.h - i;
+        int i = static_cast<int>(trunc(tempHue));
+        double f = h - i;
 
-        double x = hsv.v * (1.0 - hsv.s);
-        double y = hsv.v * (1.0 - (hsv.s * f));
-        double z = hsv.v * (1.0 - (hsv.s * (1.0 - f)));
+        double x = v * (1.0 - s);
+        double y = v * (1.0 - (s * f));
+        double z = v * (1.0 - (s * (1.0 - f)));
 
         switch (i) {
             case 0:
-                r = hsv.v;
+                r = v;
                 g = z;
                 b = x;
                 break;
 
             case 1:
                 r = y;
-                g = hsv.v;
+                g = v;
                 b = x;
                 break;
 
             case 2:
                 r = x;
-                g = hsv.v;
+                g = v;
                 b = z;
                 break;
 
             case 3:
                 r = x;
                 g = y;
-                b = hsv.v;
+                b = v;
                 break;
 
             case 4:
                 r = z;
                 g = x;
-                b = hsv.v;
+                b = v;
                 break;
 
             default:
-                r = hsv.v;
+                r = v;
                 g = x;
                 b = y;
                 break;
diff --git a/cmds/surfacereplayer/replayer/Main.cpp b/cmds/surfacereplayer/replayer/Main.cpp
index bf5da52..dd1dd7d 100644
--- a/cmds/surfacereplayer/replayer/Main.cpp
+++ b/cmds/surfacereplayer/replayer/Main.cpp
@@ -41,9 +41,16 @@
     std::cout << "  -m  Stops the replayer at the start of the trace and switches ";
                  "to manual replay\n";
 
-    std::cout << "  -t [Number of Threads]  Specifies the number of threads to be used while "
+    std::cout << "\n  -t [Number of Threads]  Specifies the number of threads to be used while "
                  "replaying (default is " << android::DEFAULT_THREADS << ")\n";
 
+    std::cout << "\n  -s [Timestamp]  Specify at what timestamp should the replayer switch "
+                 "to manual replay\n";
+
+    std::cout << "  -n  Ignore timestamps and run through trace as fast as possible\n";
+
+    std::cout << "  -l  Indefinitely loop the replayer\n";
+
     std::cout << "  -h  Display help menu\n";
 
     std::cout << std::endl;
@@ -51,11 +58,14 @@
 
 int main(int argc, char** argv) {
     std::string filename;
+    bool loop = false;
+    bool wait = true;
     bool pauseBeginning = false;
     int numThreads = DEFAULT_THREADS;
+    long stopHere = -1;
 
     int opt = 0;
-    while ((opt = getopt(argc, argv, "pt:h?")) != -1) {
+    while ((opt = getopt(argc, argv, "mt:s:nlh?")) != -1) {
         switch (opt) {
             case 'm':
                 pauseBeginning = true;
@@ -63,6 +73,15 @@
             case 't':
                 numThreads = atoi(optarg);
                 break;
+            case 's':
+                stopHere = atol(optarg);
+                break;
+            case 'n':
+                wait = false;
+                break;
+            case 'l':
+                loop = true;
+                break;
             case 'h':
             case '?':
                 printHelpMenu();
@@ -81,8 +100,11 @@
     }
     filename.assign(input[0]);
 
-    android::Replayer r(filename, pauseBeginning, numThreads);
-    auto status = r.replay();
+    status_t status = NO_ERROR;
+    do {
+        android::Replayer r(filename, pauseBeginning, numThreads, wait, stopHere);
+        status = r.replay();
+    } while(loop);
 
     if (status == NO_ERROR) {
         std::cout << "Successfully finished replaying trace" << std::endl;
diff --git a/cmds/surfacereplayer/replayer/README.md b/cmds/surfacereplayer/replayer/README.md
new file mode 100644
index 0000000..893f0dc
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/README.md
@@ -0,0 +1,262 @@
+SurfaceReplayer Documentation
+===================
+
+[go/SurfaceReplayer](go/SurfaceReplayer)
+
+SurfaceReplayer is a playback mechanism that allows the replaying of traces recorded by
+[SurfaceInterceptor](go/SurfaceInterceptor) from SurfaceFlinger. It specifically replays
+
+* Creation and deletion of surfaces/displays
+* Alterations to the surfaces/displays called Transactions
+* Buffer Updates to surfaces
+* VSync events
+
+At their specified times to be as close to the original trace.
+
+Usage
+--------
+
+###Creating a trace
+
+SurfaceInterceptor is the mechanism used to create traces. The device needs to be rooted in order to
+utilize it. To allow it to write to the device, run
+
+`setenforce 0`
+
+To start recording a trace, run
+
+`service call SurfaceFlinger 1020 i32 1`
+
+To stop recording, run
+
+`service call SurfaceFlinger 1020 i32 0`
+
+The default location for the trace is `/data/SurfaceTrace.dat`
+
+###Executable
+
+To replay a specific trace, execute
+
+`/data/local/tmp/surfacereplayer /absolute/path/to/trace`
+
+inside the android shell. This will replay the full trace and then exit. Running this command
+outside of the shell by prepending `adb shell` will not allow for manual control and will not turn
+off VSync injections if it interrupted in any way other than fully replaying the trace
+
+The replay will not fill surfaces with their contents during the capture. Rather they are given a
+random color which will be the same every time the trace is replayed. Surfaces modulate their color
+at buffer updates.
+
+**Options:**
+
+- -m    pause the replayer at the start of the trace for manual replay
+- -t [Number of Threads] uses specified number of threads to queue up actions (default is 3)
+- -s [Timestamp] switches to manual replay at specified timestamp
+- -n    Ignore timestamps and run through trace as fast as possible
+- -l    Indefinitely loop the replayer
+- -h    displays help menu
+
+**Manual Replay:**
+When replaying, if the user presses CTRL-C, the replay will stop and can be manually controlled
+by the user. Pressing CTRL-C again will exit the replayer.
+
+Manual replaying is similar to debugging in gdb. A prompt is presented and the user is able to
+input commands to choose how to proceed by hitting enter after inputting a command. Pressing enter
+without inputting a command repeats the previous command.
+
+- n  - steps the replayer to the next VSync event
+- ni - steps the replayer to the next increment
+- c  - continues normal replaying
+- c [milliseconds] - continue until specified number of milliseconds have passed
+- s [timestamp]    - continue and stop at specified timestamp
+- l  - list out timestamp of current increment
+- h  - displays help menu
+
+###Shared Library
+
+To use the shared library include these shared libraries
+
+`libsurfacereplayer`
+`libprotobuf-cpp-full`
+`libutils`
+
+And the static library
+
+`libtrace_proto`
+
+Include the replayer header at the top of your file
+
+`#include <replayer/Replayer.h>`
+
+There are two constructors for the replayer
+
+`Replayer(std::string& filename, bool replayManually, int numThreads, bool wait, nsecs_t stopHere)`
+`Replayer(Trace& trace, ... ditto ...)`
+
+The first constructor takes in the filepath where the trace is located and loads in the trace
+object internally.
+- replayManually - **True**: if the replayer will immediately switch to manual replay at the start
+- numThreads - Number of worker threads the replayer will use.
+- wait - **False**: Replayer ignores waits in between increments
+- stopHere - Time stamp of where the replayer should run to then switch to manual replay
+
+The second constructor includes all of the same parameters but takes in a preloaded trace object.
+To use add
+
+`#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>`
+
+To your file
+
+After initializing the Replayer call
+
+    replayer.replay();
+
+And the trace will start replaying. Once the trace is finished replaying, the function will return.
+The layers that are visible at the end of the trace will remain on screen until the program
+terminates.
+
+
+**If VSyncs are broken after running the replayer** that means `enableVSyncInjections(false)` was
+never executed. This can be fixed by executing
+
+`service call SurfaceFlinger 23 i32 0`
+
+in the android shell
+
+Code Breakdown
+-------------
+
+The Replayer is composed of 5 components.
+
+- The data format of the trace (Trace.proto)
+- The Replayer object (Replayer.cpp)
+- The synchronization mechanism to signal threads within the Replayer (Event.cpp)
+- The scheduler for buffer updates per surface (BufferQueueScheduler.cpp)
+- The Main executable (Main.cpp)
+
+### Traces
+
+Traces are represented as a protobuf message located in surfacereplayer/proto/src.
+
+**Traces** contain *repeated* **Increments** (events that have occurred in SurfaceFlinger).
+**Increments** contain the time stamp of when it occurred and a *oneof* which can be a
+
+ - Transaction
+ - SurfaceCreation
+ - SurfaceDeletion
+ - DisplayCreation
+ - DisplayDeleteion
+ - BufferUpdate
+ - VSyncEvent
+ - PowerModeUpdate
+
+**Transactions** contain whether the transaction was synchronous or animated and *repeated*
+**SurfaceChanges** and **DisplayChanges**
+
+- **SurfaceChanges** contain an id of the surface being manipulated and can be changes such as
+position, alpha, hidden, size, etc.
+- **DisplayChanges** contain the id of the display being manipulated and can be changes such as
+size, layer stack, projection, etc.
+
+**Surface/Display Creation** contain the id of the surface/display and the name of the
+surface/display
+
+**Surface/Display Deletion** contain the id of the surface/display to be deleted
+
+**Buffer Updates** contain the id of the surface who's buffer is being updated, the size of the
+buffer, and the frame number.
+
+**VSyncEvents** contain when the VSync event has occurred.
+
+**PowerModeUpdates** contain the id of the display being updated and what mode it is being
+changed to.
+
+To output the contents of a trace in a readable format, execute
+
+`**aprotoc** --decode=Trace \
+-I=$ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src \
+$ANDROID_BUILD_TOP/frameworks/native/cmds/surfacereplayer/proto/src/trace.proto \
+ < **YourTraceFile.dat** > **YourOutputName.txt**`
+
+
+###Replayer
+
+Fundamentally the replayer loads a trace and iterates through each increment, waiting the required
+amount of time until the increment should be executed, then executing the increment. The first
+increment in a trace does not start at 0, rather the replayer treats its time stamp as time 0 and
+goes from there.
+
+Increments from the trace are played asynchronously rather than one by one, being dispatched by
+the main thread, queued up in a thread pool and completed when the main thread deems they are
+ready to finish execution.
+
+When an increment is dispatched, it completes as much work as it can before it has to be
+synchronized (e.g. prebaking a buffer for a BufferUpdate). When it gets to a critical action
+(e.g. locking and pushing a buffer), it waits for the main thread to complete it using an Event
+object. The main thread holds a queue of these Event objects and completes the
+corresponding Event base on its time stamp. After completing an increment, the main thread will
+dispatch another increment and continue.
+
+The main thread's execution flow is outlined below
+
+    initReplay() //queue up the initial increments
+    while(!pendingIncrements.empty()) { //while increments remaining
+        event = pendingIncrement.pop();
+        wait(event.time_stamp(); //waitUntil it is time to complete this increment
+
+        event.complete() //signal to let event finish
+        if(increments remaing()) {
+            dispatchEvent() //queue up another increment
+        }
+    }
+
+A worker thread's flow looks like so
+
+    //dispatched!
+    Execute non-time sensitive work here
+    ...
+    event.readyToExecute() //time sensitive point...waiting for Main Thread
+    ...
+    Finish execution
+
+
+### Event
+
+An Event is a simple synchronization mechanism used to facilitate communication between the main
+and worker threads. Every time an increment is dispatched, an Event object is also created.
+
+An Event can be in 4 different states:
+
+- **SettingUp** - The worker is in the process of completing all non-time sensitive work
+- **Waiting** - The worker is waiting on the main thread to signal it.
+- **Signaled** - The worker has just been signaled by the main thread
+- **Running** - The worker is running again and finishing the rest of its work.
+
+When the main thread wants to finish the execution of a worker, the worker can either still be
+**SettingUp**, in which the main thread will wait, or the worker will be **Waiting**, in which the
+main thread will **Signal** it to complete. The worker thread changes itself to the **Running**
+state once **Signaled**. This last step exists in order to communicate back to the main thread that
+the worker thread has actually started completing its execution, rather than being preempted right
+after signalling. Once this happens, the main thread schedules the next worker. This makes sure
+there is a constant amount of workers running at one time.
+
+This activity is encapsulated in the `readyToExecute()` and `complete()` functions called by the
+worker and main thread respectively.
+
+### BufferQueueScheduler
+
+During a **BuferUpdate**, the worker thread will wait until **Signaled** to unlock and post a
+buffer that has been prefilled during the **SettingUp** phase. However if there are two sequential
+**BufferUpdates** that act on the same surface, both threads will try to lock a buffer and fill it,
+which isn't possible and will cause a deadlock. The BufferQueueScheduler solves this problem by
+handling when **BufferUpdates** should be scheduled, making sure that they don't overlap.
+
+When a surface is created, a BufferQueueScheduler is also created along side it. Whenever a
+**BufferUpdate** is read, it schedules the event onto its own internal queue and then schedules one
+every time an Event is completed.
+
+### Main
+
+The main exectuable reads in the command line arguments. Creates the Replayer using those
+arguments. Executes `replay()` on the Replayer. If there are no errors while replaying it will exit
+gracefully, if there are then it will report the error and then exit.
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));
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index ff951d1..f757fc3 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -40,16 +40,21 @@
 namespace android {
 
 const auto DEFAULT_PATH = "/data/local/tmp/SurfaceTrace.dat";
-const auto RAND_COLOR_SEED = 1000;
+const auto RAND_COLOR_SEED = 700;
 const auto DEFAULT_THREADS = 3;
 
-typedef uint32_t layer_id;
+typedef int32_t layer_id;
+typedef int32_t display_id;
+
+typedef google::protobuf::RepeatedPtrField<SurfaceChange> SurfaceChanges;
+typedef google::protobuf::RepeatedPtrField<DisplayChange> DisplayChanges;
 
 class Replayer {
   public:
     Replayer(const std::string& filename, bool replayManually = false,
-            int numThreads = DEFAULT_THREADS);
-    Replayer(const Trace& trace, bool replayManually = false, int numThreads = DEFAULT_THREADS);
+            int numThreads = DEFAULT_THREADS, bool wait = true, nsecs_t stopHere = -1);
+    Replayer(const Trace& trace, bool replayManually = false, int numThreads = DEFAULT_THREADS,
+            bool wait = true, nsecs_t stopHere = -1);
 
     status_t replay();
 
@@ -62,24 +67,37 @@
     status_t dispatchEvent(int index);
 
     status_t doTransaction(const Transaction& transaction, const std::shared_ptr<Event>& event);
-    status_t createSurfaceControl(const Create& create, const std::shared_ptr<Event>& event);
-    status_t deleteSurfaceControl(const Delete& delete_, const std::shared_ptr<Event>& event);
+    status_t createSurfaceControl(const SurfaceCreation& create,
+            const std::shared_ptr<Event>& event);
+    status_t deleteSurfaceControl(const SurfaceDeletion& delete_,
+            const std::shared_ptr<Event>& event);
     status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr<Event>& event);
+    void createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event);
+    void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
+    void updatePowerMode(const PowerModeUpdate& update, const std::shared_ptr<Event>& event);
 
-    status_t setPosition(uint32_t id, const PositionChange& pc);
-    status_t setSize(uint32_t id, const SizeChange& sc);
-    status_t setAlpha(uint32_t id, const AlphaChange& ac);
-    status_t setLayer(uint32_t id, const LayerChange& lc);
-    status_t setCrop(uint32_t id, const CropChange& cc);
-    status_t setFinalCrop(uint32_t id, const FinalCropChange& fcc);
-    status_t setMatrix(uint32_t id, const MatrixChange& mc);
-    status_t setOverrideScalingMode(uint32_t id, const OverrideScalingModeChange& osmc);
-    status_t setTransparentRegionHint(uint32_t id, const TransparentRegionHintChange& trgc);
-    status_t setLayerStack(uint32_t id, const LayerStackChange& lsc);
-    status_t setHiddenFlag(uint32_t id, const HiddenFlagChange& hfc);
-    status_t setOpaqueFlag(uint32_t id, const OpaqueFlagChange& ofc);
-    status_t setSecureFlag(uint32_t id, const SecureFlagChange& sfc);
-    status_t setDeferredTransaction(uint32_t id, const DeferredTransactionChange& dtc);
+    status_t doSurfaceTransaction(const SurfaceChanges& surfaceChange);
+    void doDisplayTransaction(const DisplayChanges& displayChange);
+
+    status_t setPosition(layer_id id, const PositionChange& pc);
+    status_t setSize(layer_id id, const SizeChange& sc);
+    status_t setAlpha(layer_id id, const AlphaChange& ac);
+    status_t setLayer(layer_id id, const LayerChange& lc);
+    status_t setCrop(layer_id id, const CropChange& cc);
+    status_t setFinalCrop(layer_id id, const FinalCropChange& fcc);
+    status_t setMatrix(layer_id id, const MatrixChange& mc);
+    status_t setOverrideScalingMode(layer_id id, const OverrideScalingModeChange& osmc);
+    status_t setTransparentRegionHint(layer_id id, const TransparentRegionHintChange& trgc);
+    status_t setLayerStack(layer_id id, const LayerStackChange& lsc);
+    status_t setHiddenFlag(layer_id id, const HiddenFlagChange& hfc);
+    status_t setOpaqueFlag(layer_id id, const OpaqueFlagChange& ofc);
+    status_t setSecureFlag(layer_id id, const SecureFlagChange& sfc);
+    status_t setDeferredTransaction(layer_id id, const DeferredTransactionChange& dtc);
+
+    void setDisplaySurface(display_id id, const DispSurfaceChange& dsc);
+    void setDisplayLayerStack(display_id id, const LayerStackChange& lsc);
+    void setDisplaySize(display_id id, const SizeChange& sc);
+    void setDisplayProjection(display_id id, const ProjectionChange& pc);
 
     void doDeleteSurfaceControls();
     void waitUntilTimestamp(int64_t timestamp);
@@ -93,15 +111,20 @@
     int64_t mCurrentTime = 0;
     int32_t mNumThreads = DEFAULT_THREADS;
 
+    Increment mCurrentIncrement;
+
     std::string mLastInput;
 
     static atomic_bool sReplayingManually;
     bool mWaitingForNextVSync;
+    bool mWaitForTimeStamps;
+    nsecs_t mStopTimeStamp;
+    bool mHasStopped;
 
     std::mutex mLayerLock;
     std::condition_variable mLayerCond;
     std::unordered_map<layer_id, sp<SurfaceControl>> mLayers;
-    std::unordered_map<layer_id, RGB> mColors;
+    std::unordered_map<layer_id, HSV> mColors;
 
     std::mutex mPendingLayersLock;
     std::vector<layer_id> mLayersPendingRemoval;
@@ -109,6 +132,10 @@
     std::mutex mBufferQueueSchedulerLock;
     std::unordered_map<layer_id, std::shared_ptr<BufferQueueScheduler>> mBufferQueueSchedulers;
 
+    std::mutex mDisplayLock;
+    std::condition_variable mDisplayCond;
+    std::unordered_map<display_id, sp<IBinder>> mDisplays;
+
     sp<SurfaceComposerClient> mComposerClient;
     std::queue<std::shared_ptr<Event>> mPendingIncrements;
 };
diff --git a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py
new file mode 100644
index 0000000..a892e46
--- /dev/null
+++ b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py
@@ -0,0 +1,294 @@
+#!/usr/bin/python
+from subprocess import call
+import os
+proto_path = os.environ['ANDROID_BUILD_TOP'] + "/frameworks/native/cmds/surfacereplayer/proto/src/"
+call(["aprotoc", "-I=" + proto_path, "--python_out=.", proto_path + "trace.proto"])
+
+from trace_pb2 import *
+
+trace = Trace()
+
+def main():
+    global trace
+    while(1):
+        option = main_menu()
+
+        if option == 0:
+            break
+
+        increment = trace.increment.add()
+        increment.time_stamp  = int(input("Time stamp of action: "))
+
+        if option == 1:
+           transaction(increment)
+        elif option == 2:
+            surface_create(increment)
+        elif option == 3:
+            surface_delete(increment)
+        elif option == 4:
+            display_create(increment)
+        elif option == 5:
+            display_delete(increment)
+        elif option == 6:
+            buffer_update(increment)
+        elif option == 7:
+            vsync_event(increment)
+        elif option == 8:
+            power_mode_update(increment)
+
+    seralizeTrace()
+
+def seralizeTrace():
+    with open("trace.dat", 'wb') as f:
+        f.write(trace.SerializeToString())
+
+
+def main_menu():
+    print ("")
+    print ("What would you like to do?")
+    print ("1. Add transaction")
+    print ("2. Add surface creation")
+    print ("3. Add surface deletion")
+    print ("4. Add display creation")
+    print ("5. Add display deletion")
+    print ("6. Add buffer update")
+    print ("7. Add VSync event")
+    print ("8. Add power mode update")
+    print ("0. Finish and serialize")
+    print ("")
+
+    return int(input("> "))
+
+def transaction_menu():
+    print ("")
+    print ("What kind of transaction?")
+    print ("1. Position Change")
+    print ("2. Size Change")
+    print ("3. Alpha Change")
+    print ("4. Layer Change")
+    print ("5. Crop Change")
+    print ("6. Final Crop Change")
+    print ("7. Matrix Change")
+    print ("8. Override Scaling Mode Change")
+    print ("9. Transparent Region Hint Change")
+    print ("10. Layer Stack Change")
+    print ("11. Hidden Flag Change")
+    print ("12. Opaque Flag Change")
+    print ("13. Secure Flag Change")
+    print ("14. Deferred Transaction Change")
+    print ("15. Display - Surface Change")
+    print ("16. Display - Layer Stack Change")
+    print ("17. Display - Size Change")
+    print ("18. Display - Projection Change")
+    print ("0. Finished adding Changes to this transaction")
+    print ("")
+
+    return int(input("> "))
+
+def transaction(increment):
+    global trace
+
+    increment.transaction.synchronous \
+            = bool(input("Is transaction synchronous (True/False): "))
+    increment.transaction.animation \
+            = bool(input("Is transaction animated (True/False): "))
+
+    while(1):
+        option = transaction_menu()
+
+        if option == 0:
+            break
+
+        change = None
+        if option <= 14:
+            change = increment.transaction.surface_change.add()
+        elif option >= 15 and option <= 18:
+            change = increment.transaction.display_change.add()
+
+        change.id = int(input("ID of layer/display to undergo a change: "))
+
+        if option == 1:
+            change.position.x, change.position.y = position()
+        elif option == 2:
+            change.size.w, change.size.h = size()
+        elif option == 3:
+            change.alpha.alpha = alpha()
+        elif option == 4:
+            change.layer.layer = layer()
+        elif option == 5:
+            change.crop.rectangle.left,  change.crop.rectangle.top, \
+            change.crop.rectangle.right, change.crop.rectangle.bottom = crop()
+        elif option == 6:
+            change.final_crop.rectangle.left, \
+            change.final_crop.rectangle.top,  \
+            change.final_crop.rectangle.right,\
+            change.final_crop.rectangle.bottom = final_crop()
+        elif option == 7:
+            change.matrix.dsdx,\
+            change.matrix.dtdx,\
+            change.matrix.dsdy,\
+            change.matrix.dtdy = layer()
+        elif option == 8:
+            change.override_scaling_mode.override_scaling_mode \
+                                     = override_scaling_mode()
+        elif option == 9:
+            for rect in transparent_region_hint():
+                new = increment.transparent_region_hint.region.add()
+                new.left = rect[0]
+                new.top = rect[1]
+                new.right = rect[2]
+                new.bottom = rect[3]
+        elif option == 10:
+            change.layer_stack.layer_stack = layer_stack()
+        elif option == 11:
+            change.hidden_flag.hidden_flag = hidden_flag()
+        elif option == 12:
+            change.opaque_flag.opaque_flag = opaque_flag()
+        elif option == 13:
+            change.secure_flag.secure_flag = secure_flag()
+        elif option == 14:
+            change.deferred_transaction.layer_id, \
+            change.deferred_transaction.frame_number = deferred_transaction()
+        elif option == 15:
+            change.surface.buffer_queue_id, \
+            change.surface.buffer_queue_name = surface()
+        elif option == 16:
+            change.layer_stack.layer_stack = layer_stack()
+        elif option == 17:
+            change.size.w, change.size.h = size()
+        elif option == 18:
+            projection(change)
+
+def surface_create(increment):
+    increment.surface_creation.id = int(input("Enter id: "))
+    n = str(raw_input("Enter name: "))
+    increment.surface_creation.name = n
+    increment.surface_creation.w = input("Enter w: ")
+    increment.surface_creation.h = input("Enter h: ")
+
+def surface_delete(increment):
+    increment.surface_deletion.id = int(input("Enter id: "))
+
+def display_create(increment):
+    increment.display_creation.id = int(input("Enter id: "))
+    increment.display_creation.name = str(raw_input("Enter name: "))
+    increment.display_creation.type = int(input("Enter type: "))
+    increment.display_creation.is_secure = bool(input("Enter if secure: "))
+
+def display_delete(increment):
+    increment.surface_deletion.id = int(input("Enter id: "))
+
+def buffer_update(increment):
+    increment.buffer_update.id = int(input("Enter id: "))
+    increment.buffer_update.w = int(input("Enter w: "))
+    increment.buffer_update.h = int(input("Enter h: "))
+    increment.buffer_update.frame_number = int(input("Enter frame_number: "))
+
+def vsync_event(increment):
+    increment.vsync_event.when = int(input("Enter when: "))
+
+def power_mode_update(increment):
+    increment.power_mode_update.id = int(input("Enter id: "))
+    increment.power_mode_update.mode = int(input("Enter mode: "))
+
+def position():
+    x = input("Enter x: ")
+    y = input("Enter y: ")
+
+    return float(x), float(y)
+
+def size():
+    w = input("Enter w: ")
+    h = input("Enter h: ")
+
+    return int(w), int(h)
+
+def alpha():
+    alpha = input("Enter alpha: ")
+
+    return float(alpha)
+
+def layer():
+    layer = input("Enter layer: ")
+
+    return int(layer)
+
+def crop():
+    return rectangle()
+
+def final_crop():
+    return rectangle()
+
+def matrix():
+    dsdx = input("Enter dsdx: ")
+    dtdx = input("Enter dtdx: ")
+    dsdy = input("Enter dsdy: ")
+    dtdy = input("Enter dtdy: ")
+
+    return float(dsdx)
+
+def override_scaling_mode():
+    mode = input("Enter override scaling mode: ")
+
+    return int(mode)
+
+def transparent_region_hint():
+    num = input("Enter number of rectangles in region: ")
+
+    return [rectangle() in range(x)]
+
+def layer_stack():
+    layer_stack = input("Enter layer stack: ")
+
+    return int(layer_stack)
+
+def hidden_flag():
+    flag = input("Enter hidden flag state (True/False): ")
+
+    return bool(flag)
+
+def opaque_flag():
+    flag = input("Enter opaque flag state (True/False): ")
+
+    return bool(flag)
+
+def secure_flag():
+    flag = input("Enter secure flag state (True/False): ")
+
+    return bool(flag)
+
+def deferred_transaction():
+    layer_id = input("Enter layer_id: ")
+    frame_number = input("Enter frame_number: ")
+
+    return int(layer_id), int(frame_number)
+
+def surface():
+    id = input("Enter id: ")
+    name = raw_input("Enter name: ")
+
+    return int(id), str(name)
+
+def projection(change):
+    change.projection.orientation = input("Enter orientation: ")
+    print("Enter rectangle for viewport")
+    change.projection.viewport.left, \
+    change.projection.viewport.top,  \
+    change.projection.viewport.right,\
+    change.projection.viewport.bottom = rectangle()
+    print("Enter rectangle for frame")
+    change.projection.frame.left, \
+    change.projection.frame.top,  \
+    change.projection.frame.right,\
+    change.projection.frame.bottom = rectangle()
+
+def rectangle():
+    left = input("Enter left: ")
+    top = input("Enter top: ")
+    right = input("Enter right: ")
+    bottom = input("Enter bottom: ")
+
+    return int(left), int(top), int(right), int(bottom)
+
+if __name__ == "__main__":
+    main()
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 55ad6cc..790fa8c 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "IMemory"
 
+#include <atomic>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,7 +30,6 @@
 #include <cutils/log.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
-#include <utils/Atomic.h>
 #include <binder/Parcel.h>
 #include <utils/CallStack.h>
 
@@ -56,12 +56,15 @@
     struct heap_info_t {
         sp<IMemoryHeap> heap;
         int32_t         count;
+        // Note that this cannot be meaningfully copied.
     };
 
     void free_heap(const wp<IBinder>& binder);
 
-    Mutex mHeapCacheLock;
+    Mutex mHeapCacheLock;  // Protects entire vector below.
     KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
+    // We do not use the copy-on-write capabilities of KeyedVector.
+    // TODO: Reimplemement based on standard C++ container?
 };
 
 static sp<HeapCache> gHeapCache = new HeapCache();
@@ -105,7 +108,7 @@
     void assertMapped() const;
     void assertReallyMapped() const;
 
-    mutable volatile int32_t mHeapId;
+    mutable std::atomic<int32_t> mHeapId;
     mutable void*       mBase;
     mutable size_t      mSize;
     mutable uint32_t    mFlags;
@@ -248,8 +251,9 @@
 }
 
 BpMemoryHeap::~BpMemoryHeap() {
-    if (mHeapId != -1) {
-        close(mHeapId);
+    int32_t heapId = mHeapId.load(memory_order_relaxed);
+    if (heapId != -1) {
+        close(heapId);
         if (mRealHeap) {
             // by construction we're the last one
             if (mBase != MAP_FAILED) {
@@ -257,7 +261,7 @@
 
                 if (VERBOSE) {
                     ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
-                            binder.get(), this, mSize, mHeapId);
+                            binder.get(), this, mSize, heapId);
                     CallStack stack(LOG_TAG);
                 }
 
@@ -273,17 +277,21 @@
 
 void BpMemoryHeap::assertMapped() const
 {
-    if (mHeapId == -1) {
+    int32_t heapId = mHeapId.load(memory_order_acquire);
+    if (heapId == -1) {
         sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
         sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
         heap->assertReallyMapped();
         if (heap->mBase != MAP_FAILED) {
             Mutex::Autolock _l(mLock);
-            if (mHeapId == -1) {
+            if (mHeapId.load(memory_order_relaxed) == -1) {
                 mBase   = heap->mBase;
                 mSize   = heap->mSize;
                 mOffset = heap->mOffset;
-                android_atomic_write( dup( heap->mHeapId ), &mHeapId );
+                int fd = dup(heap->mHeapId.load(memory_order_relaxed));
+                ALOGE_IF(fd==-1, "cannot dup fd=%d",
+                        heap->mHeapId.load(memory_order_relaxed));
+                mHeapId.store(fd, memory_order_release);
             }
         } else {
             // something went wrong
@@ -294,7 +302,8 @@
 
 void BpMemoryHeap::assertReallyMapped() const
 {
-    if (mHeapId == -1) {
+    int32_t heapId = mHeapId.load(memory_order_acquire);
+    if (heapId == -1) {
 
         // remote call without mLock held, worse case scenario, we end up
         // calling transact() from multiple threads, but that's not a problem,
@@ -313,7 +322,7 @@
                 parcel_fd, size, err, strerror(-err));
 
         Mutex::Autolock _l(mLock);
-        if (mHeapId == -1) {
+        if (mHeapId.load(memory_order_relaxed) == -1) {
             int fd = dup( parcel_fd );
             ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
                     parcel_fd, size, err, strerror(errno));
@@ -322,7 +331,6 @@
             if (!(flags & READ_ONLY)) {
                 access |= PROT_WRITE;
             }
-
             mRealHeap = true;
             mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
             if (mBase == MAP_FAILED) {
@@ -333,7 +341,7 @@
                 mSize = size;
                 mFlags = flags;
                 mOffset = offset;
-                android_atomic_write(fd, &mHeapId);
+                mHeapId.store(fd, memory_order_release);
             }
         }
     }
@@ -341,7 +349,8 @@
 
 int BpMemoryHeap::getHeapID() const {
     assertMapped();
-    return mHeapId;
+    // We either stored mHeapId ourselves, or loaded it with acquire semantics.
+    return mHeapId.load(memory_order_relaxed);
 }
 
 void* BpMemoryHeap::getBase() const {
@@ -418,9 +427,10 @@
                 "found binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
                 binder.get(), info.heap.get(),
                 static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
-                static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
+                static_cast<BpMemoryHeap*>(info.heap.get())
+                    ->mHeapId.load(memory_order_relaxed),
                 info.count);
-        android_atomic_inc(&info.count);
+        ++info.count;
         return info.heap;
     } else {
         heap_info_t info;
@@ -445,13 +455,13 @@
         ssize_t i = mHeapCache.indexOfKey(binder);
         if (i>=0) {
             heap_info_t& info(mHeapCache.editValueAt(i));
-            int32_t c = android_atomic_dec(&info.count);
-            if (c == 1) {
+            if (--info.count == 0) {
                 ALOGD_IF(VERBOSE,
                         "removing binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
                         binder.unsafe_get(), info.heap.get(),
                         static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
-                        static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
+                        static_cast<BpMemoryHeap*>(info.heap.get())
+                            ->mHeapId.load(memory_order_relaxed),
                         info.count);
                 rel = mHeapCache.valueAt(i).heap;
                 mHeapCache.removeItemsAt(i);
@@ -482,7 +492,7 @@
         ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)",
                 mHeapCache.keyAt(i).unsafe_get(),
                 info.heap.get(), info.count,
-                h->mHeapId, h->mBase, h->mSize);
+                h->mHeapId.load(memory_order_relaxed), h->mBase, h->mSize);
     }
 }
 
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 319d1d9..d42bb82 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "ProcessState"
 
-#include <cutils/process_name.h>
-
 #include <binder/ProcessState.h>
 
 #include <utils/Atomic.h>
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 81d5a57..308bd7d 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -115,13 +115,13 @@
     EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
     EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
 
-    EXPECT_TRUE(checkPixel(22, 19, 100, 255,  74, 255));
-    EXPECT_TRUE(checkPixel(45, 11, 100, 255,  74, 255));
-    EXPECT_TRUE(checkPixel(52, 12, 155,   0, 181, 255));
-    EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
-    EXPECT_TRUE(checkPixel(31, 54,   0,  71, 117, 255));
-    EXPECT_TRUE(checkPixel(29, 28,   0, 133,   0, 255));
-    EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
+    EXPECT_TRUE(checkPixel(22, 19, 100, 255,  74, 255, 3));
+    EXPECT_TRUE(checkPixel(45, 11, 100, 255,  74, 255, 3));
+    EXPECT_TRUE(checkPixel(52, 12, 155,   0, 181, 255, 3));
+    EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255, 3));
+    EXPECT_TRUE(checkPixel(31, 54,   0,  71, 117, 255, 3));
+    EXPECT_TRUE(checkPixel(29, 28,   0, 133,   0, 255, 3));
+    EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255, 3));
 }
 
 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index c1e1bad..f2f1444 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -206,7 +206,7 @@
 status_t SensorService::SensorEventConnection::sendEvents(
         sensors_event_t const* buffer, size_t numEvents,
         sensors_event_t* scratch,
-        SensorEventConnection const * const * mapFlushEventsToConnections) {
+        wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
     // filter out events not for this connection
     int count = 0;
     Mutex::Autolock _l(mConnectionLock);
@@ -234,7 +234,7 @@
             FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
             // Check if there is a pending flush_complete event for this sensor on this connection.
             if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
-                    this == mapFlushEventsToConnections[i]) {
+                    mapFlushEventsToConnections[i] == this) {
                 flushInfo.mFirstFlushPending = false;
                 ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
                         buffer[i].meta_data.sensor);
@@ -255,7 +255,7 @@
                 // from the same sensor_handle AND the current connection is mapped to the
                 // corresponding flush_complete_event.
                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                    if (this == mapFlushEventsToConnections[i]) {
+                    if (mapFlushEventsToConnections[i] == this) {
                         scratch[count++] = buffer[i];
                     }
                     ++i;
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index b796cc0..883c16e 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -52,7 +52,7 @@
                           bool isDataInjectionMode, const String16& opPackageName);
 
     status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
-                        SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+                        wp<const SensorEventConnection> const * mapFlushEventsToConnections = NULL);
     bool hasSensor(int32_t handle) const;
     bool hasAnySensor() const;
     bool hasOneShotSensors() const;
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
index 644cfb0..53fb9de 100644
--- a/services/sensorservice/SensorRecord.cpp
+++ b/services/sensorservice/SensorRecord.cpp
@@ -21,13 +21,13 @@
 namespace android {
 
 SensorService::SensorRecord::SensorRecord(
-        const sp<SensorEventConnection>& connection)
+        const sp<const SensorEventConnection>& connection)
 {
     mConnections.add(connection);
 }
 
 bool SensorService::SensorRecord::addConnection(
-        const sp<SensorEventConnection>& connection)
+        const sp<const SensorEventConnection>& connection)
 {
     if (mConnections.indexOf(connection) < 0) {
         mConnections.add(connection);
@@ -37,16 +37,16 @@
 }
 
 bool SensorService::SensorRecord::removeConnection(
-        const wp<SensorEventConnection>& connection)
+        const wp<const SensorEventConnection>& connection)
 {
     ssize_t index = mConnections.indexOf(connection);
     if (index >= 0) {
         mConnections.removeItemsAt(index, 1);
     }
     // Remove this connections from the queue of flush() calls made on this sensor.
-    for (Vector< wp<SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
+    for (Vector< wp<const SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
             it != mPendingFlushConnections.end(); ) {
-        if (it->unsafe_get() == connection.unsafe_get()) {
+        if (*it == connection) {
             it = mPendingFlushConnections.erase(it);
         } else {
             ++it;
@@ -56,7 +56,7 @@
 }
 
 void SensorService::SensorRecord::addPendingFlushConnection(
-        const sp<SensorEventConnection>& connection) {
+        const sp<const SensorEventConnection>& connection) {
     mPendingFlushConnections.add(connection);
 }
 
@@ -66,10 +66,10 @@
     }
 }
 
-SensorService::SensorEventConnection *
+wp<const SensorService::SensorEventConnection>
         SensorService::SensorRecord::getFirstPendingFlushConnection() {
     if (mPendingFlushConnections.size() > 0) {
-        return mPendingFlushConnections[0].unsafe_get();
+        return mPendingFlushConnections[0];
     }
     return NULL;
 }
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
index 29b970d..5a35410 100644
--- a/services/sensorservice/SensorRecord.h
+++ b/services/sensorservice/SensorRecord.h
@@ -25,20 +25,20 @@
 
 class SensorService::SensorRecord {
 public:
-    SensorRecord(const sp<SensorEventConnection>& connection);
-    bool addConnection(const sp<SensorEventConnection>& connection);
-    bool removeConnection(const wp<SensorEventConnection>& connection);
+    SensorRecord(const sp<const SensorEventConnection>& connection);
+    bool addConnection(const sp<const SensorEventConnection>& connection);
+    bool removeConnection(const wp<const SensorEventConnection>& connection);
     size_t getNumConnections() const { return mConnections.size(); }
 
-    void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+    void addPendingFlushConnection(const sp<const SensorEventConnection>& connection);
     void removeFirstPendingFlushConnection();
-    SensorEventConnection * getFirstPendingFlushConnection();
+    wp<const SensorEventConnection> getFirstPendingFlushConnection();
     void clearAllPendingFlushConnections();
 private:
-    SortedVector< wp<SensorEventConnection> > mConnections;
+    SortedVector< wp<const SensorEventConnection> > mConnections;
     // A queue of all flush() calls made on this sensor. Flush complete events
     // will be sent in this order.
-    Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+    Vector< wp<const SensorEventConnection> > mPendingFlushConnections;
 };
 
 }
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index a24740b..dbd0624 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -260,7 +260,7 @@
             const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
             mSensorEventBuffer = new sensors_event_t[minBufferSize];
             mSensorEventScratch = new sensors_event_t[minBufferSize];
-            mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
+            mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];
             mCurrentOperatingMode = NORMAL;
 
             mNextSensorRegIndex = 0;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 343796a..e969d8a 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -237,7 +237,7 @@
     SortedVector< wp<SensorEventConnection> > mActiveConnections;
     bool mWakeLockAcquired;
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
-    SensorEventConnection const **mMapFlushEventsToConnections;
+    wp<const SensorEventConnection> * mMapFlushEventsToConnections;
     std::unordered_map<int, RecentEventLogger*> mRecentEvent;
     Mode mCurrentOperatingMode;
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5c2c0ad..6c18ef7 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -613,3 +613,17 @@
     mDisplaySurface->dumpAsString(surfaceDump);
     result.append(surfaceDump);
 }
+
+std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1);
+
+DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure)
+    : type(type),
+      layerStack(DisplayDevice::NO_LAYER_STACK),
+      orientation(0),
+      width(0),
+      height(0),
+      isSecure(isSecure)
+{
+    viewport.makeInvalid();
+    frame.makeInvalid();
+}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 105e980..92ede08 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -263,6 +263,28 @@
 #endif
 };
 
+struct DisplayDeviceState {
+    DisplayDeviceState() = default;
+    DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
+
+    bool isValid() const { return type >= 0; }
+    bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
+    bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
+
+    static std::atomic<int32_t> nextDisplayId;
+    int32_t displayId = nextDisplayId++;
+    DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID;
+    sp<IGraphicBufferProducer> surface;
+    uint32_t layerStack = DisplayDevice::NO_LAYER_STACK;
+    Rect viewport;
+    Rect frame;
+    uint8_t orientation = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    String8 displayName;
+    bool isSecure = false;
+};
+
 }; // namespace android
 
 #endif // ANDROID_DISPLAY_DEVICE_H
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index bdd94e3..d1bc7eb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,13 +44,14 @@
     return;
 }
 
-EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs)
     : mVSyncSource(src),
       mFlinger(flinger),
       mUseSoftwareVSync(false),
       mVsyncEnabled(false),
       mDebugVsyncEnabled(false),
-      mVsyncHintSent(false) {
+      mVsyncHintSent(false),
+      mInterceptVSyncs(interceptVSyncs) {
 
     for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
         mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
@@ -226,7 +227,9 @@
             timestamp = mVSyncEvent[i].header.timestamp;
             if (timestamp) {
                 // we have a vsync event to dispatch
-                mFlinger.mInterceptor.saveVSyncEvent(timestamp);
+                if (mInterceptVSyncs) {
+                    mFlinger.mInterceptor.saveVSyncEvent(timestamp);
+                }
                 *event = mVSyncEvent[i];
                 mVSyncEvent[i].header.timestamp = 0;
                 vsyncCount = mVSyncEvent[i].vsync.count;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 34654fa..f1f89f8 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
 
 public:
 
-    EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
+    EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs);
 
     sp<Connection> createEventConnection() const;
     status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -132,6 +132,7 @@
     bool mDebugVsyncEnabled;
 
     bool mVsyncHintSent;
+    const bool mInterceptVSyncs;
     timer_t mTimerId;
 };
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 320f416..c15b4bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -198,6 +198,10 @@
     property_get("debug.sf.disable_backpressure", value, "0");
     mPropagateBackpressure = !atoi(value);
     ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
+
+    property_get("debug.sf.disable_hwc_vds", value, "0");
+    mUseHwcVirtualDisplays = !atoi(value);
+    ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -257,7 +261,7 @@
     DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
     info.displayName = displayName;
     mCurrentState.displays.add(token, info);
-
+    mInterceptor.saveDisplayCreation(info);
     return token;
 }
 
@@ -275,7 +279,7 @@
         ALOGE("destroyDisplay called for non-virtual display");
         return;
     }
-
+    mInterceptor.saveDisplayDeletion(info.displayId);
     mCurrentState.displays.removeItemsAt(idx);
     setTransactionFlags(eDisplayTransactionNeeded);
 }
@@ -288,6 +292,7 @@
     // All non-virtual displays are currently considered secure.
     DisplayDeviceState info(type, true);
     mCurrentState.displays.add(mBuiltinDisplays[type], info);
+    mInterceptor.saveDisplayCreation(info);
 }
 
 sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
@@ -498,10 +503,10 @@
         // start the EventThread
         sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                 vsyncPhaseOffsetNs, true, "app");
-        mEventThread = new EventThread(vsyncSrc, *this);
+        mEventThread = new EventThread(vsyncSrc, *this, false);
         sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                 sfVsyncPhaseOffsetNs, true, "sf");
-        mSFEventThread = new EventThread(sfVsyncSrc, *this);
+        mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
         mEventQueue.setEventThread(mSFEventThread);
 
         // set SFEventThread to SCHED_FIFO to minimize jitter
@@ -891,7 +896,7 @@
         ALOGV("VSync Injections enabled");
         if (mVSyncInjector.get() == nullptr) {
             mVSyncInjector = new InjectVSyncSource();
-            mInjectorEventThread = new EventThread(mVSyncInjector, *this);
+            mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
         }
         mEventQueue.setEventThread(mInjectorEventThread);
     } else {
@@ -1655,26 +1660,28 @@
                         // etc.) but no internal state (i.e. a DisplayDevice).
                         if (state.surface != NULL) {
 
-                            int width = 0;
-                            int status = state.surface->query(
-                                    NATIVE_WINDOW_WIDTH, &width);
-                            ALOGE_IF(status != NO_ERROR,
-                                    "Unable to query width (%d)", status);
-                            int height = 0;
-                            status = state.surface->query(
-                                    NATIVE_WINDOW_HEIGHT, &height);
-                            ALOGE_IF(status != NO_ERROR,
-                                    "Unable to query height (%d)", status);
-                            int intFormat = 0;
-                            status = state.surface->query(
-                                    NATIVE_WINDOW_FORMAT, &intFormat);
-                            ALOGE_IF(status != NO_ERROR,
-                                    "Unable to query format (%d)", status);
-                            auto format = static_cast<android_pixel_format_t>(
-                                    intFormat);
+                            if (mUseHwcVirtualDisplays) {
+                                int width = 0;
+                                int status = state.surface->query(
+                                        NATIVE_WINDOW_WIDTH, &width);
+                                ALOGE_IF(status != NO_ERROR,
+                                        "Unable to query width (%d)", status);
+                                int height = 0;
+                                status = state.surface->query(
+                                        NATIVE_WINDOW_HEIGHT, &height);
+                                ALOGE_IF(status != NO_ERROR,
+                                        "Unable to query height (%d)", status);
+                                int intFormat = 0;
+                                status = state.surface->query(
+                                        NATIVE_WINDOW_FORMAT, &intFormat);
+                                ALOGE_IF(status != NO_ERROR,
+                                        "Unable to query format (%d)", status);
+                                auto format = static_cast<android_pixel_format_t>(
+                                        intFormat);
 
-                            mHwc->allocateVirtualDisplay(width, height, &format,
-                                    &hwcId);
+                                mHwc->allocateVirtualDisplay(width, height, &format,
+                                        &hwcId);
+                            }
 
                             // TODO: Plumb requested format back up to consumer
 
@@ -2371,7 +2378,9 @@
     }
 
     if (transactionFlags) {
-        mInterceptor.saveLayerUpdates(state, flags);
+        if (mInterceptor.isEnabled()) {
+            mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
+        }
 
         // this triggers the transaction
         setTransactionFlags(transactionFlags);
@@ -2567,7 +2576,7 @@
     if (result != NO_ERROR) {
         return result;
     }
-    mInterceptor.saveLayerCreate(layer);
+    mInterceptor.saveSurfaceCreation(layer);
 
     setTransactionFlags(eTransactionNeeded);
     return result;
@@ -2615,7 +2624,7 @@
     status_t err = NO_ERROR;
     sp<Layer> l(client->getLayerUser(handle));
     if (l != NULL) {
-        mInterceptor.saveLayerDelete(l);
+        mInterceptor.saveSurfaceDeletion(l);
         err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -2687,6 +2696,16 @@
         return;
     }
 
+    if (mInterceptor.isEnabled()) {
+        Mutex::Autolock _l(mStateLock);
+        ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
+        if (idx < 0) {
+            ALOGW("Surface Interceptor SavePowerMode: invalid display token");
+            return;
+        }
+        mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+    }
+
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
@@ -3356,7 +3375,7 @@
                 n = data.readInt32();
                 if (n) {
                     ALOGV("Interceptor enabled");
-                    mInterceptor.enable(mDrawingState.layersSortedByZ);
+                    mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
                 }
                 else{
                     ALOGV("Interceptor disabled");
@@ -3364,6 +3383,11 @@
                 }
                 return NO_ERROR;
             }
+            case 1021: { // Disable HWC virtual displays
+                n = data.readInt32();
+                mUseHwcVirtualDisplays = !n;
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -3884,31 +3908,6 @@
     return l->sequence - r->sequence;
 }
 
-// ---------------------------------------------------------------------------
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
-    : type(DisplayDevice::DISPLAY_ID_INVALID),
-      layerStack(DisplayDevice::NO_LAYER_STACK),
-      orientation(0),
-      width(0),
-      height(0),
-      isSecure(false) {
-}
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
-    DisplayDevice::DisplayType type, bool isSecure)
-    : type(type),
-      layerStack(DisplayDevice::NO_LAYER_STACK),
-      orientation(0),
-      width(0),
-      height(0),
-      isSecure(isSecure) {
-    viewport.makeInvalid();
-    frame.makeInvalid();
-}
-
-// ---------------------------------------------------------------------------
-
 }; // namespace android
 
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 00790b1..6449e57 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -175,23 +175,6 @@
         virtual int do_compare(const void* lhs, const void* rhs) const;
     };
 
-    struct DisplayDeviceState {
-        DisplayDeviceState();
-        DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
-        bool isValid() const { return type >= 0; }
-        bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
-        bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
-        DisplayDevice::DisplayType type;
-        sp<IGraphicBufferProducer> surface;
-        uint32_t layerStack;
-        Rect viewport;
-        Rect frame;
-        uint8_t orientation;
-        uint32_t width, height;
-        String8 displayName;
-        bool isSecure;
-    };
-
     struct State {
         LayerVector layersSortedByZ;
         DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
@@ -539,6 +522,7 @@
     bool mPropagateBackpressure = true;
 #endif
     SurfaceInterceptor mInterceptor;
+    bool mUseHwcVirtualDisplays = true;
 
     // these are thread safe
     mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index bccefe8..97ad9b2 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -196,6 +196,10 @@
     }
     ALOGI_IF(mDebugRegion, "showupdates enabled");
     ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+    property_get("debug.sf.disable_hwc_vds", value, "0");
+    mUseHwcVirtualDisplays = !atoi(value);
+    ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -255,7 +259,7 @@
     DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
     info.displayName = displayName;
     mCurrentState.displays.add(token, info);
-
+    mInterceptor.saveDisplayCreation(info);
     return token;
 }
 
@@ -273,7 +277,7 @@
         ALOGE("destroyDisplay called for non-virtual display");
         return;
     }
-
+    mInterceptor.saveDisplayDeletion(info.displayId);
     mCurrentState.displays.removeItemsAt(idx);
     setTransactionFlags(eDisplayTransactionNeeded);
 }
@@ -285,6 +289,7 @@
     // All non-virtual displays are currently considered secure.
     DisplayDeviceState info(type, true);
     mCurrentState.displays.add(mBuiltinDisplays[type], info);
+    mInterceptor.saveDisplayCreation(info);
 }
 
 sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
@@ -494,10 +499,10 @@
     // start the EventThread
     sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
             vsyncPhaseOffsetNs, true, "app");
-    mEventThread = new EventThread(vsyncSrc, *this);
+    mEventThread = new EventThread(vsyncSrc, *this, false);
     sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
             sfVsyncPhaseOffsetNs, true, "sf");
-    mSFEventThread = new EventThread(sfVsyncSrc, *this);
+    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
     mEventQueue.setEventThread(mSFEventThread);
 
     // set SFEventThread to SCHED_FIFO to minimize jitter
@@ -854,7 +859,7 @@
         ALOGV("VSync Injections enabled");
         if (mVSyncInjector.get() == nullptr) {
             mVSyncInjector = new InjectVSyncSource();
-            mInjectorEventThread = new EventThread(mVSyncInjector, *this);
+            mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
         }
         mEventQueue.setEventThread(mInjectorEventThread);
     } else {
@@ -1581,9 +1586,10 @@
                                     NATIVE_WINDOW_HEIGHT, &height);
                             ALOGE_IF(status != NO_ERROR,
                                     "Unable to query height (%d)", status);
-                            if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
+                            if (mUseHwcVirtualDisplays &&
+                                    (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
                                     (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
-                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION))) {
                                 hwcDisplayId = allocateHwcDisplayId(state.type);
                             }
 
@@ -2288,7 +2294,9 @@
     }
 
     if (transactionFlags) {
-        mInterceptor.saveLayerUpdates(state, flags);
+        if (mInterceptor.isEnabled()) {
+            mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
+        }
 
         // this triggers the transaction
         setTransactionFlags(transactionFlags);
@@ -2484,7 +2492,7 @@
     if (result != NO_ERROR) {
         return result;
     }
-    mInterceptor.saveLayerCreate(layer);
+    mInterceptor.saveSurfaceCreation(layer);
 
     setTransactionFlags(eTransactionNeeded);
     return result;
@@ -2532,7 +2540,7 @@
     status_t err = NO_ERROR;
     sp<Layer> l(client->getLayerUser(handle));
     if (l != NULL) {
-        mInterceptor.saveLayerDelete(l);
+        mInterceptor.saveSurfaceDeletion(l);
         err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -2604,6 +2612,16 @@
         return;
     }
 
+    if (mInterceptor.isEnabled()) {
+        Mutex::Autolock _l(mStateLock);
+        ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
+        if (idx < 0) {
+            ALOGW("Surface Interceptor SavePowerMode: invalid display token");
+            return;
+        }
+        mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+    }
+
     if (currentMode == HWC_POWER_MODE_OFF) {
         // Turn on the display
         getHwComposer().setPowerMode(type, mode);
@@ -3270,7 +3288,7 @@
                 n = data.readInt32();
                 if (n) {
                     ALOGV("Interceptor enabled");
-                    mInterceptor.enable(mDrawingState.layersSortedByZ);
+                    mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
                 }
                 else{
                     ALOGV("Interceptor disabled");
@@ -3278,6 +3296,11 @@
                 }
                 return NO_ERROR;
             }
+            case 1021: { // Disable HWC virtual displays
+                n = data.readInt32();
+                mUseHwcVirtualDisplays = !n;
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -3792,31 +3815,6 @@
     return l->sequence - r->sequence;
 }
 
-// ---------------------------------------------------------------------------
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
-    : type(DisplayDevice::DISPLAY_ID_INVALID),
-      layerStack(DisplayDevice::NO_LAYER_STACK),
-      orientation(0),
-      width(0),
-      height(0),
-      isSecure(false) {
-}
-
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
-    DisplayDevice::DisplayType type, bool isSecure)
-    : type(type),
-      layerStack(DisplayDevice::NO_LAYER_STACK),
-      orientation(0),
-      width(0),
-      height(0),
-      isSecure(isSecure) {
-    viewport.makeInvalid();
-    frame.makeInvalid();
-}
-
-// ---------------------------------------------------------------------------
-
 }; // namespace android
 
 
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index c860228..4ae3580 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #undef LOG_TAG
 #define LOG_TAG "SurfaceInterceptor"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -21,7 +20,6 @@
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceInterceptor.h"
-
 #include <cutils/log.h>
 
 #include <utils/Trace.h>
@@ -32,20 +30,24 @@
 
 // ----------------------------------------------------------------------------
 
-void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers) {
-    ATRACE_CALL();
+void SurfaceInterceptor::enable(const SortedVector<sp<Layer>>& layers,
+        const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays)
+{
     if (mEnabled) {
         return;
     }
+    ATRACE_CALL();
     mEnabled = true;
-    saveExistingLayers(layers);
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    saveExistingDisplaysLocked(displays);
+    saveExistingSurfacesLocked(layers);
 }
 
 void SurfaceInterceptor::disable() {
-    ATRACE_CALL();
     if (!mEnabled) {
         return;
     }
+    ATRACE_CALL();
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
     mEnabled = false;
     status_t err(writeProtoFileLocked());
@@ -54,21 +56,32 @@
     mTrace.Clear();
 }
 
-void SurfaceInterceptor::saveExistingLayers(const SortedVector<sp<Layer>>& layers) {
+bool SurfaceInterceptor::isEnabled() {
+    return mEnabled;
+}
+
+void SurfaceInterceptor::saveExistingDisplaysLocked(
+        const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays)
+{
+    // Caveat: The initial snapshot does not capture the power mode of the existing displays
     ATRACE_CALL();
-    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    for (const auto& layer : layers) {
-        saveLayerCreateLocked(layer);
-        saveInitialLayerStateLocked(layer);
+    for (size_t i = 0 ; i < displays.size() ; i++) {
+        addDisplayCreationLocked(createTraceIncrementLocked(), displays[i]);
+        addInitialDisplayStateLocked(createTraceIncrementLocked(), displays[i]);
     }
 }
 
-void SurfaceInterceptor::saveInitialLayerStateLocked(const sp<const Layer>& layer) {
+void SurfaceInterceptor::saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers) {
     ATRACE_CALL();
-    if (layer == nullptr) {
-        return;
+    for (const auto& layer : layers) {
+        addSurfaceCreationLocked(createTraceIncrementLocked(), layer);
+        addInitialSurfaceStateLocked(createTraceIncrementLocked(), layer);
     }
-    Increment* increment(addTraceIncrementLocked());
+}
+
+void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment,
+        const sp<const Layer>& layer)
+{
     Transaction* transaction(increment->mutable_transaction());
     transaction->set_synchronous(layer->mTransactionFlags & BnSurfaceComposer::eSynchronous);
     transaction->set_animation(layer->mTransactionFlags & BnSurfaceComposer::eAnimation);
@@ -77,13 +90,11 @@
     addPositionLocked(transaction, layerId, layer->mCurrentState.active.transform.tx(),
             layer->mCurrentState.active.transform.ty());
     addDepthLocked(transaction, layerId, layer->mCurrentState.z);
-    addSizeLocked(transaction, layerId, layer->mCurrentState.active.w,
-            layer->mCurrentState.active.h);
     addAlphaLocked(transaction, layerId, layer->mCurrentState.alpha);
     addTransparentRegionLocked(transaction, layerId, layer->mCurrentState.activeTransparentRegion);
     addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
     addCropLocked(transaction, layerId, layer->mCurrentState.crop);
-    if (layer->mCurrentState.handle != NULL) {
+    if (layer->mCurrentState.handle != nullptr) {
         addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.handle,
                 layer->mCurrentState.frameNumber);
     }
@@ -92,6 +103,20 @@
     addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
 }
 
+void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
+        const DisplayDeviceState& display)
+{
+    Transaction* transaction(increment->mutable_transaction());
+    transaction->set_synchronous(false);
+    transaction->set_animation(false);
+
+    addDisplaySurfaceLocked(transaction, display.displayId, display.surface);
+    addDisplayLayerStackLocked(transaction, display.displayId, display.layerStack);
+    addDisplaySizeLocked(transaction, display.displayId, display.width, display.height);
+    addDisplayProjectionLocked(transaction, display.displayId, display.orientation,
+            display.viewport, display.frame);
+}
+
 status_t SurfaceInterceptor::writeProtoFileLocked() {
     ATRACE_CALL();
     std::ofstream output(mOutputFileName, std::ios::out | std::ios::trunc | std::ios::binary);
@@ -105,11 +130,8 @@
     return NO_ERROR;
 }
 
-void SurfaceInterceptor::setOutputFileName(const std::string& outputFileName) {
-    mOutputFileName = outputFileName;
-}
-
-const sp<const Layer> SurfaceInterceptor::getLayer(const sp<const IBinder>& handle) {
+const sp<const Layer> SurfaceInterceptor::getLayer(const wp<const IBinder>& weakHandle) {
+    const sp<const IBinder>& handle(weakHandle.promote());
     const auto layerHandle(static_cast<const Layer::Handle*>(handle.get()));
     const sp<const Layer> layer(layerHandle->owner.promote());
     // layer could be a nullptr at this point
@@ -124,18 +146,28 @@
     return layer->sequence;
 }
 
-Increment* SurfaceInterceptor::addTraceIncrementLocked() {
+Increment* SurfaceInterceptor::createTraceIncrementLocked() {
     Increment* increment(mTrace.add_increment());
     increment->set_time_stamp(systemTime());
     return increment;
 }
 
-Change* SurfaceInterceptor::addChangeLocked(Transaction* transaction, int32_t layerId) {
-    Change* change(transaction->add_change());
+SurfaceChange* SurfaceInterceptor::createSurfaceChangeLocked(Transaction* transaction,
+        int32_t layerId)
+{
+    SurfaceChange* change(transaction->add_surface_change());
     change->set_id(layerId);
     return change;
 }
 
+DisplayChange* SurfaceInterceptor::createDisplayChangeLocked(Transaction* transaction,
+        int32_t displayId)
+{
+    DisplayChange* dispChange(transaction->add_display_change());
+    dispChange->set_id(displayId);
+    return dispChange;
+}
+
 void SurfaceInterceptor::setProtoRectLocked(Rectangle* protoRect, const Rect& rect) {
     protoRect->set_left(rect.left);
     protoRect->set_top(rect.top);
@@ -143,17 +175,19 @@
     protoRect->set_bottom(rect.bottom);
 }
 
-void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId, float x,
-        float y)
+void SurfaceInterceptor::addPositionLocked(Transaction* transaction, int32_t layerId,
+        float x, float y)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     PositionChange* posChange(change->mutable_position());
     posChange->set_x(x);
     posChange->set_y(y);
 }
 
-void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z) {
-    Change* change(addChangeLocked(transaction, layerId));
+void SurfaceInterceptor::addDepthLocked(Transaction* transaction, int32_t layerId,
+        uint32_t z)
+{
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     LayerChange* depthChange(change->mutable_layer());
     depthChange->set_layer(z);
 }
@@ -161,14 +195,16 @@
 void SurfaceInterceptor::addSizeLocked(Transaction* transaction, int32_t layerId, uint32_t w,
         uint32_t h)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     SizeChange* sizeChange(change->mutable_size());
     sizeChange->set_w(w);
     sizeChange->set_h(h);
 }
 
-void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId, float alpha) {
-    Change* change(addChangeLocked(transaction, layerId));
+void SurfaceInterceptor::addAlphaLocked(Transaction* transaction, int32_t layerId,
+        float alpha)
+{
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     AlphaChange* alphaChange(change->mutable_alpha());
     alphaChange->set_alpha(alpha);
 }
@@ -176,7 +212,7 @@
 void SurfaceInterceptor::addMatrixLocked(Transaction* transaction, int32_t layerId,
         const layer_state_t::matrix22_t& matrix)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     MatrixChange* matrixChange(change->mutable_matrix());
     matrixChange->set_dsdx(matrix.dsdx);
     matrixChange->set_dtdx(matrix.dtdx);
@@ -184,10 +220,10 @@
     matrixChange->set_dtdy(matrix.dtdy);
 }
 
-void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction, int32_t layerId,
-        const Region& transRegion)
+void SurfaceInterceptor::addTransparentRegionLocked(Transaction* transaction,
+        int32_t layerId, const Region& transRegion)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     TransparentRegionHintChange* transparentChange(change->mutable_transparent_region_hint());
 
     for (const auto& rect : transRegion) {
@@ -196,20 +232,22 @@
     }
 }
 
-void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags) {
+void SurfaceInterceptor::addFlagsLocked(Transaction* transaction, int32_t layerId,
+        uint8_t flags)
+{
     // There can be multiple flags changed
     if (flags & layer_state_t::eLayerHidden) {
-        Change* change(addChangeLocked(transaction, layerId));
+        SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         HiddenFlagChange* flagChange(change->mutable_hidden_flag());
         flagChange->set_hidden_flag(true);
     }
     if (flags & layer_state_t::eLayerOpaque) {
-        Change* change(addChangeLocked(transaction, layerId));
+        SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         OpaqueFlagChange* flagChange(change->mutable_opaque_flag());
         flagChange->set_opaque_flag(true);
     }
     if (flags & layer_state_t::eLayerSecure) {
-        Change* change(addChangeLocked(transaction, layerId));
+        SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
         SecureFlagChange* flagChange(change->mutable_secure_flag());
         flagChange->set_secure_flag(true);
     }
@@ -218,7 +256,7 @@
 void SurfaceInterceptor::addLayerStackLocked(Transaction* transaction, int32_t layerId,
         uint32_t layerStack)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     LayerStackChange* layerStackChange(change->mutable_layer_stack());
     layerStackChange->set_layer_stack(layerStack);
 }
@@ -226,7 +264,7 @@
 void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId,
         const Rect& rect)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     CropChange* cropChange(change->mutable_crop());
     Rectangle* protoRect(cropChange->mutable_rectangle());
     setProtoRectLocked(protoRect, rect);
@@ -235,17 +273,17 @@
 void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId,
         const Rect& rect)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     FinalCropChange* finalCropChange(change->mutable_final_crop());
     Rectangle* protoRect(finalCropChange->mutable_rectangle());
     setProtoRectLocked(protoRect, rect);
 }
 
 void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
-        const sp<const IBinder>& handle, uint64_t frameNumber)
+        const wp<const IBinder>& weakHandle, uint64_t frameNumber)
 {
-    Change* change(addChangeLocked(transaction, layerId));
-    const sp<const Layer> layer(getLayer(handle));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
+    const sp<const Layer> layer(getLayer(weakHandle));
     if (layer == nullptr) {
         ALOGE("An existing layer could not be retrieved with the handle"
                 " for the deferred transaction");
@@ -256,15 +294,15 @@
     deferTransaction->set_frame_number(frameNumber);
 }
 
-void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
-        int32_t overrideScalingMode)
+void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction,
+        int32_t layerId, int32_t overrideScalingMode)
 {
-    Change* change(addChangeLocked(transaction, layerId));
+    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
     OverrideScalingModeChange* overrideChange(change->mutable_override_scaling_mode());
     overrideChange->set_override_scaling_mode(overrideScalingMode);
 }
 
-void SurfaceInterceptor::addChangedPropertiesLocked(Transaction* transaction,
+void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction,
         const layer_state_t& state)
 {
     const sp<const Layer> layer(getLayer(state.surface));
@@ -314,31 +352,62 @@
     }
 }
 
-void SurfaceInterceptor::addUpdatedLayersLocked(Increment* increment, uint32_t flags,
-        const Vector<ComposerState>& stateUpdates)
+void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
+        const DisplayState& state, int32_t displayId)
 {
-    Transaction* transaction(increment->mutable_transaction());
-    transaction->set_synchronous(flags & BnSurfaceComposer::eSynchronous);
-    transaction->set_animation(flags & BnSurfaceComposer::eAnimation);
-    for (const auto& compState: stateUpdates) {
-        addChangedPropertiesLocked(transaction, compState.state);
+    if (state.what & DisplayState::eSurfaceChanged) {
+        addDisplaySurfaceLocked(transaction, displayId, state.surface);
+    }
+    if (state.what & DisplayState::eLayerStackChanged) {
+        addDisplayLayerStackLocked(transaction, displayId, state.layerStack);
+    }
+    if (state.what & DisplayState::eDisplaySizeChanged) {
+        addDisplaySizeLocked(transaction, displayId, state.width, state.height);
+    }
+    if (state.what & DisplayState::eDisplayProjectionChanged) {
+        addDisplayProjectionLocked(transaction, displayId, state.orientation, state.viewport,
+                state.frame);
     }
 }
 
-void SurfaceInterceptor::addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer) {
-    Create* create(increment->mutable_create());
-    create->set_id(getLayerId(layer));
-    create->set_name(getLayerName(layer));
-    create->set_w(layer->mCurrentState.active.w);
-    create->set_h(layer->mCurrentState.active.h);
+void SurfaceInterceptor::addTransactionLocked(Increment* increment,
+        const Vector<ComposerState>& stateUpdates,
+        const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+        const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags)
+{
+    Transaction* transaction(increment->mutable_transaction());
+    transaction->set_synchronous(transactionFlags & BnSurfaceComposer::eSynchronous);
+    transaction->set_animation(transactionFlags & BnSurfaceComposer::eAnimation);
+    for (const auto& compState: stateUpdates) {
+        addSurfaceChangesLocked(transaction, compState.state);
+    }
+    for (const auto& disp: changedDisplays) {
+        ssize_t dpyIdx = displays.indexOfKey(disp.token);
+        if (dpyIdx >= 0) {
+            const DisplayDeviceState& dispState(displays.valueAt(dpyIdx));
+            addDisplayChangesLocked(transaction, disp, dispState.displayId);
+        }
+    }
 }
 
-void SurfaceInterceptor::addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer) {
-    Delete* deleteLayer(increment->mutable_delete_());
-    deleteLayer->set_id(getLayerId(layer));
+void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment,
+        const sp<const Layer>& layer)
+{
+    SurfaceCreation* creation(increment->mutable_surface_creation());
+    creation->set_id(getLayerId(layer));
+    creation->set_name(getLayerName(layer));
+    creation->set_w(layer->mCurrentState.active.w);
+    creation->set_h(layer->mCurrentState.active.h);
 }
 
-void SurfaceInterceptor::addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer,
+void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
+        const sp<const Layer>& layer)
+{
+    SurfaceDeletion* deletion(increment->mutable_surface_deletion());
+    deletion->set_id(getLayerId(layer));
+}
+
+void SurfaceInterceptor::addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer,
         uint32_t width, uint32_t height, uint64_t frameNumber)
 {
     BufferUpdate* update(increment->mutable_buffer_update());
@@ -348,56 +417,123 @@
     update->set_frame_number(frameNumber);
 }
 
-void SurfaceInterceptor::addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp) {
+void SurfaceInterceptor::addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp) {
     VSyncEvent* event(increment->mutable_vsync_event());
     event->set_when(timestamp);
 }
 
-void SurfaceInterceptor::saveLayerUpdates(const Vector<ComposerState>& stateUpdates,
-        uint32_t flags)
+void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+        const sp<const IGraphicBufferProducer>& surface)
 {
-    ATRACE_CALL();
-    if (!mEnabled || stateUpdates.size() <= 0) {
+    if (surface == nullptr) {
         return;
     }
-    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    addUpdatedLayersLocked(addTraceIncrementLocked(), flags, stateUpdates);
+    uint64_t bufferQueueId = 0;
+    status_t err(surface->getUniqueId(&bufferQueueId));
+    if (err == NO_ERROR) {
+        DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+        DispSurfaceChange* surfaceChange(dispChange->mutable_surface());
+        surfaceChange->set_buffer_queue_id(bufferQueueId);
+        surfaceChange->set_buffer_queue_name(surface->getConsumerName().string());
+    }
+    else {
+        ALOGE("invalid graphic buffer producer received while tracing a display change (%s)",
+                strerror(-err));
+    }
 }
 
-void SurfaceInterceptor::saveLayerCreate(const sp<const Layer>& layer) {
+void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction,
+        int32_t displayId, uint32_t layerStack)
+{
+    DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+    LayerStackChange* layerStackChange(dispChange->mutable_layer_stack());
+    layerStackChange->set_layer_stack(layerStack);
+}
+
+void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t displayId,
+        uint32_t w, uint32_t h)
+{
+    DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+    SizeChange* sizeChange(dispChange->mutable_size());
+    sizeChange->set_w(w);
+    sizeChange->set_h(h);
+}
+
+void SurfaceInterceptor::addDisplayProjectionLocked(Transaction* transaction,
+        int32_t displayId, int32_t orientation, const Rect& viewport, const Rect& frame)
+{
+    DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+    ProjectionChange* projectionChange(dispChange->mutable_projection());
+    projectionChange->set_orientation(orientation);
+    Rectangle* viewportRect(projectionChange->mutable_viewport());
+    setProtoRectLocked(viewportRect, viewport);
+    Rectangle* frameRect(projectionChange->mutable_frame());
+    setProtoRectLocked(frameRect, frame);
+}
+
+void SurfaceInterceptor::addDisplayCreationLocked(Increment* increment,
+        const DisplayDeviceState& info)
+{
+    DisplayCreation* creation(increment->mutable_display_creation());
+    creation->set_id(info.displayId);
+    creation->set_name(info.displayName);
+    creation->set_type(info.type);
+    creation->set_is_secure(info.isSecure);
+}
+
+void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t displayId) {
+    DisplayDeletion* deletion(increment->mutable_display_deletion());
+    deletion->set_id(displayId);
+}
+
+void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t displayId,
+        int32_t mode)
+{
+    PowerModeUpdate* powerModeUpdate(increment->mutable_power_mode_update());
+    powerModeUpdate->set_id(displayId);
+    powerModeUpdate->set_mode(mode);
+}
+
+void SurfaceInterceptor::saveTransaction(const Vector<ComposerState>& stateUpdates,
+        const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+        const Vector<DisplayState>& changedDisplays, uint32_t flags)
+{
+    if (!mEnabled || (stateUpdates.size() <= 0 && changedDisplays.size() <= 0)) {
+        return;
+    }
     ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    addTransactionLocked(createTraceIncrementLocked(), stateUpdates, displays, changedDisplays,
+            flags);
+}
+
+void SurfaceInterceptor::saveSurfaceCreation(const sp<const Layer>& layer) {
     if (!mEnabled || layer == nullptr) {
         return;
     }
-    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    addCreatedLayerLocked(addTraceIncrementLocked(), layer);
-}
-
-void SurfaceInterceptor::saveLayerCreateLocked(const sp<const Layer>& layer) {
-    if (!mEnabled || layer == nullptr) {
-        return;
-    }
-    addCreatedLayerLocked(addTraceIncrementLocked(), layer);
-}
-
-void SurfaceInterceptor::saveLayerDelete(const sp<const Layer>& layer) {
     ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    addSurfaceCreationLocked(createTraceIncrementLocked(), layer);
+}
+
+void SurfaceInterceptor::saveSurfaceDeletion(const sp<const Layer>& layer) {
     if (!mEnabled || layer == nullptr) {
         return;
     }
+    ATRACE_CALL();
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    addDeletedLayerLocked(addTraceIncrementLocked(), layer);
+    addSurfaceDeletionLocked(createTraceIncrementLocked(), layer);
 }
 
 void SurfaceInterceptor::saveBufferUpdate(const sp<const Layer>& layer, uint32_t width,
         uint32_t height, uint64_t frameNumber)
 {
-    ATRACE_CALL();
     if (!mEnabled || layer == nullptr) {
         return;
     }
+    ATRACE_CALL();
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    addUpdatedBufferLocked(addTraceIncrementLocked(), layer, width, height, frameNumber);
+    addBufferUpdateLocked(createTraceIncrementLocked(), layer, width, height, frameNumber);
 }
 
 void SurfaceInterceptor::saveVSyncEvent(nsecs_t timestamp) {
@@ -405,7 +541,35 @@
         return;
     }
     std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-    addUpdatedVsyncLocked(addTraceIncrementLocked(), timestamp);
+    addVSyncUpdateLocked(createTraceIncrementLocked(), timestamp);
 }
 
+void SurfaceInterceptor::saveDisplayCreation(const DisplayDeviceState& info) {
+    if (!mEnabled) {
+        return;
+    }
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    addDisplayCreationLocked(createTraceIncrementLocked(), info);
+}
+
+void SurfaceInterceptor::saveDisplayDeletion(int32_t displayId) {
+    if (!mEnabled) {
+        return;
+    }
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    addDisplayDeletionLocked(createTraceIncrementLocked(), displayId);
+}
+
+void SurfaceInterceptor::savePowerModeUpdate(int32_t displayId, int32_t mode) {
+    if (!mEnabled) {
+        return;
+    }
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> protoGuard(mTraceMutex);
+    addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode);
+}
+
+
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index bc8174c..4695138 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -25,6 +25,7 @@
 
 class BufferItem;
 class Layer;
+struct DisplayState;
 struct layer_state_t;
 
 constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
@@ -35,37 +36,56 @@
  */
 class SurfaceInterceptor {
 public:
-    // The layer vector is used to capture the inital snapshot in the trace
-    void enable(const SortedVector<sp<Layer>>& layers);
+    // Both vectors are used to capture the current state of SF as the initial snapshot in the trace
+    void enable(const SortedVector<sp<Layer>>& layers,
+            const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
     void disable();
-    void setOutputFileName(const std::string& OutputFileName);
+    bool isEnabled();
 
-    void saveLayerUpdates(const Vector<ComposerState>& state, uint32_t flags);
-    void saveLayerCreate(const sp<const Layer>& layer);
-    void saveLayerDelete(const sp<const Layer>& layer);
+    // Intercept display and surface transactions
+    void saveTransaction(const Vector<ComposerState>& stateUpdates,
+            const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+            const Vector<DisplayState>& changedDisplays, uint32_t flags);
+
+    // Intercept surface data
+    void saveSurfaceCreation(const sp<const Layer>& layer);
+    void saveSurfaceDeletion(const sp<const Layer>& layer);
     void saveBufferUpdate(const sp<const Layer>& layer, uint32_t width, uint32_t height,
             uint64_t frameNumber);
+
+    // Intercept display data
+    void saveDisplayCreation(const DisplayDeviceState& info);
+    void saveDisplayDeletion(int32_t displayId);
+    void savePowerModeUpdate(int32_t displayId, int32_t mode);
     void saveVSyncEvent(nsecs_t timestamp);
 
 private:
-    void saveExistingLayers(const SortedVector<sp<Layer>>& layers);
-    void saveInitialLayerStateLocked(const sp<const Layer>& layer);
-    void saveLayerCreateLocked(const sp<const Layer>& layer);
+    // The creation increments of Surfaces and Displays do not contain enough information to capture
+    // the initial state of each object, so a transaction with all of the missing properties is
+    // performed at the initial snapshot for each display and surface.
+    void saveExistingDisplaysLocked(
+            const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays);
+    void saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers);
+    void addInitialSurfaceStateLocked(Increment* increment, const sp<const Layer>& layer);
+    void addInitialDisplayStateLocked(Increment* increment, const DisplayDeviceState& display);
+
     status_t writeProtoFileLocked();
-    const sp<const Layer> getLayer(const sp<const IBinder>& handle);
+    const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle);
     const std::string getLayerName(const sp<const Layer>& layer);
     int32_t getLayerId(const sp<const Layer>& layer);
-    Increment* addTraceIncrementLocked();
 
-    void addUpdatedLayersLocked(Increment* increment, uint32_t flags,
-            const Vector<ComposerState>& stateUpdates);
-    void addCreatedLayerLocked(Increment* increment, const sp<const Layer>& layer);
-    void addDeletedLayerLocked(Increment* increment, const sp<const Layer>& layer);
-    void addUpdatedBufferLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
+    Increment* createTraceIncrementLocked();
+    void addSurfaceCreationLocked(Increment* increment, const sp<const Layer>& layer);
+    void addSurfaceDeletionLocked(Increment* increment, const sp<const Layer>& layer);
+    void addBufferUpdateLocked(Increment* increment, const sp<const Layer>& layer, uint32_t width,
             uint32_t height, uint64_t frameNumber);
-    void addUpdatedVsyncLocked(Increment* increment, nsecs_t timestamp);
+    void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp);
+    void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info);
+    void addDisplayDeletionLocked(Increment* increment, int32_t displayId);
+    void addPowerModeUpdateLocked(Increment* increment, int32_t displayId, int32_t mode);
 
-    Change* addChangeLocked(Transaction* transaction, int32_t layerId);
+    // Add surface transactions to the trace
+    SurfaceChange* createSurfaceChangeLocked(Transaction* transaction, int32_t layerId);
     void setProtoRectLocked(Rectangle* protoRect, const Rect& rect);
     void addPositionLocked(Transaction* transaction, int32_t layerId, float x, float y);
     void addDepthLocked(Transaction* transaction, int32_t layerId, uint32_t z);
@@ -79,11 +99,28 @@
     void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
     void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
-            const sp<const IBinder>& handle, uint64_t frameNumber);
+            const wp<const IBinder>& weakHandle, uint64_t frameNumber);
     void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
             int32_t overrideScalingMode);
-    void addChangedPropertiesLocked(Transaction* transaction, const layer_state_t& state);
+    void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state);
+    void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates,
+            const DefaultKeyedVector< wp<IBinder>, DisplayDeviceState>& displays,
+            const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags);
+
+    // Add display transactions to the trace
+    DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t displayId);
+    void addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+            const sp<const IGraphicBufferProducer>& surface);
+    void addDisplayLayerStackLocked(Transaction* transaction, int32_t displayId,
+            uint32_t layerStack);
+    void addDisplaySizeLocked(Transaction* transaction, int32_t displayId, uint32_t w,
+            uint32_t h);
+    void addDisplayProjectionLocked(Transaction* transaction, int32_t displayId,
+            int32_t orientation, const Rect& viewport, const Rect& frame);
+    void addDisplayChangesLocked(Transaction* transaction,
+            const DisplayState& state, int32_t displayId);
+
 
     bool mEnabled {false};
     std::string mOutputFileName {DEFAULT_FILENAME};
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index ebc4dd1..1a3f89f 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <frameworks/native/cmds/surfacecapturereplay/proto/src/trace.pb.h>
+#include <frameworks/native/cmds/surfacereplayer/proto/src/trace.pb.h>
 
 #include <gtest/gtest.h>
 
@@ -23,6 +23,7 @@
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
 #include <private/gui/LayerState.h>
 #include <ui/DisplayInfo.h>
 
@@ -42,6 +43,7 @@
 constexpr float POSITION_UPDATE = 121;
 const Rect CROP_UPDATE(16, 16, 32, 32);
 
+const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
 constexpr auto LAYER_NAME = "Layer Create and Delete Test";
 
 constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
@@ -81,16 +83,16 @@
     system("service call SurfaceFlinger 1020 i32 0 > /dev/null");
 }
 
-uint32_t getLayerId(const std::string& layerName) {
+int32_t getSurfaceId(const std::string& surfaceName) {
     enableInterceptor();
     disableInterceptor();
     Trace capturedTrace;
     readProtoFile(&capturedTrace);
-    uint32_t layerId = 0;
+    int32_t layerId = 0;
     for (const auto& increment : *capturedTrace.mutable_increment()) {
-        if (increment.increment_case() == increment.kCreate) {
-            if (increment.create().name() == layerName) {
-                layerId = increment.create().id();
+        if (increment.increment_case() == increment.kSurfaceCreation) {
+            if (increment.surface_creation().name() == surfaceName) {
+                layerId = increment.surface_creation().id();
                 break;
             }
         }
@@ -98,6 +100,23 @@
     return layerId;
 }
 
+int32_t getDisplayId(const std::string& displayName) {
+    enableInterceptor();
+    disableInterceptor();
+    Trace capturedTrace;
+    readProtoFile(&capturedTrace);
+    int32_t displayId = 0;
+    for (const auto& increment : *capturedTrace.mutable_increment()) {
+        if (increment.increment_case() == increment.kDisplayCreation) {
+            if (increment.display_creation().name() == displayName) {
+                displayId = increment.display_creation().id();
+                break;
+            }
+        }
+    }
+    return displayId;
+}
+
 class SurfaceInterceptorTest : public ::testing::Test {
 protected:
     virtual void SetUp() {
@@ -120,7 +139,7 @@
                 PIXEL_FORMAT_RGBA_8888, 0);
         ASSERT_TRUE(mBGSurfaceControl != NULL);
         ASSERT_TRUE(mBGSurfaceControl->isValid());
-        mBGLayerId = getLayerId("BG Interceptor Test Surface");
+        mBGLayerId = getSurfaceId("BG Interceptor Test Surface");
 
         SurfaceComposerClient::openGlobalTransaction();
         mComposerClient->setDisplayLayerStack(display, 0);
@@ -137,35 +156,43 @@
 
     sp<SurfaceComposerClient> mComposerClient;
     sp<SurfaceControl> mBGSurfaceControl;
-    uint32_t mBGLayerId;
+    int32_t mBGLayerId;
+    // Used to verify creation and destruction of surfaces and displays
+    int32_t mTargetId;
 
 public:
     void captureTest(void (SurfaceInterceptorTest::* action)(void),
             bool (SurfaceInterceptorTest::* verification)(Trace *));
-    void captureTest(void (SurfaceInterceptorTest::* action)(void), Change::ChangeCase changeCase);
+    void captureTest(void (SurfaceInterceptorTest::* action)(void),
+            SurfaceChange::SurfaceChangeCase changeCase);
+    void captureTest(void (SurfaceInterceptorTest::* action)(void),
+            Increment::IncrementCase incrementCase);
     void runInTransaction(void (SurfaceInterceptorTest::* action)(void), bool intercepted = false);
 
     // Verification of changes to a surface
-    bool positionUpdateFound(const Change& change, bool foundPosition);
-    bool sizeUpdateFound(const Change& change, bool foundSize);
-    bool alphaUpdateFound(const Change& change, bool foundAlpha);
-    bool layerUpdateFound(const Change& change, bool foundLayer);
-    bool cropUpdateFound(const Change& change, bool foundCrop);
-    bool finalCropUpdateFound(const Change& change, bool foundFinalCrop);
-    bool matrixUpdateFound(const Change& change, bool foundMatrix);
-    bool scalingModeUpdateFound(const Change& change, bool foundScalingMode);
-    bool transparentRegionHintUpdateFound(const Change& change, bool foundTransparentRegion);
-    bool layerStackUpdateFound(const Change& change, bool foundLayerStack);
-    bool hiddenFlagUpdateFound(const Change& change, bool foundHiddenFlag);
-    bool opaqueFlagUpdateFound(const Change& change, bool foundOpaqueFlag);
-    bool secureFlagUpdateFound(const Change& change, bool foundSecureFlag);
-    bool deferredTransactionUpdateFound(const Change& change, bool foundDeferred);
-    bool surfaceUpdateFound(Trace* trace, Change::ChangeCase changeCase);
+    bool positionUpdateFound(const SurfaceChange& change, bool foundPosition);
+    bool sizeUpdateFound(const SurfaceChange& change, bool foundSize);
+    bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha);
+    bool layerUpdateFound(const SurfaceChange& change, bool foundLayer);
+    bool cropUpdateFound(const SurfaceChange& change, bool foundCrop);
+    bool finalCropUpdateFound(const SurfaceChange& change, bool foundFinalCrop);
+    bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix);
+    bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode);
+    bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion);
+    bool layerStackUpdateFound(const SurfaceChange& change, bool foundLayerStack);
+    bool hiddenFlagUpdateFound(const SurfaceChange& change, bool foundHiddenFlag);
+    bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
+    bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
+    bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
+    bool surfaceUpdateFound(Trace* trace, SurfaceChange::SurfaceChangeCase changeCase);
     void assertAllUpdatesFound(Trace* trace);
 
     // Verification of creation and deletion of a surface
-    bool surfaceCreateFound(Trace* trace);
-    bool surfaceDeleteFound(Trace* trace, uint32_t targetLayerId);
+    bool surfaceCreationFound(const Increment& increment, bool foundSurface);
+    bool surfaceDeletionFound(const Increment& increment, bool foundSurface);
+    bool displayCreationFound(const Increment& increment, bool foundDisplay);
+    bool displayDeletionFound(const Increment& increment, bool foundDisplay);
+    bool singleIncrementFound(Trace* trace, Increment::IncrementCase incrementCase);
 
     // Verification of buffer updates
     bool bufferUpdatesFound(Trace* trace);
@@ -186,8 +213,10 @@
     void secureFlagUpdate();
     void deferredTransactionUpdate();
     void runAllUpdates();
-    void surfaceCreate();
+    void surfaceCreation();
     void nBufferUpdates();
+    void displayCreation();
+    void displayDeletion();
 };
 
 void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
@@ -200,7 +229,16 @@
 }
 
 void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
-        Change::ChangeCase changeCase)
+        Increment::IncrementCase incrementCase)
+{
+    runInTransaction(action, true);
+    Trace capturedTrace;
+    ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+    ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase));
+}
+
+void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(void),
+        SurfaceChange::SurfaceChangeCase changeCase)
 {
     runInTransaction(action, true);
     Trace capturedTrace;
@@ -279,6 +317,17 @@
     mBGSurfaceControl->deferTransactionUntil(mBGSurfaceControl->getHandle(), DEFERRED_UPDATE);
 }
 
+void SurfaceInterceptorTest::displayCreation() {
+    sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
+    SurfaceComposerClient::destroyDisplay(testDisplay);
+}
+
+void SurfaceInterceptorTest::displayDeletion() {
+    sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
+    mTargetId = getDisplayId(DISPLAY_NAME.string());
+    SurfaceComposerClient::destroyDisplay(testDisplay);
+}
+
 void SurfaceInterceptorTest::runAllUpdates() {
     runInTransaction(&SurfaceInterceptorTest::positionUpdate);
     runInTransaction(&SurfaceInterceptorTest::sizeUpdate);
@@ -296,7 +345,7 @@
     runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
 }
 
-void SurfaceInterceptorTest::surfaceCreate() {
+void SurfaceInterceptorTest::surfaceCreation() {
     mComposerClient->createSurface(String8(LAYER_NAME), SIZE_UPDATE, SIZE_UPDATE,
             PIXEL_FORMAT_RGBA_8888, 0);
 }
@@ -311,7 +360,7 @@
     }
 }
 
-bool SurfaceInterceptorTest::positionUpdateFound(const Change& change, bool foundPosition) {
+bool SurfaceInterceptorTest::positionUpdateFound(const SurfaceChange& change, bool foundPosition) {
     // There should only be one position transaction with x and y = POSITION_UPDATE
     bool hasX(change.position().x() == POSITION_UPDATE);
     bool hasY(change.position().y() == POSITION_UPDATE);
@@ -325,7 +374,7 @@
     return foundPosition;
 }
 
-bool SurfaceInterceptorTest::sizeUpdateFound(const Change& change, bool foundSize) {
+bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange& change, bool foundSize) {
     bool hasWidth(change.size().h() == SIZE_UPDATE);
     bool hasHeight(change.size().w() == SIZE_UPDATE);
     if (hasWidth && hasHeight && !foundSize) {
@@ -337,7 +386,7 @@
     return foundSize;
 }
 
-bool SurfaceInterceptorTest::alphaUpdateFound(const Change& change, bool foundAlpha) {
+bool SurfaceInterceptorTest::alphaUpdateFound(const SurfaceChange& change, bool foundAlpha) {
     bool hasAlpha(change.alpha().alpha() == ALPHA_UPDATE);
     if (hasAlpha && !foundAlpha) {
         foundAlpha = true;
@@ -348,7 +397,7 @@
     return foundAlpha;
 }
 
-bool SurfaceInterceptorTest::layerUpdateFound(const Change& change, bool foundLayer) {
+bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool foundLayer) {
     bool hasLayer(change.layer().layer() == LAYER_UPDATE);
     if (hasLayer && !foundLayer) {
         foundLayer = true;
@@ -359,7 +408,7 @@
     return foundLayer;
 }
 
-bool SurfaceInterceptorTest::cropUpdateFound(const Change& change, bool foundCrop) {
+bool SurfaceInterceptorTest::cropUpdateFound(const SurfaceChange& change, bool foundCrop) {
     bool hasLeft(change.crop().rectangle().left() == CROP_UPDATE.left);
     bool hasTop(change.crop().rectangle().top() == CROP_UPDATE.top);
     bool hasRight(change.crop().rectangle().right() == CROP_UPDATE.right);
@@ -373,7 +422,9 @@
     return foundCrop;
 }
 
-bool SurfaceInterceptorTest::finalCropUpdateFound(const Change& change, bool foundFinalCrop) {
+bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change,
+        bool foundFinalCrop)
+{
     bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left);
     bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top);
     bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right);
@@ -387,7 +438,7 @@
     return foundFinalCrop;
 }
 
-bool SurfaceInterceptorTest::matrixUpdateFound(const Change& change, bool foundMatrix) {
+bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) {
     bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2);
     bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2);
     bool hasSy((float)change.matrix().dsdy() == (float)-M_SQRT1_2);
@@ -401,7 +452,9 @@
     return foundMatrix;
 }
 
-bool SurfaceInterceptorTest::scalingModeUpdateFound(const Change& change, bool foundScalingMode) {
+bool SurfaceInterceptorTest::scalingModeUpdateFound(const SurfaceChange& change,
+        bool foundScalingMode)
+{
     bool hasScalingUpdate(change.override_scaling_mode().override_scaling_mode() == SCALING_UPDATE);
     if (hasScalingUpdate && !foundScalingMode) {
         foundScalingMode = true;
@@ -412,7 +465,7 @@
     return foundScalingMode;
 }
 
-bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const Change& change,
+bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChange& change,
         bool foundTransparentRegion)
 {
     auto traceRegion = change.transparent_region_hint().region(0);
@@ -429,7 +482,9 @@
     return foundTransparentRegion;
 }
 
-bool SurfaceInterceptorTest::layerStackUpdateFound(const Change& change, bool foundLayerStack) {
+bool SurfaceInterceptorTest::layerStackUpdateFound(const SurfaceChange& change,
+        bool foundLayerStack)
+{
     bool hasLayerStackUpdate(change.layer_stack().layer_stack() == STACK_UPDATE);
     if (hasLayerStackUpdate && !foundLayerStack) {
         foundLayerStack = true;
@@ -440,7 +495,9 @@
     return foundLayerStack;
 }
 
-bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const Change& change, bool foundHiddenFlag) {
+bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const SurfaceChange& change,
+        bool foundHiddenFlag)
+{
     bool hasHiddenFlag(change.hidden_flag().hidden_flag());
     if (hasHiddenFlag && !foundHiddenFlag) {
         foundHiddenFlag = true;
@@ -451,7 +508,9 @@
     return foundHiddenFlag;
 }
 
-bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const Change& change, bool foundOpaqueFlag) {
+bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const SurfaceChange& change,
+        bool foundOpaqueFlag)
+{
     bool hasOpaqueFlag(change.opaque_flag().opaque_flag());
     if (hasOpaqueFlag && !foundOpaqueFlag) {
         foundOpaqueFlag = true;
@@ -462,7 +521,9 @@
     return foundOpaqueFlag;
 }
 
-bool SurfaceInterceptorTest::secureFlagUpdateFound(const Change& change, bool foundSecureFlag) {
+bool SurfaceInterceptorTest::secureFlagUpdateFound(const SurfaceChange& change,
+        bool foundSecureFlag)
+{
     bool hasSecureFlag(change.secure_flag().secure_flag());
     if (hasSecureFlag && !foundSecureFlag) {
         foundSecureFlag = true;
@@ -473,12 +534,11 @@
     return foundSecureFlag;
 }
 
-bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const Change& change,
+bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change,
         bool foundDeferred)
 {
     bool hasId(change.deferred_transaction().layer_id() == mBGLayerId);
-    bool hasFrameNumber(change.deferred_transaction().frame_number() ==
-            DEFERRED_UPDATE);
+    bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE);
     if (hasId && hasFrameNumber && !foundDeferred) {
         foundDeferred = true;
     }
@@ -488,114 +548,158 @@
     return foundDeferred;
 }
 
-bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace, Change::ChangeCase changeCase) {
-    bool updateFound = false;
+bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace,
+        SurfaceChange::SurfaceChangeCase changeCase)
+{
+    bool foundUpdate = false;
     for (const auto& increment : *trace->mutable_increment()) {
         if (increment.increment_case() == increment.kTransaction) {
-            for (const auto& change : increment.transaction().change()) {
-                if (change.id() == mBGLayerId && change.Change_case() == changeCase) {
+            for (const auto& change : increment.transaction().surface_change()) {
+                if (change.id() == mBGLayerId && change.SurfaceChange_case() == changeCase) {
                     switch (changeCase) {
-                        case Change::ChangeCase::kPosition:
-                            // updateFound is sent for the tests to fail on duplicated increments
-                            updateFound = positionUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kPosition:
+                            // foundUpdate is sent for the tests to fail on duplicated increments
+                            foundUpdate = positionUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kSize:
-                            updateFound = sizeUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kSize:
+                            foundUpdate = sizeUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kAlpha:
-                            updateFound = alphaUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kAlpha:
+                            foundUpdate = alphaUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kLayer:
-                            updateFound = layerUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kLayer:
+                            foundUpdate = layerUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kCrop:
-                            updateFound = cropUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kCrop:
+                            foundUpdate = cropUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kFinalCrop:
-                            updateFound = finalCropUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kFinalCrop:
+                            foundUpdate = finalCropUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kMatrix:
-                            updateFound = matrixUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kMatrix:
+                            foundUpdate = matrixUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kOverrideScalingMode:
-                            updateFound = scalingModeUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
+                            foundUpdate = scalingModeUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kTransparentRegionHint:
-                            updateFound = transparentRegionHintUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint:
+                            foundUpdate = transparentRegionHintUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kLayerStack:
-                            updateFound = layerStackUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kLayerStack:
+                            foundUpdate = layerStackUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kHiddenFlag:
-                            updateFound = hiddenFlagUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kHiddenFlag:
+                            foundUpdate = hiddenFlagUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kOpaqueFlag:
-                            updateFound = opaqueFlagUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kOpaqueFlag:
+                            foundUpdate = opaqueFlagUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kSecureFlag:
-                            updateFound = secureFlagUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kSecureFlag:
+                            foundUpdate = secureFlagUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::kDeferredTransaction:
-                            updateFound = deferredTransactionUpdateFound(change, updateFound);
+                        case SurfaceChange::SurfaceChangeCase::kDeferredTransaction:
+                            foundUpdate = deferredTransactionUpdateFound(change, foundUpdate);
                             break;
-                        case Change::ChangeCase::CHANGE_NOT_SET:
+                        case SurfaceChange::SurfaceChangeCase::SURFACECHANGE_NOT_SET:
                             break;
                     }
                 }
             }
         }
     }
-    return updateFound;
+    return foundUpdate;
 }
 
 void SurfaceInterceptorTest::assertAllUpdatesFound(Trace* trace) {
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kPosition));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kSize));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kAlpha));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kLayer));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kCrop));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kFinalCrop));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kMatrix));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kOverrideScalingMode));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kTransparentRegionHint));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kLayerStack));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kHiddenFlag));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kOpaqueFlag));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kSecureFlag));
-    ASSERT_TRUE(surfaceUpdateFound(trace, Change::ChangeCase::kDeferredTransaction));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kPosition));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSize));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kFinalCrop));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayerStack));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kHiddenFlag));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag));
+    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction));
 }
 
-bool SurfaceInterceptorTest::surfaceCreateFound(Trace* trace) {
-    bool foundLayer = false;
-    for (const auto& inc : *trace->mutable_increment()) {
-        if (inc.increment_case() == inc.kCreate) {
-            bool isMatch(inc.create().name() == LAYER_NAME && inc.create().w() == SIZE_UPDATE &&
-                    inc.create().h() == SIZE_UPDATE);
-            if (isMatch && !foundLayer) {
-                foundLayer = true;
-            }
-            else if (isMatch && foundLayer) {
-                return false;
-            }
-        }
+bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
+    bool isMatch(increment.surface_creation().name() == LAYER_NAME &&
+            increment.surface_creation().w() == SIZE_UPDATE &&
+            increment.surface_creation().h() == SIZE_UPDATE);
+    if (isMatch && !foundSurface) {
+        foundSurface = true;
     }
-    return foundLayer;
+    else if (isMatch && foundSurface) {
+        [] () { FAIL(); }();
+    }
+    return foundSurface;
 }
 
-bool SurfaceInterceptorTest::surfaceDeleteFound(Trace* trace, uint32_t targetLayerId) {
-    bool foundLayer = false;
+bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment, bool foundSurface) {
+    bool isMatch(increment.surface_deletion().id() == mTargetId);
+    if (isMatch && !foundSurface) {
+        foundSurface = true;
+    }
+    else if (isMatch && foundSurface) {
+        [] () { FAIL(); }();
+    }
+    return foundSurface;
+}
+
+bool SurfaceInterceptorTest::displayCreationFound(const Increment& increment, bool foundDisplay) {
+    bool isMatch(increment.display_creation().name() == DISPLAY_NAME.string() &&
+            increment.display_creation().is_secure());
+    if (isMatch && !foundDisplay) {
+        foundDisplay = true;
+    }
+    else if (isMatch && foundDisplay) {
+        [] () { FAIL(); }();
+    }
+    return foundDisplay;
+}
+
+bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment, bool foundDisplay) {
+    bool isMatch(increment.display_deletion().id() == mTargetId);
+    if (isMatch && !foundDisplay) {
+        foundDisplay = true;
+    }
+    else if (isMatch && foundDisplay) {
+        [] () { FAIL(); }();
+    }
+    return foundDisplay;
+}
+
+bool SurfaceInterceptorTest::singleIncrementFound(Trace* trace,
+        Increment::IncrementCase incrementCase)
+{
+    bool foundIncrement = false;
     for (const auto& increment : *trace->mutable_increment()) {
-        if (increment.increment_case() == increment.kDelete) {
-            bool isMatch(increment.delete_().id() == targetLayerId);
-            if (isMatch && !foundLayer) {
-                foundLayer = true;
-            }
-            else if (isMatch && foundLayer) {
-                return false;
+        if (increment.increment_case() == incrementCase) {
+            switch (incrementCase) {
+                case Increment::IncrementCase::kSurfaceCreation:
+                    foundIncrement = surfaceCreationFound(increment, foundIncrement);
+                    break;
+                case Increment::IncrementCase::kSurfaceDeletion:
+                    foundIncrement = surfaceDeletionFound(increment, foundIncrement);
+                    break;
+                case Increment::IncrementCase::kDisplayCreation:
+                    foundIncrement = displayCreationFound(increment, foundIncrement);
+                    break;
+                case Increment::IncrementCase::kDisplayDeletion:
+                    foundIncrement = displayDeletionFound(increment, foundIncrement);
+                    break;
+                default:
+                    /* code */
+                    break;
             }
         }
     }
-    return foundLayer;
+    return foundIncrement;
 }
 
 bool SurfaceInterceptorTest::bufferUpdatesFound(Trace* trace) {
@@ -609,62 +713,68 @@
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptPositionUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::positionUpdate, Change::ChangeCase::kPosition);
+    captureTest(&SurfaceInterceptorTest::positionUpdate,
+            SurfaceChange::SurfaceChangeCase::kPosition);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptSizeUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::sizeUpdate, Change::ChangeCase::kSize);
+    captureTest(&SurfaceInterceptorTest::sizeUpdate, SurfaceChange::SurfaceChangeCase::kSize);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptAlphaUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::alphaUpdate, Change::ChangeCase::kAlpha);
+    captureTest(&SurfaceInterceptorTest::alphaUpdate, SurfaceChange::SurfaceChangeCase::kAlpha);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptLayerUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::layerUpdate, Change::ChangeCase::kLayer);
+    captureTest(&SurfaceInterceptorTest::layerUpdate, SurfaceChange::SurfaceChangeCase::kLayer);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptCropUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::cropUpdate, Change::ChangeCase::kCrop);
+    captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptFinalCropUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::finalCropUpdate, Change::ChangeCase::kFinalCrop);
+    captureTest(&SurfaceInterceptorTest::finalCropUpdate,
+            SurfaceChange::SurfaceChangeCase::kFinalCrop);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::matrixUpdate, Change::ChangeCase::kMatrix);
+    captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptOverrideScalingModeUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::overrideScalingModeUpdate,
-            Change::ChangeCase::kOverrideScalingMode);
+            SurfaceChange::SurfaceChangeCase::kOverrideScalingMode);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptTransparentRegionHintUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::transparentRegionHintUpdate,
-            Change::ChangeCase::kTransparentRegionHint);
+            SurfaceChange::SurfaceChangeCase::kTransparentRegionHint);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptLayerStackUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::layerStackUpdate, Change::ChangeCase::kLayerStack);
+    captureTest(&SurfaceInterceptorTest::layerStackUpdate,
+            SurfaceChange::SurfaceChangeCase::kLayerStack);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptHiddenFlagUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::hiddenFlagUpdate, Change::ChangeCase::kHiddenFlag);
+    captureTest(&SurfaceInterceptorTest::hiddenFlagUpdate,
+            SurfaceChange::SurfaceChangeCase::kHiddenFlag);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptOpaqueFlagUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::opaqueFlagUpdate, Change::ChangeCase::kOpaqueFlag);
+    captureTest(&SurfaceInterceptorTest::opaqueFlagUpdate,
+            SurfaceChange::SurfaceChangeCase::kOpaqueFlag);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptSecureFlagUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::secureFlagUpdate, Change::ChangeCase::kSecureFlag);
+    captureTest(&SurfaceInterceptorTest::secureFlagUpdate,
+            SurfaceChange::SurfaceChangeCase::kSecureFlag);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::deferredTransactionUpdate,
-            Change::ChangeCase::kDeferredTransaction);
+            SurfaceChange::SurfaceChangeCase::kDeferredTransaction);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) {
@@ -678,21 +788,32 @@
     assertAllUpdatesFound(&capturedTrace);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptLayerCreateWorks) {
-    captureTest(&SurfaceInterceptorTest::surfaceCreate, &SurfaceInterceptorTest::surfaceCreateFound);
+TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) {
+    captureTest(&SurfaceInterceptorTest::surfaceCreation,
+            Increment::IncrementCase::kSurfaceCreation);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptLayerDeleteWorks) {
+TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) {
     sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME),
             SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0);
-    uint32_t targetLayerId = getLayerId(LAYER_NAME);
+    this->mTargetId = getSurfaceId(LAYER_NAME);
     enableInterceptor();
     mComposerClient->destroySurface(layerToDelete->getHandle());
     disableInterceptor();
 
     Trace capturedTrace;
     ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
-    ASSERT_TRUE(surfaceDeleteFound(&capturedTrace, targetLayerId));
+    ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) {
+    captureTest(&SurfaceInterceptorTest::displayCreation,
+            Increment::IncrementCase::kDisplayCreation);
+}
+
+TEST_F(SurfaceInterceptorTest, InterceptDisplayDeletionWorks) {
+    captureTest(&SurfaceInterceptorTest::displayDeletion,
+            Increment::IncrementCase::kDisplayDeletion);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) {
@@ -701,7 +822,8 @@
 }
 
 // If the interceptor is enabled while buffer updates are being pushed, the interceptor should
-// first create a snapshot of the existing surfaces and then start capturing the buffer updates
+// first create a snapshot of the existing displays and surfaces and then start capturing
+// the buffer updates
 TEST_F(SurfaceInterceptorTest, InterceptWhileBufferUpdatesWorks) {
     std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
     enableInterceptor();
@@ -711,14 +833,14 @@
     Trace capturedTrace;
     ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
     const auto& firstIncrement = capturedTrace.mutable_increment(0);
-    ASSERT_EQ(firstIncrement->increment_case(), Increment::IncrementCase::kCreate);
+    ASSERT_EQ(firstIncrement->increment_case(), Increment::IncrementCase::kDisplayCreation);
 }
 
 TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) {
     enableInterceptor();
     std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
     std::thread surfaceUpdates(&SurfaceInterceptorTest::runAllUpdates, this);
-    runInTransaction(&SurfaceInterceptorTest::surfaceCreate);
+    runInTransaction(&SurfaceInterceptorTest::surfaceCreation);
     bufferUpdates.join();
     surfaceUpdates.join();
     disableInterceptor();
@@ -728,7 +850,7 @@
 
     assertAllUpdatesFound(&capturedTrace);
     ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
-    ASSERT_TRUE(surfaceCreateFound(&capturedTrace));
+    ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceCreation));
 }
 
 }