Merge "Delete RenderEngine path for OpenGL ES 1.0/1.1"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index f3b12b1..d486a3d 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -1,6 +1,6 @@
 ## Permissions to allow system-wide tracing to the kernel trace buffer.
 ##
-on boot
+on fs
 
 # Allow writing to the kernel trace log.
     chmod 0222 /sys/kernel/debug/tracing/trace_marker
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 443511e..73d274f 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -23,6 +23,8 @@
 #include <binder/IServiceManager.h>
 #include <binder/IShellCallback.h>
 #include <binder/TextOutput.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
 #include <utils/Vector.h>
 
 #include <getopt.h>
@@ -39,6 +41,8 @@
 
 #include <UniquePtr.h>
 
+#define DEBUG 0
+
 using namespace android;
 
 static int sort_func(const String16* lhs, const String16* rhs)
@@ -94,7 +98,24 @@
 class MyResultReceiver : public BnResultReceiver
 {
 public:
-    virtual void send(int32_t /*resultCode*/) {
+    Mutex mMutex;
+    Condition mCondition;
+    bool mHaveResult = false;
+    int32_t mResult = 0;
+
+    virtual void send(int32_t resultCode) {
+        AutoMutex _l(mMutex);
+        mResult = resultCode;
+        mHaveResult = true;
+        mCondition.signal();
+    }
+
+    int32_t waitForResult() {
+        AutoMutex _l(mMutex);
+        while (!mHaveResult) {
+            mCondition.wait(mMutex);
+        }
+        return mResult;
     }
 };
 
@@ -107,13 +128,13 @@
     sp<IServiceManager> sm = defaultServiceManager();
     fflush(stdout);
     if (sm == NULL) {
-        ALOGE("Unable to get default service manager!");
+        ALOGW("Unable to get default service manager!");
         aerr << "cmd: Unable to get default service manager!" << endl;
         return 20;
     }
 
     if (argc == 1) {
-        aout << "cmd: no service specified; use -l to list all services" << endl;
+        aerr << "cmd: No service specified; use -l to list all services" << endl;
         return 20;
     }
 
@@ -138,17 +159,41 @@
     String16 cmd = String16(argv[1]);
     sp<IBinder> service = sm->checkService(cmd);
     if (service == NULL) {
-        aerr << "Can't find service: " << argv[1] << endl;
+        ALOGW("Can't find service %s", argv[1]);
+        aerr << "cmd: Can't find service: " << argv[1] << endl;
         return 20;
     }
 
     sp<MyShellCallback> cb = new MyShellCallback();
+    sp<MyResultReceiver> result = new MyResultReceiver();
+
+#if DEBUG
+    ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
+            STDERR_FILENO);
+#endif
 
     // TODO: block until a result is returned to MyResultReceiver.
-    IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
-            cb, new MyResultReceiver());
+    status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
+            cb, result);
+    if (err < 0) {
+        const char* errstr;
+        switch (err) {
+            case BAD_TYPE: errstr = "Bad type"; break;
+            case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
+            case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
+            case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
+            default: errstr = strerror(-err); break;
+        }
+        ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
+        aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
+                << (-err) << ")" << endl;
+        return err;
+    }
 
     cb->mActive = false;
-
-    return 0;
+    status_t res = result->waitForResult();
+#if DEBUG
+    ALOGD("result=%d", (int)res);
+#endif
+    return res;
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 32dbf8d..a48f112 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -56,18 +56,10 @@
 static char cmdline_buf[16384] = "(unknown)";
 static const char *dump_traces_path = NULL;
 
-// Command-line arguments as string
-static std::string args;
-
 // TODO: variables below should be part of dumpstate object
-static time_t now;
 static std::unique_ptr<ZipWriter> zip_writer;
 static std::set<std::string> mount_points;
 void add_mountinfo();
-/* suffix of the bugreport files - it's typically the date (when invoked with -d),
- * although it could be changed by the user using a system property */
-static std::string suffix;
-static std::string extraOptions;
 
 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
@@ -111,13 +103,6 @@
     return ds.IsUserBuild();
 }
 
-/*
- * List of supported zip format versions.
- *
- * See bugreport-format.md for more info.
- */
-static std::string VERSION_DEFAULT = "1.0";
-
 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
 static const std::string ZIP_ROOT_DIR = "FS";
 
@@ -127,7 +112,7 @@
 /* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
  * otherwise, gets just those modified in the last half an hour. */
 static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
-    time_t thirty_minutes_ago = now - 60*30;
+    time_t thirty_minutes_ago = ds.now_ - 60 * 30;
     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
         snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
         int fd = TEMP_FAILURE_RETRY(open(data[i].name,
@@ -336,7 +321,7 @@
         MYLOGD("Not dumping systrace because zip_writer is not set\n");
         return;
     }
-    std::string systrace_path = ds.bugreportDir_ + "/systrace-" + suffix + ".txt";
+    std::string systrace_path = ds.GetPath("-systrace.txt");
     if (systrace_path.empty()) {
         MYLOGE("Not dumping systrace because path is empty\n");
         return;
@@ -377,7 +362,7 @@
         return;
     }
 
-    std::string raft_log_path = ds.bugreportDir_ + "/raft_log.txt";
+    std::string raft_log_path = ds.GetPath("-raft_log.txt");
     if (raft_log_path.empty()) {
         MYLOGD("raft_log_path is empty\n");
         return;
@@ -686,8 +671,8 @@
 
 /* End copy from system/core/logd/LogBuffer.cpp */
 
-/* dumps the current system state to stdout */
-void print_header(const std::string& version) {
+// TODO: move to utils.cpp
+void Dumpstate::PrintHeader() {
     std::string build, fingerprint, radio, bootloader, network;
     char date[80];
 
@@ -696,7 +681,7 @@
     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
-    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
+    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
 
     printf("========================================================\n");
     printf("== dumpstate: %s\n", date);
@@ -713,9 +698,9 @@
     printf("Kernel: ");
     DumpFile("", "/proc/version");
     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
-    printf("Bugreport format version: %s\n", version.c_str());
-    printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
-           ds.IsDryRun(), args.c_str(), extraOptions.c_str());
+    printf("Bugreport format version: %s\n", version_.c_str());
+    printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", id_, getpid(),
+           dryRun_, args_.c_str(), extraOptions_.c_str());
     printf("\n");
 }
 
@@ -748,8 +733,8 @@
 
     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
-    int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
-            ZipWriter::kCompress, get_mtime(fd, now));
+    int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
+                                                 get_mtime(fd, ds.now_));
     if (err) {
         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
                 ZipWriter::ErrorCodeString(err));
@@ -815,7 +800,7 @@
         return false;
     }
     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
-    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
+    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
     if (err) {
         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
                 ZipWriter::ErrorCodeString(err));
@@ -849,8 +834,7 @@
     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
 }
 
-static void dumpstate(const std::string& screenshot_path,
-                      const std::string& version __attribute__((unused))) {
+static void dumpstate() {
     DurationReporter durationReporter("DUMPSTATE");
     unsigned long timeout;
 
@@ -897,10 +881,9 @@
     /* Dump Bluetooth HCI logs */
     add_dir("/data/misc/bluetooth/logs", true);
 
-    if (!screenshot_path.empty()) {
+    if (!ds.doEarlyScreenshot_) {
         MYLOGI("taking late screenshot\n");
-        take_screenshot(screenshot_path);
-        MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
+        ds.TakeScreenshot();
     }
 
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -1147,7 +1130,7 @@
 
 static void ShowUsageAndExit(int exitCode = 1) {
     fprintf(stderr,
-            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
             "  -h: display this help message\n"
             "  -b: play sound file instead of vibrate, at beginning of job\n"
@@ -1203,13 +1186,13 @@
    temporary file.
  */
 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
-                            const std::string& log_path, time_t now) {
+                            const std::string& log_path) {
     // 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", ds.id_, date,
-           the_real_now_please_stand_up - now);
+           the_real_now_please_stand_up - ds.now_);
 
     if (!add_zip_entry(bugreport_name, bugreport_path)) {
         MYLOGE("Failed to add text entry to .zip file\n");
@@ -1292,11 +1275,7 @@
     int use_control_socket = 0;
     int do_fb = 0;
     int do_broadcast = 0;
-    int do_early_screenshot = 0;
     int is_remote_mode = 0;
-    std::string version = VERSION_DEFAULT;
-
-    now = time(nullptr);
 
     MYLOGI("begin\n");
 
@@ -1314,14 +1293,14 @@
 
     // TODO: use helper function to convert argv into a string
     for (int i = 0; i < argc; i++) {
-        args += argv[i];
+        ds.args_ += argv[i];
         if (i < argc - 1) {
-            args += " ";
+            ds.args_ += " ";
         }
     }
 
-    extraOptions = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
-    MYLOGI("Dumpstate args: %s (extra options: %s)\n", args.c_str(), extraOptions.c_str());
+    ds.extraOptions_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
+    MYLOGI("Dumpstate args: %s (extra options: %s)\n", ds.args_.c_str(), ds.extraOptions_.c_str());
 
     /* gets the sequential id */
     int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
@@ -1350,18 +1329,18 @@
     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
         switch (c) {
             // clang-format off
-            case 'd': do_add_date = 1;          break;
-            case 'z': do_zip_file = 1;          break;
-            case 'o': use_outfile = optarg;     break;
-            case 's': use_socket = 1;           break;
-            case 'S': use_control_socket = 1;   break;
-            case 'v': break;  // compatibility no-op
-            case 'q': do_vibrate = 0;           break;
-            case 'p': do_fb = 1;                break;
-            case 'P': ds.updateProgress_ = 1;   break;
-            case 'R': is_remote_mode = 1;       break;
-            case 'B': do_broadcast = 1;         break;
-            case 'V': version = optarg;         break;
+            case 'd': do_add_date = 1;           break;
+            case 'z': do_zip_file = 1;           break;
+            case 'o': use_outfile = optarg;      break;
+            case 's': use_socket = 1;            break;
+            case 'S': use_control_socket = 1;    break;
+            case 'v':                            break;  // compatibility no-op
+            case 'q': do_vibrate = 0;            break;
+            case 'p': do_fb = 1;                 break;
+            case 'P': ds.updateProgress_ = true; break;
+            case 'R': is_remote_mode = 1;        break;
+            case 'B': do_broadcast = 1;          break;
+            case 'V': ds.version_ = optarg;      break;
             case 'h':
                 ShowUsageAndExit(0);
                 break;
@@ -1372,23 +1351,23 @@
         }
     }
 
-    if (!extraOptions.empty()) {
+    if (!ds.extraOptions_.empty()) {
         // Framework uses a system property to override some command-line args.
         // Currently, it contains the type of the requested bugreport.
-        if (extraOptions == "bugreportplus") {
+        if (ds.extraOptions_ == "bugreportplus") {
             MYLOGD("Running as bugreportplus: add -P, remove -p\n");
-            ds.updateProgress_ = 1;
+            ds.updateProgress_ = true;
             do_fb = 0;
-        } else if (extraOptions == "bugreportremote") {
+        } else if (ds.extraOptions_ == "bugreportremote") {
             MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
             do_vibrate = 0;
             is_remote_mode = 1;
             do_fb = 0;
-        } else if (extraOptions == "bugreportwear") {
+        } else if (ds.extraOptions_ == "bugreportwear") {
             MYLOGD("Running as bugreportwear: add -P\n");
-            ds.updateProgress_ = 1;
+            ds.updateProgress_ = true;
         } else {
-            MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
+            MYLOGE("Unknown extra option: %s\n", ds.extraOptions_.c_str());
         }
         // Reset the property
         android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
@@ -1410,13 +1389,13 @@
         ExitOnInvalidArgs();
     }
 
-    if (version != VERSION_DEFAULT) {
+    if (ds.version_ != VERSION_DEFAULT) {
         ShowUsageAndExit();
     }
 
-    MYLOGI("bugreport format version: %s\n", version.c_str());
+    MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
 
-    do_early_screenshot = ds.updateProgress_;
+    ds.doEarlyScreenshot_ = ds.updateProgress_;
 
     // If we are going to use a socket, do it as early as possible
     // to avoid timeouts from bugreport.
@@ -1436,15 +1415,6 @@
     /* full path of the file containing the dumpstate logs */
     std::string log_path;
 
-    /* full path of the systrace file, when enabled */
-    std::string systrace_path;
-
-    /* full path of the temporary file containing the screenshot (when requested) */
-    std::string screenshot_path;
-
-    /* base name (without suffix or extensions) of the bugreport files */
-    std::string base_name;
-
     /* pointer to the actual path, be it zip or text */
     std::string path;
 
@@ -1456,25 +1426,21 @@
 
     if (is_redirecting) {
         ds.bugreportDir_ = dirname(use_outfile);
-        base_name = basename(use_outfile);
+        ds.baseName_ = basename(use_outfile);
         if (do_add_date) {
             char date[80];
-            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
-            suffix = date;
+            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
+            ds.suffix_ = date;
         } else {
-            suffix = "undated";
+            ds.suffix_ = "undated";
         }
         std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
-        base_name = base_name + "-" + buildId;
+        ds.baseName_ = ds.baseName_ + "-" + buildId;
         if (do_fb) {
-            // TODO: if dumpstate was an object, the paths could be internal variables and then
-            // we could have a function to calculate the derived values, such as:
-            //     screenshot_path = GetPath(".png");
-            screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
+            ds.screenshotPath_ = ds.GetPath(".png");
         }
-        tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
-        log_path =
-            ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";
+        tmp_path = ds.GetPath(".tmp");
+        log_path = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt");
 
         MYLOGD(
             "Bugreport dir: %s\n"
@@ -1483,11 +1449,11 @@
             "Log path: %s\n"
             "Temporary path: %s\n"
             "Screenshot path: %s\n",
-            ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
-            tmp_path.c_str(), screenshot_path.c_str());
+            ds.bugreportDir_.c_str(), ds.baseName_.c_str(), ds.suffix_.c_str(), log_path.c_str(),
+            tmp_path.c_str(), ds.screenshotPath_.c_str());
 
         if (do_zip_file) {
-            path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
+            path = ds.GetPath(".zip");
             MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
             create_parent_dirs(path.c_str());
             zip_file.reset(fopen(path.c_str(), "wb"));
@@ -1497,7 +1463,7 @@
             } else {
                 zip_writer.reset(new ZipWriter(zip_file.get()));
             }
-            add_text_zip_entry("version.txt", version);
+            add_text_zip_entry("version.txt", ds.version_);
         }
 
         if (ds.updateProgress_) {
@@ -1505,7 +1471,7 @@
                 // clang-format off
                 std::vector<std::string> am_args = {
                      "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
-                     "--es", "android.intent.extra.NAME", suffix,
+                     "--es", "android.intent.extra.NAME", ds.suffix_,
                      "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
                      "--ei", "android.intent.extra.PID", std::to_string(getpid()),
                      "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
@@ -1535,18 +1501,13 @@
         }
     }
 
-    if (do_fb && do_early_screenshot) {
-        if (screenshot_path.empty()) {
+    if (do_fb && ds.doEarlyScreenshot_) {
+        if (ds.screenshotPath_.empty()) {
             // should not have happened
             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
         } else {
             MYLOGI("taking early screenshot\n");
-            take_screenshot(screenshot_path);
-            MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
-            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
-                MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
-                        screenshot_path.c_str(), strerror(errno));
-            }
+            ds.TakeScreenshot();
         }
     }
 
@@ -1574,7 +1535,7 @@
     // NOTE: there should be no stdout output until now, otherwise it would break the header.
     // In particular, DurationReport objects should be created passing 'title, NULL', so their
     // duration is logged into MYLOG instead.
-    print_header(version);
+    ds.PrintHeader();
 
     // Dumps systrace right away, otherwise it will be filled with unnecessary events.
     // First try to dump anrd trace if the daemon is running. Otherwise, dump
@@ -1619,7 +1580,7 @@
         return -1;
     }
 
-    dumpstate(do_early_screenshot ? "": screenshot_path, version);
+    dumpstate();
 
     /* close output if needed */
     if (is_redirecting) {
@@ -1643,31 +1604,30 @@
             }
         }
         if (change_suffix) {
-            MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), name.c_str());
-            suffix = name;
-            if (!screenshot_path.empty()) {
-                std::string new_screenshot_path =
-                    ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
-                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
-                    MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
-                            new_screenshot_path.c_str(), strerror(errno));
+            MYLOGI("changing suffix from %s to %s\n", ds.suffix_.c_str(), name.c_str());
+            ds.suffix_ = name;
+            if (!ds.screenshotPath_.empty()) {
+                std::string newScreenshotPath = ds.GetPath(".png");
+                if (rename(ds.screenshotPath_.c_str(), newScreenshotPath.c_str())) {
+                    MYLOGE("rename(%s, %s): %s\n", ds.screenshotPath_.c_str(),
+                           newScreenshotPath.c_str(), strerror(errno));
                 } else {
-                    screenshot_path = new_screenshot_path;
+                    ds.screenshotPath_ = newScreenshotPath;
                 }
             }
         }
 
         bool do_text_file = true;
         if (do_zip_file) {
-            std::string entry_name = base_name + "-" + suffix + ".txt";
+            std::string entry_name = ds.baseName_ + "-" + ds.suffix_ + ".txt";
             MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
-            if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
+            if (!finish_zip_file(entry_name, tmp_path, log_path)) {
                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
                 do_text_file = true;
             } else {
                 do_text_file = false;
                 // Since zip file is already created, it needs to be renamed.
-                std::string new_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
+                std::string new_path = ds.GetPath(".zip");
                 if (path != new_path) {
                     MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
                     if (rename(path.c_str(), new_path.c_str())) {
@@ -1680,7 +1640,7 @@
             }
         }
         if (do_text_file) {
-            path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".txt";
+            path = ds.GetPath(".txt");
             MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
             if (rename(tmp_path.c_str(), path.c_str())) {
                 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
@@ -1724,7 +1684,7 @@
             if (do_fb) {
                 am_args.push_back("--es");
                 am_args.push_back("android.intent.extra.SCREENSHOT");
-                am_args.push_back(screenshot_path);
+                am_args.push_back(ds.screenshotPath_);
             }
             if (is_remote_mode) {
                 am_args.push_back("--es");
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index adaf29e..54d91f7 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -193,6 +193,13 @@
 static const int WEIGHT_TOTAL = 6500;
 
 /*
+ * List of supported zip format versions.
+ *
+ * See bugreport-format.md for more info.
+ */
+static std::string VERSION_DEFAULT = "1.0";
+
+/*
  * Main class driving a bugreport generation.
  *
  * Currently, it only contains variables that are accessed externally, but gradually the functions
@@ -255,6 +262,13 @@
      */
     int DumpFile(const std::string& title, const std::string& path);
 
+    /*
+     * Takes a screenshot and save it to the given `path`.
+     *
+     * If `path` is empty, uses a standard path based on the bugreport name.
+     */
+    void TakeScreenshot(const std::string& path = "");
+
     // TODO: members below should be private once refactor is finished
 
     /*
@@ -262,6 +276,12 @@
      */
     void UpdateProgress(int delta);
 
+    /* Prints the dumpstate header on `stdout`. */
+    void PrintHeader();
+
+    /* Gets the path of a bugreport file with the given suffix. */
+    std::string GetPath(const std::string& suffix);
+
     // TODO: initialize fields on constructor
 
     // dumpstate id - unique after each device reboot.
@@ -270,6 +290,9 @@
     // Whether progress updates should be published.
     bool updateProgress_ = false;
 
+    // Whether it should take an screenshot earlier in the process.
+    bool doEarlyScreenshot_ = false;
+
     // Currrent progress.
     int progress_ = 0;
 
@@ -279,10 +302,30 @@
     // When set, defines a socket file-descriptor use to report progress to bugreportz.
     int controlSocketFd_ = -1;
 
+    // Bugreport format version;
+    std::string version_ = VERSION_DEFAULT;
 
-    // Full path of the directory where the bugreport files will be written;
+    // Command-line arguments as string
+    std::string args_;
+
+    // Extra options passed as system property.
+    std::string extraOptions_;
+
+    // Full path of the directory where the bugreport files will be written.
     std::string bugreportDir_;
 
+    // Full path of the temporary file containing the screenshot (when requested).
+    std::string screenshotPath_;
+
+    time_t now_;
+
+    // Suffix of the bugreport files - it's typically the date (when invoked with -d),
+    // although it could be changed by the user using a system property.
+    std::string suffix_;
+
+    // Base name (without suffix or extensions) of the bugreport files.
+    std::string baseName_;
+
   private:
     // Used by GetInstance() only.
     Dumpstate(bool dryRun = false, const std::string& buildType = "user");
@@ -380,9 +423,6 @@
 /* Implemented by libdumpstate_board to dump board-specific info */
 void dumpstate_board();
 
-/* Takes a screenshot and save it to the given file */
-void take_screenshot(const std::string& path);
-
 /* Vibrates for a given durating (in milliseconds). */
 void vibrate(FILE* vibrator, int ms);
 
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index fc1f721..83fcf21 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -163,7 +163,7 @@
 }
 
 Dumpstate::Dumpstate(bool dryRun, const std::string& buildType)
-    : dryRun_(dryRun), buildType_(buildType) {
+    : now_(time(nullptr)), dryRun_(dryRun), buildType_(buildType) {
 }
 
 Dumpstate& Dumpstate::GetInstance() {
@@ -208,6 +208,10 @@
     return "user" == buildType_;
 }
 
+std::string Dumpstate::GetPath(const std::string& suffix) {
+    return bugreportDir_ + "/" + baseName_ + "-" + suffix_ + suffix;
+}
+
 void for_each_userid(void (*func)(int), const char *header) {
     if (IsDryRun()) return;
 
@@ -1342,9 +1346,16 @@
     }
 }
 
-void take_screenshot(const std::string& path) {
-    RunCommand("", {"/system/bin/screencap", "-p", path},
-               CommandOptions::WithTimeout(10).Always().RedirectStderr().Build());
+void Dumpstate::TakeScreenshot(const std::string& path) {
+    const std::string& realPath = path.empty() ? screenshotPath_ : path;
+    int status =
+        RunCommand("", {"/system/bin/screencap", "-p", realPath},
+                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+    if (status == 0) {
+        MYLOGD("Screenshot saved on %s\n", realPath.c_str());
+    } else {
+        MYLOGE("Failed to take screenshot on %s\n", realPath.c_str());
+    }
 }
 
 void vibrate(FILE* vibrator, int ms) {
diff --git a/data/etc/android.hardware.sensor.heartrate.fitness.xml b/data/etc/android.hardware.sensor.heartrate.fitness.xml
new file mode 100644
index 0000000..aef77b4
--- /dev/null
+++ b/data/etc/android.hardware.sensor.heartrate.fitness.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Feature for devices supporting a fitness heart rate monitor -->
+<permissions>
+    <feature name="android.hardware.sensor.heartrate.fitness" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 9cb4d6d..f10cbc3 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -42,6 +42,7 @@
     <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
+    <feature name="android.software.picture_in_picture" />
     <feature name="android.software.print" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 8128165..7f545e6 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -42,6 +42,7 @@
     <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
+    <feature name="android.software.picture_in_picture" />
     <feature name="android.software.print" />
 
     <!-- Feature to specify if the device supports adding device admins. -->
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index 4c74bc5..b18fd54 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -546,6 +546,8 @@
         case OMX_IndexConfigAndroidIntraRefresh:        return "ConfigAndroidIntraRefresh";
         case OMX_IndexParamAndroidVideoTemporalLayering: return "ParamAndroidVideoTemporalLayering";
         case OMX_IndexConfigAndroidVideoTemporalLayering: return "ConfigAndroidVideoTemporalLayering";
+        case OMX_IndexParamMaxFrameDurationForBitrateControl:
+            return "ParamMaxFrameDurationForBitrateControl";
         case OMX_IndexConfigAutoFramerateConversion:    return "ConfigAutoFramerateConversion";
         case OMX_IndexConfigPriority:                   return "ConfigPriority";
         case OMX_IndexConfigOperatingRate:              return "ConfigOperatingRate";
diff --git a/include/media/openmax/OMX_Index.h b/include/media/openmax/OMX_Index.h
index 1a2a548..5be1355 100644
--- a/include/media/openmax/OMX_Index.h
+++ b/include/media/openmax/OMX_Index.h
@@ -98,10 +98,13 @@
     OMX_IndexParamMetadataKeyFilter,        /**< reference: OMX_PARAM_METADATAFILTERTYPE */
     OMX_IndexConfigPriorityMgmt,            /**< reference: OMX_PRIORITYMGMTTYPE */
     OMX_IndexParamStandardComponentRole,    /**< reference: OMX_PARAM_COMPONENTROLETYPE */
+    OMX_IndexComponentEndUnused,
 
     OMX_IndexPortStartUnused = 0x02000000,
     OMX_IndexParamPortDefinition,           /**< reference: OMX_PARAM_PORTDEFINITIONTYPE */
     OMX_IndexParamCompBufferSupplier,       /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */
+    OMX_IndexPortEndUnused,
+
     OMX_IndexReservedStartUnused = 0x03000000,
 
     /* Audio parameters and configurations */
@@ -134,6 +137,7 @@
     OMX_IndexParamAudioSmv,                 /**< reference: OMX_AUDIO_PARAM_SMVTYPE */
     OMX_IndexParamAudioVorbis,              /**< reference: OMX_AUDIO_PARAM_VORBISTYPE */
     OMX_IndexParamAudioFlac,                /**< reference: OMX_AUDIO_PARAM_FLACTYPE */
+    OMX_IndexAudioEndUnused,
 
     OMX_IndexConfigAudioMidiImmediateEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE */
     OMX_IndexConfigAudioMidiControl,        /**< reference: OMX_AUDIO_CONFIG_MIDICONTROLTYPE */
@@ -194,6 +198,7 @@
     OMX_IndexParamVideoSliceFMO,            /**< reference: OMX_VIDEO_PARAM_AVCSLICEFMO */
     OMX_IndexConfigVideoAVCIntraPeriod,     /**< reference: OMX_VIDEO_CONFIG_AVCINTRAPERIOD */
     OMX_IndexConfigVideoNalSize,            /**< reference: OMX_VIDEO_CONFIG_NALSIZE */
+    OMX_IndexVideoEndUnused,
 
     /* Image & Video common Configurations */
     OMX_IndexCommonStartUnused = 0x07000000,
@@ -231,6 +236,7 @@
     OMX_IndexConfigCommonFocusRegion,       /**< reference: OMX_CONFIG_FOCUSREGIONTYPE */
     OMX_IndexConfigCommonFocusStatus,       /**< reference: OMX_PARAM_FOCUSSTATUSTYPE */
     OMX_IndexConfigCommonTransitionEffect,  /**< reference: OMX_CONFIG_TRANSITIONEFFECTTYPE */
+    OMX_IndexCommonEndUnused,
 
     /* Reserved Configuration range */
     OMX_IndexOtherStartUnused = 0x08000000,
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index 78d1f5d..63fbff8 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -62,6 +62,7 @@
     OMX_IndexParamAudioAndroidAacPresentation,      /**< reference: OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE */
     OMX_IndexParamAudioAndroidEac3,                 /**< reference: OMX_AUDIO_PARAM_ANDROID_EAC3TYPE */
     OMX_IndexParamAudioProfileQuerySupported,       /**< reference: OMX_AUDIO_PARAM_ANDROID_PROFILETYPE */
+    OMX_IndexExtAudioEndUnused,
 
     /* Image parameters and configurations */
     OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000,
@@ -82,6 +83,8 @@
     OMX_IndexConfigAndroidIntraRefresh,             /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */
     OMX_IndexParamAndroidVideoTemporalLayering,     /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE */
     OMX_IndexConfigAndroidVideoTemporalLayering,    /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE */
+    OMX_IndexParamMaxFrameDurationForBitrateControl,/**< reference: OMX_PARAM_U32TYPE */
+    OMX_IndexExtVideoEndUnused,
 
     /* Image & Video common configurations */
     OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000,
@@ -92,6 +95,7 @@
     OMX_IndexConfigPriority,                        /**< reference: OMX_PARAM_U32TYPE */
     OMX_IndexConfigOperatingRate,                   /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
     OMX_IndexParamConsumerUsageBits,                /**< reference: OMX_PARAM_U32TYPE */
+    OMX_IndexExtOtherEndUnused,
 
     /* Time configurations */
     OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index d45ad76..1df15f8 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -27,6 +27,8 @@
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
+#include <experimental/optional>
+
 struct ANativeWindowBuffer;
 
 namespace android {
@@ -96,6 +98,27 @@
     // occurs then -1 is returned.
     nsecs_t getSignalTime() const;
 
+#if __cplusplus > 201103L
+    // hasSignaled returns whether the fence has signaled yet. Prefer this to
+    // getSignalTime() or wait() if all you care about is whether the fence has
+    // signaled. Returns an optional bool, which will have a value if there was
+    // no error.
+    inline std::experimental::optional<bool> hasSignaled() {
+        // The sync_wait call underlying wait() has been measured to be
+        // significantly faster than the sync_fence_info call underlying
+        // getSignalTime(), which might otherwise appear to be the more obvious
+        // way to check whether a fence has signaled.
+        switch (wait(0)) {
+            case NO_ERROR:
+                return true;
+            case -ETIME:
+                return false;
+            default:
+                return {};
+        }
+    }
+#endif
+
     // Flattenable interface
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
new file mode 100644
index 0000000..23b78ed
--- /dev/null
+++ b/include/ui/GrallocAllocator.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC_ALLOCATOR_H
+#define ANDROID_UI_GRALLOC_ALLOCATOR_H
+
+#include <string>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::Error;
+using hardware::graphics::allocator::V2_0::PixelFormat;
+using hardware::graphics::allocator::V2_0::ProducerUsage;
+using hardware::graphics::allocator::V2_0::ConsumerUsage;
+using hardware::graphics::allocator::V2_0::BufferDescriptor;
+using hardware::graphics::allocator::V2_0::Buffer;
+using hardware::graphics::allocator::V2_0::IAllocator;
+
+// Allocator is a wrapper to IAllocator, a proxy to server-side allocator.
+class Allocator {
+public:
+    Allocator();
+
+    // this will be removed and Allocator will be always valid
+    bool valid() const { return (mService != nullptr); }
+
+    std::string dumpDebugInfo() const;
+
+    Error createBufferDescriptor(
+            const IAllocator::BufferDescriptorInfo& descriptorInfo,
+            BufferDescriptor& descriptor) const;
+    void destroyBufferDescriptor(BufferDescriptor descriptor) const;
+
+    Error allocate(BufferDescriptor descriptor, Buffer& buffer) const;
+    void free(Buffer buffer) const;
+
+    Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
+            native_handle_t*& bufferHandle) const;
+
+private:
+    sp<IAllocator> mService;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC_ALLOCATOR_H
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
new file mode 100644
index 0000000..5517449
--- /dev/null
+++ b/include/ui/GrallocMapper.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_GRALLOC_MAPPER_H
+#define ANDROID_UI_GRALLOC_MAPPER_H
+
+#include <memory>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::Error;
+using hardware::graphics::allocator::V2_0::PixelFormat;
+using hardware::graphics::allocator::V2_0::ProducerUsage;
+using hardware::graphics::allocator::V2_0::ConsumerUsage;
+using hardware::graphics::mapper::V2_0::FlexLayout;
+using hardware::graphics::mapper::V2_0::BackingStore;
+using hardware::graphics::mapper::V2_0::Device;
+using hardware::graphics::mapper::V2_0::IMapper;
+
+// Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
+class Mapper {
+public:
+    Mapper();
+    ~Mapper();
+
+    // this will be removed and Mapper will be always valid
+    bool valid() const { return (mMapper != nullptr); }
+
+    Error retain(buffer_handle_t handle) const
+    {
+        return mMapper->retain(mDevice, handle);
+    }
+
+    void release(buffer_handle_t handle) const;
+
+    Error getDimensions(buffer_handle_t handle,
+            uint32_t& width, uint32_t& height) const
+    {
+        return mMapper->getDimensions(mDevice, handle, &width, &height);
+    }
+
+    Error getFormat(buffer_handle_t handle,
+            PixelFormat& format) const
+    {
+        return mMapper->getFormat(mDevice, handle, &format);
+    }
+
+    Error getProducerUsageMask(buffer_handle_t handle,
+            uint64_t& usageMask) const
+    {
+        return mMapper->getProducerUsageMask(mDevice, handle, &usageMask);
+    }
+
+    Error getConsumerUsageMask(buffer_handle_t handle,
+            uint64_t& usageMask) const
+    {
+        return mMapper->getConsumerUsageMask(mDevice, handle, &usageMask);
+    }
+
+    Error getBackingStore(buffer_handle_t handle,
+            BackingStore& store) const
+    {
+        return mMapper->getBackingStore(mDevice, handle, &store);
+    }
+
+    Error getStride(buffer_handle_t handle, uint32_t& stride) const
+    {
+        return mMapper->getStride(mDevice, handle, &stride);
+    }
+
+    Error getNumFlexPlanes(buffer_handle_t handle, uint32_t& numPlanes) const
+    {
+        return mMapper->getNumFlexPlanes(mDevice, handle, &numPlanes);
+    }
+
+    Error lock(buffer_handle_t handle,
+            uint64_t producerUsageMask,
+            uint64_t consumerUsageMask,
+            const Device::Rect& accessRegion,
+            int acquireFence, void*& data) const
+    {
+        return mMapper->lock(mDevice, handle,
+                producerUsageMask, consumerUsageMask,
+                &accessRegion, acquireFence, &data);
+    }
+
+    Error lock(buffer_handle_t handle,
+            uint64_t producerUsageMask,
+            uint64_t consumerUsageMask,
+            const Device::Rect& accessRegion,
+            int acquireFence, FlexLayout& flexLayout) const
+    {
+        return mMapper->lockFlex(mDevice, handle,
+                producerUsageMask, consumerUsageMask,
+                &accessRegion, acquireFence, &flexLayout);
+    }
+
+    int unlock(buffer_handle_t handle) const;
+
+private:
+    const IMapper* mMapper;
+    Device* mDevice;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC_MAPPER_H
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index 28d0238..9cc5806 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -32,7 +32,12 @@
 
 namespace android {
 
+namespace Gralloc2 {
+class Allocator;
+}
+
 class Gralloc1Loader;
+class GraphicBufferMapper;
 class String8;
 
 class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
@@ -86,6 +91,9 @@
     GraphicBufferAllocator();
     ~GraphicBufferAllocator();
 
+    const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
+    GraphicBufferMapper& mMapper;
+
     std::unique_ptr<Gralloc1::Loader> mLoader;
     std::unique_ptr<Gralloc1::Device> mDevice;
 };
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index a25809c..b6de1b2 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -28,6 +28,10 @@
 
 // ---------------------------------------------------------------------------
 
+namespace Gralloc2 {
+class Mapper;
+}
+
 class Rect;
 
 class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
@@ -57,11 +61,18 @@
 
     status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
 
+    const Gralloc2::Mapper& getGrallocMapper() const
+    {
+        return *mMapper;
+    }
+
 private:
     friend class Singleton<GraphicBufferMapper>;
 
     GraphicBufferMapper();
 
+    const std::unique_ptr<const Gralloc2::Mapper> mMapper;
+
     std::unique_ptr<Gralloc1::Loader> mLoader;
     std::unique_ptr<Gralloc1::Device> mDevice;
 };
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
new file mode 100644
index 0000000..8e8bb80
--- /dev/null
+++ b/libs/gui/Android.bp
@@ -0,0 +1,111 @@
+// Copyright 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libgui",
+
+    clang: true,
+    cppflags: [
+        "-Weverything",
+        "-Werror",
+
+        // The static constructors and destructors in this library have not been noted to
+        // introduce significant overheads
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+
+        // We only care about compiling as C++14
+        "-Wno-c++98-compat-pedantic",
+
+        // We don't need to enumerate every case in a switch as long as a default case
+        // is present
+        "-Wno-switch-enum",
+
+        // Allow calling variadic macros without a __VA_ARGS__ list
+        "-Wno-gnu-zero-variadic-macro-arguments",
+
+        // Don't warn about struct padding
+        "-Wno-padded",
+
+        // android/sensors.h uses nested anonymous unions and anonymous structs
+        "-Wno-nested-anon-types",
+        "-Wno-gnu-anonymous-struct",
+
+        "-DDEBUG_ONLY_CODE=0",
+    ],
+
+    product_variables: {
+        brillo: {
+            cflags: ["-DHAVE_NO_SURFACE_FLINGER"],
+        },
+        debuggable: {
+            cppflags: [
+                "-UDEBUG_ONLY_CODE",
+                "-DDEBUG_ONLY_CODE=1",
+            ],
+        },
+    },
+
+    srcs: [
+        "IGraphicBufferConsumer.cpp",
+        "IConsumerListener.cpp",
+        "BitTube.cpp",
+        "BufferItem.cpp",
+        "BufferItemConsumer.cpp",
+        "BufferQueue.cpp",
+        "BufferQueueConsumer.cpp",
+        "BufferQueueCore.cpp",
+        "BufferQueueProducer.cpp",
+        "BufferSlot.cpp",
+        "ConsumerBase.cpp",
+        "CpuConsumer.cpp",
+        "DisplayEventReceiver.cpp",
+        "GLConsumer.cpp",
+        "GraphicBufferAlloc.cpp",
+        "GuiConfig.cpp",
+        "IDisplayEventConnection.cpp",
+        "IGraphicBufferAlloc.cpp",
+        "IGraphicBufferProducer.cpp",
+        "IProducerListener.cpp",
+        "ISensorEventConnection.cpp",
+        "ISensorServer.cpp",
+        "ISurfaceComposer.cpp",
+        "ISurfaceComposerClient.cpp",
+        "LayerState.cpp",
+        "OccupancyTracker.cpp",
+        "Sensor.cpp",
+        "SensorEventQueue.cpp",
+        "SensorManager.cpp",
+        "StreamSplitter.cpp",
+        "Surface.cpp",
+        "SurfaceControl.cpp",
+        "SurfaceComposerClient.cpp",
+        "SyncFeatures.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libsync",
+        "libui",
+        "libutils",
+        "liblog",
+    ],
+
+    export_shared_lib_headers: ["libbinder"],
+}
+
+subdirs = ["tests"]
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
deleted file mode 100644
index 71b5cca..0000000
--- a/libs/gui/Android.mk
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
-
-# The static constructors and destructors in this library have not been noted to
-# introduce significant overheads
-LOCAL_CPPFLAGS += -Wno-exit-time-destructors
-LOCAL_CPPFLAGS += -Wno-global-constructors
-
-# We only care about compiling as C++14
-LOCAL_CPPFLAGS += -Wno-c++98-compat-pedantic
-
-# We don't need to enumerate every case in a switch as long as a default case
-# is present
-LOCAL_CPPFLAGS += -Wno-switch-enum
-
-# Allow calling variadic macros without a __VA_ARGS__ list
-LOCAL_CPPFLAGS += -Wno-gnu-zero-variadic-macro-arguments
-
-# Don't warn about struct padding
-LOCAL_CPPFLAGS += -Wno-padded
-
-# android/sensors.h uses nested anonymous unions and anonymous structs
-LOCAL_CPPFLAGS += -Wno-nested-anon-types -Wno-gnu-anonymous-struct
-
-LOCAL_CPPFLAGS += -DDEBUG_ONLY_CODE=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)
-
-LOCAL_SRC_FILES := \
-	IGraphicBufferConsumer.cpp \
-	IConsumerListener.cpp \
-	BitTube.cpp \
-	BufferItem.cpp \
-	BufferItemConsumer.cpp \
-	BufferQueue.cpp \
-	BufferQueueConsumer.cpp \
-	BufferQueueCore.cpp \
-	BufferQueueProducer.cpp \
-	BufferSlot.cpp \
-	ConsumerBase.cpp \
-	CpuConsumer.cpp \
-	DisplayEventReceiver.cpp \
-	GLConsumer.cpp \
-	GraphicBufferAlloc.cpp \
-	GuiConfig.cpp \
-	IDisplayEventConnection.cpp \
-	IGraphicBufferAlloc.cpp \
-	IGraphicBufferProducer.cpp \
-	IProducerListener.cpp \
-	ISensorEventConnection.cpp \
-	ISensorServer.cpp \
-	ISurfaceComposer.cpp \
-	ISurfaceComposerClient.cpp \
-	LayerState.cpp \
-	OccupancyTracker.cpp \
-	Sensor.cpp \
-	SensorEventQueue.cpp \
-	SensorManager.cpp \
-	StreamSplitter.cpp \
-	Surface.cpp \
-	SurfaceControl.cpp \
-	SurfaceComposerClient.cpp \
-	SyncFeatures.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	libbinder \
-	libcutils \
-	libEGL \
-	libGLESv2 \
-	libsync \
-	libui \
-	libutils \
-	liblog
-
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
-
-LOCAL_MODULE := libgui
-
-ifeq ($(TARGET_BOARD_PLATFORM), tegra)
-	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
-endif
-ifeq ($(TARGET_BOARD_PLATFORM), tegra3)
-	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
-endif
-
-ifeq ($(TARGET_BOARD_HAS_NO_SURFACE_FLINGER), true)
-	LOCAL_CFLAGS += -DHAVE_NO_SURFACE_FLINGER
-endif
-
-include $(BUILD_SHARED_LIBRARY)
-
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 5546d54..3cf3078 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -314,6 +314,18 @@
 
     if (!mSlots[slot].mFence.get()) {
         mSlots[slot].mFence = fence;
+        return OK;
+    }
+
+    auto signaled = mSlots[slot].mFence->hasSignaled();
+
+    if (!signaled) {
+        CB_LOGE("fence has invalid state");
+        return BAD_VALUE;
+    }
+
+    if (*signaled) {
+        mSlots[slot].mFence = fence;
     } else {
         char fenceName[32] = {};
         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 5338034..57c3073 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -194,7 +194,8 @@
         // a non_wake-up version.
         if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
             type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
-            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE) {
+            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
+            type == SENSOR_TYPE_WRIST_TILT_GESTURE) {
             wakeUpSensor = true;
         }
         // For now we just return the first sensor of that type we find.
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
new file mode 100644
index 0000000..3c7958f
--- /dev/null
+++ b/libs/gui/tests/Android.bp
@@ -0,0 +1,42 @@
+// Build the unit tests,
+
+// Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+// to integrate with auto-test framework.
+cc_test {
+    name: "libgui_test",
+
+    clang: true,
+
+    srcs: [
+        "BufferQueue_test.cpp",
+        "CpuConsumer_test.cpp",
+        "FillBuffer.cpp",
+        "GLTest.cpp",
+        "IGraphicBufferProducer_test.cpp",
+        "MultiTextureConsumer_test.cpp",
+        "Sensor_test.cpp",
+        "SRGB_test.cpp",
+        "StreamSplitter_test.cpp",
+        "SurfaceTextureClient_test.cpp",
+        "SurfaceTextureFBO_test.cpp",
+        "SurfaceTextureGLThreadToGL_test.cpp",
+        "SurfaceTextureGLToGL_test.cpp",
+        "SurfaceTextureGL_test.cpp",
+        "SurfaceTextureMultiContextGL_test.cpp",
+        "Surface_test.cpp",
+        "TextureRenderer.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libEGL",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libbinder",
+        "libcutils",
+        "libgui",
+        "libsync",
+        "libui",
+        "libutils",
+    ],
+}
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
deleted file mode 100644
index efae7f6..0000000
--- a/libs/gui/tests/Android.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-# Build the unit tests,
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_CLANG := true
-
-LOCAL_MODULE := libgui_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    BufferQueue_test.cpp \
-    CpuConsumer_test.cpp \
-    FillBuffer.cpp \
-    GLTest.cpp \
-    IGraphicBufferProducer_test.cpp \
-    MultiTextureConsumer_test.cpp \
-    Sensor_test.cpp \
-    SRGB_test.cpp \
-    StreamSplitter_test.cpp \
-    SurfaceTextureClient_test.cpp \
-    SurfaceTextureFBO_test.cpp \
-    SurfaceTextureGLThreadToGL_test.cpp \
-    SurfaceTextureGLToGL_test.cpp \
-    SurfaceTextureGL_test.cpp \
-    SurfaceTextureMultiContextGL_test.cpp \
-    Surface_test.cpp \
-    TextureRenderer.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libEGL \
-	libGLESv1_CM \
-	libGLESv2 \
-	libbinder \
-	libcutils \
-	libgui \
-	libsync \
-	libui \
-	libutils \
-
-# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
-# to integrate with auto-test framework.
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 0777468..37b2873 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -17,7 +17,6 @@
 
     clang: true,
     cppflags: [
-        "-std=c++1y",
         "-Weverything",
         "-Werror",
 
@@ -46,6 +45,8 @@
         "FrameStats.cpp",
         "Gralloc1.cpp",
         "Gralloc1On0Adapter.cpp",
+        "GrallocAllocator.cpp",
+        "GrallocMapper.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
@@ -56,10 +57,17 @@
         "UiConfig.cpp",
     ],
 
+    static_libs: [
+        "android.hardware.graphics.mapper@2.0",
+    ],
+
     shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
         "libbinder",
         "libcutils",
         "libhardware",
+        "libhidl",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
new file mode 100644
index 0000000..2eb1988
--- /dev/null
+++ b/libs/ui/GrallocAllocator.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocAllocator"
+
+#include <log/log.h>
+#include <ui/GrallocAllocator.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+// assume NO_RESOURCES when Status::isOk returns false
+constexpr Error kDefaultError = Error::NO_RESOURCES;
+
+Allocator::Allocator()
+{
+    mService = IAllocator::getService("gralloc");
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+    std::string info;
+
+    mService->dumpDebugInfo([&](const auto& tmpInfo) {
+        info = tmpInfo.c_str();
+    });
+
+    return info;
+}
+
+Error Allocator::createBufferDescriptor(
+        const IAllocator::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor& descriptor) const
+{
+    Error error = kDefaultError;
+    mService->createDescriptor(descriptorInfo,
+            [&](const auto& tmpError, const auto& tmpDescriptor) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                descriptor = tmpDescriptor;
+            });
+
+    return error;
+}
+
+void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
+{
+    mService->destroyDescriptor(descriptor);
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, Buffer& buffer) const
+{
+    hardware::hidl_vec<BufferDescriptor> descriptors;
+    descriptors.setToExternal(&descriptor, 1);
+
+    Error error = kDefaultError;
+    auto status = mService->allocate(descriptors,
+            [&](const auto& tmpError, const auto& tmpBuffers) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                buffer = tmpBuffers[0];
+            });
+
+    return error;
+}
+
+void Allocator::free(Buffer buffer) const
+{
+    mService->free(buffer);
+}
+
+Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
+        native_handle_t*& bufferHandle) const
+{
+    Error error = kDefaultError;
+    auto status = mService->exportHandle(descriptor, buffer,
+            [&](const auto& tmpError, const auto& tmpBufferHandle) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                bufferHandle = native_handle_clone(tmpBufferHandle);
+                if (!bufferHandle) {
+                    error = Error::NO_RESOURCES;
+                }
+            });
+
+    return error;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
new file mode 100644
index 0000000..d568b68
--- /dev/null
+++ b/libs/ui/GrallocMapper.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocMapper"
+
+#include <array>
+#include <string>
+
+#include <log/log.h>
+#include <ui/GrallocMapper.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+typedef const void*(*FetchInterface)(const char* name);
+
+static FetchInterface loadHalLib(const char* pkg_name)
+{
+    static const std::array<const char*, 3> sSearchDirs = {{
+        HAL_LIBRARY_PATH_ODM,
+        HAL_LIBRARY_PATH_VENDOR,
+        HAL_LIBRARY_PATH_SYSTEM,
+    }};
+    static const char sSymbolName[] = "HALLIB_FETCH_Interface";
+
+    void* handle = nullptr;
+    std::string path;
+    for (auto dir : sSearchDirs) {
+        path = dir;
+        path += pkg_name;
+        path += ".hallib.so";
+        handle = dlopen(path.c_str(), RTLD_LOCAL | RTLD_NOW);
+        if (handle) {
+            break;
+        }
+    }
+    if (!handle) {
+        return nullptr;
+    }
+
+    void* symbol = dlsym(handle, sSymbolName);
+    if (!symbol) {
+        ALOGE("%s is missing from %s", sSymbolName, path.c_str());
+        dlclose(handle);
+        return nullptr;
+    }
+
+    return reinterpret_cast<FetchInterface>(symbol);
+}
+
+Mapper::Mapper()
+    : mMapper(nullptr), mDevice(nullptr)
+{
+    static const char sHalLibName[] = "android.hardware.graphics.mapper";
+    static const char sSupportedInterface[] =
+        "android.hardware.graphics.mapper@2.0::IMapper";
+
+    FetchInterface fetchInterface = loadHalLib(sHalLibName);
+    if (!fetchInterface) {
+        return;
+    }
+
+    mMapper = static_cast<const IMapper*>(
+            fetchInterface(sSupportedInterface));
+    if (!mMapper) {
+        ALOGE("%s is not supported", sSupportedInterface);
+        return;
+    }
+
+    if (mMapper->createDevice(&mDevice) != Error::NONE) {
+        ALOGE("failed to create mapper device");
+        mMapper = nullptr;
+    }
+}
+
+Mapper::~Mapper()
+{
+    if (mMapper) {
+        mMapper->destroyDevice(mDevice);
+    }
+}
+
+void Mapper::release(buffer_handle_t handle) const
+{
+    auto error = mMapper->release(mDevice, handle);
+    ALOGE_IF(error != Error::NONE,
+            "release(%p) failed with %d", handle, error);
+}
+
+int Mapper::unlock(buffer_handle_t handle) const
+{
+    int releaseFence;
+    auto error = mMapper->unlock(mDevice, handle, &releaseFence);
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", handle, error);
+        releaseFence = -1;
+    }
+
+    return releaseFence;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 97b948d..6d72900 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -23,6 +23,7 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include <ui/GrallocMapper.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
@@ -108,8 +109,10 @@
 {
     if (mOwner == ownHandle) {
         mBufferMapper.unregisterBuffer(handle);
-        native_handle_close(handle);
-        native_handle_delete(const_cast<native_handle*>(handle));
+        if (!mBufferMapper.getGrallocMapper().valid()) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle*>(handle));
+        }
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index edfff4d..693c7cb 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -26,6 +26,9 @@
 
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/Gralloc1On0Adapter.h>
+#include <ui/GrallocAllocator.h>
+#include <ui/GrallocMapper.h>
+#include <ui/GraphicBufferMapper.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -37,8 +40,14 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-  : mLoader(std::make_unique<Gralloc1::Loader>()),
-    mDevice(mLoader->getDevice()) {}
+  : mAllocator(std::make_unique<Gralloc2::Allocator>()),
+    mMapper(GraphicBufferMapper::getInstance())
+{
+    if (!mAllocator->valid()) {
+        mLoader = std::make_unique<Gralloc1::Loader>();
+        mDevice = mLoader->getDevice();
+    }
+}
 
 GraphicBufferAllocator::~GraphicBufferAllocator() {}
 
@@ -70,7 +79,14 @@
     }
     snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f);
     result.append(buffer);
-    std::string deviceDump = mDevice->dump();
+
+    std::string deviceDump;
+    if (mAllocator->valid()) {
+        deviceDump = mAllocator->dumpDebugInfo();
+    } else {
+        deviceDump = mDevice->dump();
+    }
+
     result.append(deviceDump.c_str(), deviceDump.size());
 }
 
@@ -81,6 +97,103 @@
     ALOGD("%s", s.string());
 }
 
+namespace {
+
+class HalBuffer {
+public:
+    HalBuffer(const Gralloc2::Allocator* allocator,
+            uint32_t width, uint32_t height,
+            PixelFormat format, uint32_t usage)
+        : mAllocator(allocator), mBufferValid(false)
+    {
+        Gralloc2::IAllocator::BufferDescriptorInfo info = {};
+        info.width = width;
+        info.height = height;
+        info.format = static_cast<Gralloc2::PixelFormat>(format);
+        info.producerUsageMask = usage;
+        info.consumerUsageMask = usage;
+
+        Gralloc2::BufferDescriptor descriptor;
+        auto error = mAllocator->createBufferDescriptor(info, descriptor);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to create desc (%u x %u) format %d usage %u: %d",
+                    width, height, format, usage, error);
+            return;
+        }
+
+        error = mAllocator->allocate(descriptor, mBuffer);
+        if (error == Gralloc2::Error::NOT_SHARED) {
+            error = Gralloc2::Error::NONE;
+        }
+
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
+                    width, height, format, usage, error);
+            mAllocator->destroyBufferDescriptor(descriptor);
+            return;
+        }
+
+        error = mAllocator->exportHandle(descriptor, mBuffer, mHandle);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to export handle");
+            mAllocator->free(mBuffer);
+            mAllocator->destroyBufferDescriptor(descriptor);
+            return;
+        }
+
+        mAllocator->destroyBufferDescriptor(descriptor);
+
+        mBufferValid = true;
+    }
+
+    ~HalBuffer()
+    {
+        if (mBufferValid) {
+            if (mHandle) {
+                native_handle_close(mHandle);
+                native_handle_delete(mHandle);
+            }
+
+            mAllocator->free(mBuffer);
+        }
+    }
+
+    bool exportHandle(GraphicBufferMapper& mapper,
+            buffer_handle_t* handle, uint32_t* stride)
+    {
+        if (!mBufferValid) {
+            return false;
+        }
+
+        if (mapper.registerBuffer(mHandle)) {
+            return false;
+        }
+
+        *handle = mHandle;
+
+        auto error = mapper.getGrallocMapper().getStride(mHandle, *stride);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGW("Failed to get stride from buffer: %d", error);
+            *stride = 0;
+        }
+
+        mHandle = nullptr;
+        mAllocator->free(mBuffer);
+        mBufferValid = false;
+
+        return true;
+    }
+
+private:
+    const Gralloc2::Allocator* mAllocator;
+
+    bool mBufferValid;
+    Gralloc2::Buffer mBuffer;
+    native_handle_t* mHandle;
+};
+
+} // namespace
+
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
         PixelFormat format, uint32_t usage, buffer_handle_t* handle,
         uint32_t* stride, uint64_t graphicBufferId, std::string requestorName)
@@ -95,40 +208,51 @@
     // Filter out any usage bits that should not be passed to the gralloc module
     usage &= GRALLOC_USAGE_ALLOC_MASK;
 
-    auto descriptor = mDevice->createDescriptor();
-    auto error = descriptor->setDimensions(width, height);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to set dimensions to (%u, %u): %d", width, height, error);
-        return BAD_VALUE;
-    }
-    error = descriptor->setFormat(static_cast<android_pixel_format_t>(format));
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to set format to %d: %d", format, error);
-        return BAD_VALUE;
-    }
-    error = descriptor->setProducerUsage(
-            static_cast<gralloc1_producer_usage_t>(usage));
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to set producer usage to %u: %d", usage, error);
-        return BAD_VALUE;
-    }
-    error = descriptor->setConsumerUsage(
-            static_cast<gralloc1_consumer_usage_t>(usage));
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to set consumer usage to %u: %d", usage, error);
-        return BAD_VALUE;
-    }
+    gralloc1_error_t error;
+    if (mAllocator->valid()) {
+        HalBuffer buffer(mAllocator.get(), width, height, format, usage);
+        if (!buffer.exportHandle(mMapper, handle, stride)) {
+            return NO_MEMORY;
+        }
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        auto descriptor = mDevice->createDescriptor();
+        error = descriptor->setDimensions(width, height);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("Failed to set dimensions to (%u, %u): %d",
+                    width, height, error);
+            return BAD_VALUE;
+        }
+        error = descriptor->setFormat(
+                static_cast<android_pixel_format_t>(format));
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("Failed to set format to %d: %d", format, error);
+            return BAD_VALUE;
+        }
+        error = descriptor->setProducerUsage(
+                static_cast<gralloc1_producer_usage_t>(usage));
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("Failed to set producer usage to %u: %d", usage, error);
+            return BAD_VALUE;
+        }
+        error = descriptor->setConsumerUsage(
+                static_cast<gralloc1_consumer_usage_t>(usage));
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("Failed to set consumer usage to %u: %d", usage, error);
+            return BAD_VALUE;
+        }
 
-    error = mDevice->allocate(descriptor, graphicBufferId, handle);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
-                width, height, format, usage, error);
-        return NO_MEMORY;
-    }
+        error = mDevice->allocate(descriptor, graphicBufferId, handle);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
+                    width, height, format, usage, error);
+            return NO_MEMORY;
+        }
 
-    error = mDevice->getStride(*handle, stride);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGW("Failed to get stride from buffer: %d", error);
+        error = mDevice->getStride(*handle, stride);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGW("Failed to get stride from buffer: %d", error);
+        }
     }
 
     if (error == NO_ERROR) {
@@ -153,7 +277,14 @@
 {
     ATRACE_CALL();
 
-    auto error = mDevice->release(handle);
+    gralloc1_error_t error;
+    if (mAllocator->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper.unregisterBuffer(handle));
+    } else {
+        error = mDevice->release(handle);
+    }
+
     if (error != GRALLOC1_ERROR_NONE) {
         ALOGE("Failed to free buffer: %d", error);
     }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 481d43c..fb55bf1 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -33,6 +33,7 @@
 #include <utils/Trace.h>
 
 #include <ui/Gralloc1On0Adapter.h>
+#include <ui/GrallocMapper.h>
 #include <ui/GraphicBufferMapper.h>
 #include <ui/Rect.h>
 
@@ -44,8 +45,13 @@
 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
 
 GraphicBufferMapper::GraphicBufferMapper()
-  : mLoader(std::make_unique<Gralloc1::Loader>()),
-    mDevice(mLoader->getDevice()) {}
+  : mMapper(std::make_unique<const Gralloc2::Mapper>())
+{
+    if (!mMapper->valid()) {
+        mLoader = std::make_unique<Gralloc1::Loader>();
+        mDevice = mLoader->getDevice();
+    }
+}
 
 
 
@@ -53,7 +59,13 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->retain(handle);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+    } else {
+        error = mDevice->retain(handle);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
             handle, error);
 
@@ -64,7 +76,14 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->retain(buffer);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper->retain(buffer->getNativeBuffer()->handle));
+    } else {
+        error = mDevice->retain(buffer);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
             buffer->getNativeBuffer()->handle, error);
 
@@ -75,7 +94,14 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->release(handle);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        mMapper->release(handle);
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        error = mDevice->release(handle);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
             handle, error);
 
@@ -120,11 +146,20 @@
     ATRACE_CALL();
 
     gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
-    sp<Fence> fence = new Fence(fenceFd);
-    gralloc1_error_t error = mDevice->lock(handle,
-            static_cast<gralloc1_producer_usage_t>(usage),
-            static_cast<gralloc1_consumer_usage_t>(usage),
-            &accessRegion, vaddr, fence);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        const Gralloc2::Device::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
+        error = static_cast<gralloc1_error_t>(mMapper->lock(
+                    handle, usage, usage, accessRect, fenceFd, *vaddr));
+    } else {
+        sp<Fence> fence = new Fence(fenceFd);
+        error = mDevice->lock(handle,
+                static_cast<gralloc1_producer_usage_t>(usage),
+                static_cast<gralloc1_consumer_usage_t>(usage),
+                &accessRegion, vaddr, fence);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
             error);
 
@@ -160,20 +195,29 @@
     ATRACE_CALL();
 
     gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
-    sp<Fence> fence = new Fence(fenceFd);
 
-    if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-        gralloc1_error_t error = mDevice->lockYCbCr(handle,
-                static_cast<gralloc1_producer_usage_t>(usage),
-                static_cast<gralloc1_consumer_usage_t>(usage),
-                &accessRegion, ycbcr, fence);
-        ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lockYCbCr(%p, ...) failed: %d",
-                handle, error);
-        return error;
+    if (!mMapper->valid()) {
+        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
+            sp<Fence> fence = new Fence(fenceFd);
+            gralloc1_error_t error = mDevice->lockYCbCr(handle,
+                    static_cast<gralloc1_producer_usage_t>(usage),
+                    static_cast<gralloc1_consumer_usage_t>(usage),
+                    &accessRegion, ycbcr, fence);
+            ALOGW_IF(error != GRALLOC1_ERROR_NONE,
+                    "lockYCbCr(%p, ...) failed: %d", handle, error);
+            return error;
+        }
     }
 
     uint32_t numPlanes = 0;
-    gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper->getNumFlexPlanes(handle, numPlanes));
+    } else {
+        error = mDevice->getNumFlexPlanes(handle, &numPlanes);
+    }
+
     if (error != GRALLOC1_ERROR_NONE) {
         ALOGV("Failed to retrieve number of flex planes: %d", error);
         return error;
@@ -188,10 +232,21 @@
     flexLayout.num_planes = numPlanes;
     flexLayout.planes = planes.data();
 
-    error = mDevice->lockFlex(handle,
-            static_cast<gralloc1_producer_usage_t>(usage),
-            static_cast<gralloc1_consumer_usage_t>(usage),
-            &accessRegion, &flexLayout, fence);
+    if (mMapper->valid()) {
+        const Gralloc2::Device::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
+        Gralloc2::FlexLayout& layout =
+            *reinterpret_cast<Gralloc2::FlexLayout*>(&flexLayout);
+        error = static_cast<gralloc1_error_t>(mMapper->lock(
+                    handle, usage, usage, accessRect, fenceFd, layout));
+    } else {
+        sp<Fence> fence = new Fence(fenceFd);
+        error = mDevice->lockFlex(handle,
+                static_cast<gralloc1_producer_usage_t>(usage),
+                static_cast<gralloc1_consumer_usage_t>(usage),
+                &accessRegion, &flexLayout, fence);
+    }
+
     if (error != GRALLOC1_ERROR_NONE) {
         ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
         return error;
@@ -276,14 +331,20 @@
 {
     ATRACE_CALL();
 
-    sp<Fence> fence = Fence::NO_FENCE;
-    gralloc1_error_t error = mDevice->unlock(handle, &fence);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGE("unlock(%p) failed: %d", handle, error);
-        return error;
-    }
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        *fenceFd = mMapper->unlock(handle);
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        sp<Fence> fence = Fence::NO_FENCE;
+        error = mDevice->unlock(handle, &fence);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("unlock(%p) failed: %d", handle, error);
+            return error;
+        }
 
-    *fenceFd = fence->dup();
+        *fenceFd = fence->dup();
+    }
     return error;
 }
 
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index bdd5152..6a8aac8 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -45,3 +45,116 @@
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
 }
+
+cc_defaults {
+    name: "gl_libs_defaults",
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+        "-fvisibility=hidden",
+    ],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libdl",
+    ],
+
+    // we need to access the private Bionic header <bionic_tls.h>
+    include_dirs: ["bionic/libc/private"],
+}
+
+//##############################################################################
+// Build META EGL library
+//
+cc_defaults {
+    name: "egl_libs_defaults",
+    defaults: ["gl_libs_defaults"],
+    cflags: [
+        "-DLOG_TAG=\"libEGL\"",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libui",
+    ],
+}
+
+cc_library_static {
+    name: "libEGL_getProcAddress",
+    defaults: ["egl_libs_defaults"],
+    srcs: ["EGL/getProcAddress.cpp"],
+    arch: {
+        arm: {
+            instruction_set: "arm",
+        },
+    },
+}
+
+cc_library_shared {
+    name: "libEGL",
+    defaults: ["egl_libs_defaults"],
+    srcs: [
+        "EGL/egl_tls.cpp",
+        "EGL/egl_cache.cpp",
+        "EGL/egl_display.cpp",
+        "EGL/egl_object.cpp",
+        "EGL/egl.cpp",
+        "EGL/eglApi.cpp",
+        "EGL/Loader.cpp",
+    ],
+    static_libs: ["libEGL_getProcAddress"],
+    ldflags: ["-Wl,--exclude-libs=ALL"],
+
+    required: ["egl.cfg"],
+}
+
+cc_defaults {
+    name: "gles_libs_defaults",
+    defaults: ["gl_libs_defaults"],
+    arch: {
+        arm: {
+            instruction_set: "arm",
+
+            // TODO: This is to work around b/20093774. Remove after root cause is fixed
+            ldflags: ["-Wl,--hash-style,both"],
+        },
+    },
+    shared_libs: ["libEGL"],
+}
+
+//##############################################################################
+// Build the wrapper OpenGL ES 1.x library
+//
+cc_library_shared {
+    name: "libGLESv1_CM",
+    defaults: ["gles_libs_defaults"],
+    srcs: ["GLES_CM/gl.cpp"],
+
+    cflags: ["-DLOG_TAG=\"libGLESv1\""],
+}
+
+//##############################################################################
+// Build the wrapper OpenGL ES 2.x library
+//
+cc_library_shared {
+    name: "libGLESv2",
+    defaults: ["gles_libs_defaults"],
+    srcs: ["GLES2/gl2.cpp"],
+
+    shared_libs: ["libutils"],
+
+    cflags: ["-DLOG_TAG=\"libGLESv2\""],
+}
+
+//##############################################################################
+// Build the wrapper OpenGL ES 3.x library (this is just different name for v2)
+//
+cc_library_shared {
+    name: "libGLESv3",
+    defaults: ["gles_libs_defaults"],
+    srcs: ["GLES2/gl2.cpp"],
+
+    shared_libs: ["libutils"],
+
+    cflags: ["-DLOG_TAG=\"libGLESv3\""],
+}
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index f0ba728..21e76f5 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -1,13 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
-###############################################################################
-# Build META EGL library
-#
-
-egl.cfg_config_module :=
 # OpenGL drivers config file
 ifneq ($(BOARD_EGL_CFG),)
-
 include $(CLEAR_VARS)
 LOCAL_MODULE := egl.cfg
 LOCAL_MODULE_TAGS := optional
@@ -15,136 +9,4 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/egl
 LOCAL_SRC_FILES := ../../../../$(BOARD_EGL_CFG)
 include $(BUILD_PREBUILT)
-egl.cfg_config_module := $(LOCAL_MODULE)
 endif
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= 	       \
-	EGL/egl_tls.cpp        \
-	EGL/egl_cache.cpp      \
-	EGL/egl_display.cpp    \
-	EGL/egl_object.cpp     \
-	EGL/egl.cpp 	       \
-	EGL/eglApi.cpp 	       \
-	EGL/getProcAddress.cpp.arm \
-	EGL/Loader.cpp 	       \
-#
-
-LOCAL_SHARED_LIBRARIES += libbinder libcutils libutils liblog libui
-LOCAL_MODULE:= libEGL
-LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
-LOCAL_SHARED_LIBRARIES += libdl
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -fvisibility=hidden
-
-ifeq ($(BOARD_ALLOW_EGL_HIBERNATION),true)
-  LOCAL_CFLAGS += -DBOARD_ALLOW_EGL_HIBERNATION
-endif
-ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),)
-  LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
-endif
-
-ifneq ($(MAX_EGL_CACHE_KEY_SIZE),)
-  LOCAL_CFLAGS += -DMAX_EGL_CACHE_KEY_SIZE=$(MAX_EGL_CACHE_KEY_SIZE)
-endif
-
-ifneq ($(MAX_EGL_CACHE_SIZE),)
-  LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
-endif
-
-ifneq ($(filter address,$(SANITIZE_TARGET)),)
-  LOCAL_CFLAGS_32 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib\"
-  LOCAL_CFLAGS_64 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib64\"
-endif
-
-LOCAL_REQUIRED_MODULES := $(egl.cfg_config_module)
-egl.cfg_config_module :=
-
-include $(BUILD_SHARED_LIBRARY)
-
-###############################################################################
-# Build the wrapper OpenGL ES 1.x library
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= 		\
-	GLES_CM/gl.cpp.arm 	\
-#
-
-LOCAL_SHARED_LIBRARIES += libcutils liblog libEGL
-LOCAL_MODULE:= libGLESv1_CM
-
-LOCAL_SHARED_LIBRARIES += libdl
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -fvisibility=hidden
-
-# TODO: This is to work around b/20093774. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
-
-include $(BUILD_SHARED_LIBRARY)
-
-
-###############################################################################
-# Build the wrapper OpenGL ES 2.x library
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	GLES2/gl2.cpp   \
-#
-
-LOCAL_ARM_MODE := arm
-LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
-LOCAL_MODULE:= libGLESv2
-
-LOCAL_SHARED_LIBRARIES += libdl
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -fvisibility=hidden
-
-# TODO: This is to work around b/20093774. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
-
-include $(BUILD_SHARED_LIBRARY)
-
-###############################################################################
-# Build the wrapper OpenGL ES 3.x library (this is just different name for v2)
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	GLES2/gl2.cpp   \
-#
-
-LOCAL_ARM_MODE := arm
-LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
-LOCAL_MODULE:= libGLESv3
-LOCAL_SHARED_LIBRARIES += libdl
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv3\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -fvisibility=hidden
-
-# TODO: This is to work around b/20093774. Remove after root cause is fixed
-LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 8c135c8..1fe322d 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -27,22 +27,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#ifndef MAX_EGL_CACHE_ENTRY_SIZE
-#define MAX_EGL_CACHE_ENTRY_SIZE (16 * 1024);
-#endif
-
-#ifndef MAX_EGL_CACHE_KEY_SIZE
-#define MAX_EGL_CACHE_KEY_SIZE (1024);
-#endif
-
-#ifndef MAX_EGL_CACHE_SIZE
-#define MAX_EGL_CACHE_SIZE (64 * 1024);
-#endif
-
 // Cache size limits.
-static const size_t maxKeySize = MAX_EGL_CACHE_KEY_SIZE;
-static const size_t maxValueSize = MAX_EGL_CACHE_ENTRY_SIZE;
-static const size_t maxTotalSize = MAX_EGL_CACHE_SIZE;
+static const size_t maxKeySize = 12 * 1024;
+static const size_t maxValueSize = 64 * 1024;
+static const size_t maxTotalSize = 2 * 1024 * 1024;
 
 // Cache file header
 static const char* cacheFileMagic = "EGL$";
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 1e39aae..a32f037 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -215,8 +215,6 @@
             *major = VERSION_MAJOR;
         if (minor != NULL)
             *minor = VERSION_MINOR;
-
-        mHibernation.setDisplayValid(true);
     }
 
     {
@@ -265,8 +263,6 @@
             res = EGL_TRUE;
         }
 
-        mHibernation.setDisplayValid(false);
-
         // Reset the extension string since it will be regenerated if we get
         // reinitialized.
         mExtensionString.setTo("");
@@ -345,16 +341,12 @@
                     disp.dpy, impl_draw, impl_read, impl_ctx);
             if (result == EGL_TRUE) {
                 c->onMakeCurrent(draw, read);
-                if (!cur_c) {
-                    mHibernation.incWakeCount(HibernationMachine::STRONG);
-                }
             }
         } else {
             result = cur_c->cnx->egl.eglMakeCurrent(
                     disp.dpy, impl_draw, impl_read, impl_ctx);
             if (result == EGL_TRUE) {
                 cur_c->onLooseCurrent();
-                mHibernation.decWakeCount(HibernationMachine::STRONG);
             }
         }
     }
@@ -379,63 +371,5 @@
 }
 
 // ----------------------------------------------------------------------------
-
-bool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) {
-    Mutex::Autolock _l(mLock);
-    ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX,
-             "Invalid WakeCount (%d) on enter\n", mWakeCount);
-
-    mWakeCount++;
-    if (strength == STRONG)
-        mAttemptHibernation = false;
-
-    if (CC_UNLIKELY(mHibernating)) {
-        ALOGV("Awakening\n");
-        egl_connection_t* const cnx = &gEGLImpl;
-
-        // These conditions should be guaranteed before entering hibernation;
-        // we don't want to get into a state where we can't wake up.
-        ALOGD_IF(!mDpyValid || !cnx->egl.eglAwakenProcessIMG,
-                 "Invalid hibernation state, unable to awaken\n");
-
-        if (!cnx->egl.eglAwakenProcessIMG()) {
-            ALOGE("Failed to awaken EGL implementation\n");
-            return false;
-        }
-        mHibernating = false;
-    }
-    return true;
-}
-
-void egl_display_t::HibernationMachine::decWakeCount(WakeRefStrength strength) {
-    Mutex::Autolock _l(mLock);
-    ALOGE_IF(mWakeCount <= 0, "Invalid WakeCount (%d) on leave\n", mWakeCount);
-
-    mWakeCount--;
-    if (strength == STRONG)
-        mAttemptHibernation = true;
-
-    if (mWakeCount == 0 && CC_UNLIKELY(mAttemptHibernation)) {
-        egl_connection_t* const cnx = &gEGLImpl;
-        mAttemptHibernation = false;
-        if (mAllowHibernation && mDpyValid &&
-                cnx->egl.eglHibernateProcessIMG &&
-                cnx->egl.eglAwakenProcessIMG) {
-            ALOGV("Hibernating\n");
-            if (!cnx->egl.eglHibernateProcessIMG()) {
-                ALOGE("Failed to hibernate EGL implementation\n");
-                return;
-            }
-            mHibernating = true;
-        }
-    }
-}
-
-void egl_display_t::HibernationMachine::setDisplayValid(bool valid) {
-    Mutex::Autolock _l(mLock);
-    mDpyValid = valid;
-}
-
-// ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 2d86295..e17558c 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -68,20 +68,6 @@
     // add reference to this object. returns true if this is a valid object.
     bool getObject(egl_object_t* object) const;
 
-    // These notifications allow the display to keep track of how many window
-    // surfaces exist, which it uses to decide whether to hibernate the
-    // underlying EGL implementation. They can be called by any thread without
-    // holding a lock, but must be called via egl_display_ptr to ensure
-    // proper hibernate/wakeup sequencing. If a surface destruction triggers
-    // hibernation, hibernation will be delayed at least until the calling
-    // thread's egl_display_ptr is destroyed.
-    void onWindowSurfaceCreated() {
-        mHibernation.incWakeCount(HibernationMachine::STRONG);
-    }
-    void onWindowSurfaceDestroyed() {
-        mHibernation.decWakeCount(HibernationMachine::STRONG);
-    }
-
     static egl_display_t* get(EGLDisplay dpy);
     static EGLDisplay getFromNativeDisplay(EGLNativeDisplayType disp);
 
@@ -127,8 +113,6 @@
 
 private:
     friend class egl_display_ptr;
-    bool enter() { return mHibernation.incWakeCount(HibernationMachine::WEAK); }
-    void leave() { return mHibernation.decWakeCount(HibernationMachine::WEAK); }
 
             uint32_t                    refs;
             bool                        eglIsInitialized;
@@ -139,47 +123,6 @@
             String8 mVersionString;
             String8 mClientApiString;
             String8 mExtensionString;
-
-    // HibernationMachine uses its own internal mutex to protect its own data.
-    // The owning egl_display_t's lock may be but is not required to be held
-    // when calling HibernationMachine methods. As a result, nothing in this
-    // class may call back up to egl_display_t directly or indirectly.
-    class HibernationMachine {
-    public:
-        // STRONG refs cancel (inc) or initiate (dec) a hibernation attempt
-        // the next time the wakecount reaches zero. WEAK refs don't affect
-        // whether a hibernation attempt will be made. Use STRONG refs only
-        // for infrequent/heavy changes that are likely to indicate the
-        // EGLDisplay is entering or leaving a long-term idle state.
-        enum WakeRefStrength {
-            WEAK   = 0,
-            STRONG = 1,
-        };
-
-        HibernationMachine(): mWakeCount(0), mHibernating(false),
-                mAttemptHibernation(false), mDpyValid(false),
-#if BOARD_ALLOW_EGL_HIBERNATION
-                mAllowHibernation(true)
-#else
-                mAllowHibernation(false)
-#endif
-        {}
-        ~HibernationMachine() {}
-
-        bool incWakeCount(WakeRefStrength strenth);
-        void decWakeCount(WakeRefStrength strenth);
-
-        void setDisplayValid(bool valid);
-
-    private:
-        Mutex      mLock;
-        int32_t    mWakeCount;
-        bool       mHibernating;
-        bool       mAttemptHibernation;
-        bool       mDpyValid;
-        const bool mAllowHibernation;
-    };
-    HibernationMachine mHibernation;
 };
 
 // ----------------------------------------------------------------------------
@@ -190,13 +133,7 @@
 // as the egl_display_ptr exists.
 class egl_display_ptr {
 public:
-    explicit egl_display_ptr(egl_display_t* dpy): mDpy(dpy) {
-        if (mDpy) {
-            if (CC_UNLIKELY(!mDpy->enter())) {
-                mDpy = NULL;
-            }
-        }
-    }
+    explicit egl_display_ptr(egl_display_t* dpy): mDpy(dpy) {}
 
     // We only really need a C++11 move constructor, not a copy constructor.
     // A move constructor would save an enter()/leave() pair on every EGL API
@@ -208,17 +145,9 @@
     //     other.mDpy = NULL;
     // }
     //
-    egl_display_ptr(const egl_display_ptr& other): mDpy(other.mDpy) {
-        if (mDpy) {
-            mDpy->enter();
-        }
-    }
+    egl_display_ptr(const egl_display_ptr& other): mDpy(other.mDpy) {}
 
-    ~egl_display_ptr() {
-        if (mDpy) {
-            mDpy->leave();
-        }
-    }
+    ~egl_display_ptr() {}
 
     const egl_display_t* operator->() const { return mDpy; }
           egl_display_t* operator->()       { return mDpy; }
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index cfecf77..6a76737 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -69,17 +69,12 @@
         egl_connection_t const* cnx) :
     egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
     enableTimestamps(false), connected(true)
-{
-    if (win) {
-        getDisplay()->onWindowSurfaceCreated();
-    }
-}
+{}
 
 egl_surface_t::~egl_surface_t() {
     ANativeWindow* const window = win.get();
     if (window != NULL) {
         disconnect();
-        getDisplay()->onWindowSurfaceDestroyed();
     }
 }
 
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 7b10319..d6e6187 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -10,7 +10,6 @@
     OrientationSensor.cpp \
     RecentEventLogger.cpp \
     RotationVectorSensor.cpp \
-    SensorDevice.cpp \
     SensorEventConnection.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
@@ -19,13 +18,19 @@
     SensorService.cpp \
     SensorServiceUtils.cpp \
 
-
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
 
 LOCAL_CFLAGS += -Wall -Werror -Wextra
 
 LOCAL_CFLAGS += -fvisibility=hidden
 
+ifeq ($(ENABLE_TREBLE), true)
+LOCAL_SRC_FILES += SensorDeviceTreble.cpp
+LOCAL_CFLAGS += -DENABLE_TREBLE=1
+else
+LOCAL_SRC_FILES += SensorDevice.cpp
+endif
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libhardware \
@@ -35,7 +40,20 @@
     libbinder \
     libui \
     libgui \
-    libcrypto
+    libcrypto \
+
+ifeq ($(ENABLE_TREBLE), true)
+
+LOCAL_SHARED_LIBRARIES += \
+    libbase \
+    libhidl \
+    libhwbinder \
+    android.hardware.sensors@1.0
+
+LOCAL_STATIC_LIBRARIES := \
+    android.hardware.sensors@1.0-convert
+
+endif  # ENABLE_TREBLE
 
 LOCAL_MODULE:= libsensorservice
 
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index d340da3..0bb0752 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -27,19 +27,29 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#ifdef ENABLE_TREBLE
+#include <map>
+
+#include "android/hardware/sensors/1.0/ISensors.h"
+#endif
+
 // ---------------------------------------------------------------------------
 
 namespace android {
+
 // ---------------------------------------------------------------------------
 using SensorServiceUtil::Dumpable;
 
 class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
 public:
     ssize_t getSensorList(sensor_t const** list);
+
     void handleDynamicSensorConnection(int handle, bool connected);
     status_t initCheck() const;
     int getHalDeviceVersion() const;
+
     ssize_t poll(sensors_event_t* buffer, size_t count);
+
     status_t activate(void* ident, int handle, int enabled);
     status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                    int64_t maxBatchReportLatencyNs);
@@ -50,6 +60,7 @@
     void disableAllSensors();
     void enableAllSensors();
     void autoDisable(void *ident, int handle);
+
     status_t injectSensorData(const sensors_event_t *event);
     void notifyConnectionDestroyed(void *ident);
 
@@ -57,8 +68,15 @@
     virtual std::string dump() const;
 private:
     friend class Singleton<SensorDevice>;
+#ifdef ENABLE_TREBLE
+    sp<android::hardware::sensors::V1_0::ISensors> mSensors;
+    Vector<sensor_t> mSensorList;
+    std::map<int32_t, sensor_t*> mConnectedDynamicSensors;
+#else
     sensors_poll_device_1_t* mSensorDevice;
     struct sensors_module_t* mSensorModule;
+#endif
+
     static const nsecs_t MINIMUM_EVENTS_PERIOD =   1000000; // 1000 Hz
     mutable Mutex mLock; // protect mActivationCount[].batchParams
     // fixed-size array after construction
@@ -111,6 +129,18 @@
 
     bool isClientDisabled(void* ident);
     bool isClientDisabledLocked(void* ident);
+
+#ifdef ENABLE_TREBLE
+    using Event = hardware::sensors::V1_0::Event;
+    using SensorInfo = hardware::sensors::V1_0::SensorInfo;
+
+    void convertToSensorEvent(const Event &src, sensors_event_t *dst);
+
+    void convertToSensorEvents(
+            const hardware::hidl_vec<Event> &src,
+            const hardware::hidl_vec<SensorInfo> &dynamicSensorsAdded,
+            sensors_event_t *dst);
+#endif  // ENABLE_TREBLE
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDeviceTreble.cpp b/services/sensorservice/SensorDeviceTreble.cpp
new file mode 100644
index 0000000..22b1105
--- /dev/null
+++ b/services/sensorservice/SensorDeviceTreble.cpp
@@ -0,0 +1,610 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <android-base/logging.h>
+#include <hidl/IServiceManager.h>
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+
+#include "SensorDevice.h"
+#include "SensorService.h"
+
+#include "convert.h"
+
+using android::hardware::sensors::V1_0::ISensors;
+using android::hardware::hidl_vec;
+
+using Event = android::hardware::sensors::V1_0::Event;
+using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
+using SensorType = android::hardware::sensors::V1_0::SensorType;
+using DynamicSensorInfo = android::hardware::sensors::V1_0::DynamicSensorInfo;
+using SensorInfo = android::hardware::sensors::V1_0::SensorInfo;
+using Result = android::hardware::sensors::V1_0::Result;
+
+using namespace android::hardware::sensors::V1_0::implementation;
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SensorDevice)
+
+static status_t StatusFromResult(Result result) {
+    switch (result) {
+        case Result::OK:
+            return OK;
+        case Result::BAD_VALUE:
+            return BAD_VALUE;
+        case Result::PERMISSION_DENIED:
+            return PERMISSION_DENIED;
+        case Result::INVALID_OPERATION:
+            return INVALID_OPERATION;
+    }
+}
+
+SensorDevice::SensorDevice() {
+    mSensors = ISensors::getService("sensors");
+
+    if (mSensors == NULL) {
+        return;
+    }
+
+    mSensors->getSensorsList(
+            [&](const auto &list) {
+                const size_t count = list.size();
+
+                mActivationCount.setCapacity(count);
+                Info model;
+                for (size_t i=0 ; i < count; i++) {
+                    sensor_t sensor;
+                    convertToSensor(list[i], &sensor);
+                    mSensorList.push_back(sensor);
+
+                    mActivationCount.add(list[i].sensorHandle, model);
+
+                    /* auto result = */mSensors->activate(
+                        list[i].sensorHandle, 0 /* enabled */);
+                }
+            });
+}
+
+void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
+    if (connected) {
+        Info model;
+        mActivationCount.add(handle, model);
+        /* auto result = */mSensors->activate(handle, 0 /* enabled */);
+    } else {
+        mActivationCount.removeItem(handle);
+    }
+}
+
+std::string SensorDevice::dump() const {
+    if (mSensors == NULL) return "HAL not initialized\n";
+
+#if 0
+    result.appendFormat("HAL: %s (%s), version %#010x\n",
+                        mSensorModule->common.name,
+                        mSensorModule->common.author,
+                        getHalDeviceVersion());
+#endif
+
+    String8 result;
+    mSensors->getSensorsList([&](const auto &list) {
+            const size_t count = list.size();
+
+            result.appendFormat(
+                "Total %zu h/w sensors, %zu running:\n",
+                count,
+                mActivationCount.size());
+
+            Mutex::Autolock _l(mLock);
+            for (size_t i = 0 ; i < count ; i++) {
+                const Info& info = mActivationCount.valueFor(
+                    list[i].sensorHandle);
+
+                if (info.batchParams.isEmpty()) continue;
+                result.appendFormat(
+                    "0x%08x) active-count = %zu; ",
+                    list[i].sensorHandle,
+                    info.batchParams.size());
+
+                result.append("sampling_period(ms) = {");
+                for (size_t j = 0; j < info.batchParams.size(); j++) {
+                    const BatchParams& params = info.batchParams.valueAt(j);
+                    result.appendFormat(
+                        "%.1f%s",
+                        params.batchDelay / 1e6f,
+                        j < info.batchParams.size() - 1 ? ", " : "");
+                }
+                result.appendFormat(
+                        "}, selected = %.1f ms; ",
+                        info.bestBatchParams.batchDelay / 1e6f);
+
+                result.append("batching_period(ms) = {");
+                for (size_t j = 0; j < info.batchParams.size(); j++) {
+                    BatchParams params = info.batchParams.valueAt(j);
+
+                    result.appendFormat(
+                            "%.1f%s",
+                            params.batchTimeout / 1e6f,
+                            j < info.batchParams.size() - 1 ? ", " : "");
+                }
+
+                result.appendFormat(
+                        "}, selected = %.1f ms\n",
+                        info.bestBatchParams.batchTimeout / 1e6f);
+            }
+        });
+
+    return result.string();
+}
+
+ssize_t SensorDevice::getSensorList(sensor_t const** list) {
+    *list = &mSensorList[0];
+
+    return mSensorList.size();
+}
+
+status_t SensorDevice::initCheck() const {
+    return mSensors != NULL ? NO_ERROR : NO_INIT;
+}
+
+ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
+    if (mSensors == NULL) return NO_INIT;
+
+    ssize_t err;
+
+    mSensors->poll(
+            count,
+            [&](auto result,
+                const auto &events,
+                const auto &dynamicSensorsAdded) {
+                if (result == Result::OK) {
+                    convertToSensorEvents(events, dynamicSensorsAdded, buffer);
+                    err = (ssize_t)events.size();
+                } else {
+                    err = StatusFromResult(result);
+                }
+            });
+
+    return err;
+}
+
+void SensorDevice::autoDisable(void *ident, int handle) {
+    Info& info( mActivationCount.editValueFor(handle) );
+    Mutex::Autolock _l(mLock);
+    info.removeBatchParamsForIdent(ident);
+}
+
+status_t SensorDevice::activate(void* ident, int handle, int enabled) {
+    if (mSensors == NULL) return NO_INIT;
+
+    status_t err(NO_ERROR);
+    bool actuateHardware = false;
+
+    Mutex::Autolock _l(mLock);
+    Info& info( mActivationCount.editValueFor(handle) );
+
+    ALOGD_IF(DEBUG_CONNECTIONS,
+             "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%zu",
+             ident, handle, enabled, info.batchParams.size());
+
+    if (enabled) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
+
+        if (isClientDisabledLocked(ident)) {
+            ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
+                    ident, handle);
+            return INVALID_OPERATION;
+        }
+
+        if (info.batchParams.indexOfKey(ident) >= 0) {
+          if (info.numActiveClients() == 1) {
+              // This is the first connection, we need to activate the underlying h/w sensor.
+              actuateHardware = true;
+          }
+        } else {
+            // Log error. Every activate call should be preceded by a batch() call.
+            ALOGE("\t >>>ERROR: activate called without batch");
+        }
+    } else {
+        ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%zd", info.batchParams.indexOfKey(ident));
+
+        // If a connected dynamic sensor is deactivated, remove it from the
+        // dictionary.
+        auto it = mConnectedDynamicSensors.find(handle);
+        if (it != mConnectedDynamicSensors.end()) {
+            delete it->second;
+            mConnectedDynamicSensors.erase(it);
+        }
+
+        if (info.removeBatchParamsForIdent(ident) >= 0) {
+            if (info.numActiveClients() == 0) {
+                // This is the last connection, we need to de-activate the underlying h/w sensor.
+                actuateHardware = true;
+            } else {
+                const int halVersion = getHalDeviceVersion();
+                if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
+                    // Call batch for this sensor with the previously calculated best effort
+                    // batch_rate and timeout. One of the apps has unregistered for sensor
+                    // events, and the best effort batch parameters might have changed.
+                    ALOGD_IF(DEBUG_CONNECTIONS,
+                             "\t>>> actuating h/w batch %d %d %" PRId64 " %" PRId64, handle,
+                             info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+                             info.bestBatchParams.batchTimeout);
+                    /* auto result = */mSensors->batch(
+                            handle,
+                            info.bestBatchParams.flags,
+                            info.bestBatchParams.batchDelay,
+                            info.bestBatchParams.batchTimeout);
+                }
+            }
+        } else {
+            // sensor wasn't enabled for this ident
+        }
+
+        if (isClientDisabledLocked(ident)) {
+            return NO_ERROR;
+        }
+    }
+
+    if (actuateHardware) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
+                 enabled);
+        err = StatusFromResult(mSensors->activate(handle, enabled));
+        ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
+                 strerror(-err));
+
+        if (err != NO_ERROR && enabled) {
+            // Failure when enabling the sensor. Clean up on failure.
+            info.removeBatchParamsForIdent(ident);
+        }
+    }
+
+    // On older devices which do not support batch, call setDelay().
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.numActiveClients() > 0) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %" PRId64, handle,
+                 info.bestBatchParams.batchDelay);
+        /* auto result = */mSensors->setDelay(
+                handle, info.bestBatchParams.batchDelay);
+    }
+    return err;
+}
+
+status_t SensorDevice::batch(
+        void* ident,
+        int handle,
+        int flags,
+        int64_t samplingPeriodNs,
+        int64_t maxBatchReportLatencyNs) {
+    if (mSensors == NULL) return NO_INIT;
+
+    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
+        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
+    }
+
+    const int halVersion = getHalDeviceVersion();
+    if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
+        // Batch is not supported on older devices return invalid operation.
+        return INVALID_OPERATION;
+    }
+
+    ALOGD_IF(DEBUG_CONNECTIONS,
+             "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%" PRId64 " timeout=%" PRId64,
+             ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
+
+    Mutex::Autolock _l(mLock);
+    Info& info(mActivationCount.editValueFor(handle));
+
+    if (info.batchParams.indexOfKey(ident) < 0) {
+        BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
+        info.batchParams.add(ident, params);
+    } else {
+        // A batch has already been called with this ident. Update the batch parameters.
+        info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
+    }
+
+    BatchParams prevBestBatchParams = info.bestBatchParams;
+    // Find the minimum of all timeouts and batch_rates for this sensor.
+    info.selectBatchParams();
+
+    ALOGD_IF(DEBUG_CONNECTIONS,
+             "\t>>> curr_period=%" PRId64 " min_period=%" PRId64
+             " curr_timeout=%" PRId64 " min_timeout=%" PRId64,
+             prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
+             prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
+
+    status_t err(NO_ERROR);
+    // If the min period or min timeout has changed since the last batch call, call batch.
+    if (prevBestBatchParams != info.bestBatchParams) {
+        if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
+            ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %" PRId64 " %" PRId64, handle,
+                     info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+                     info.bestBatchParams.batchTimeout);
+            err = StatusFromResult(
+                    mSensors->batch(
+                        handle,
+                        info.bestBatchParams.flags,
+                        info.bestBatchParams.batchDelay,
+                        info.bestBatchParams.batchTimeout));
+        } else {
+            // For older devices which do not support batch, call setDelay() after activate() is
+            // called. Some older devices may not support calling setDelay before activate(), so
+            // call setDelay in SensorDevice::activate() method.
+        }
+        if (err != NO_ERROR) {
+            ALOGE("sensor batch failed %p %d %d %" PRId64 " %" PRId64 " err=%s",
+                  mSensors.get(), handle,
+                  info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+                  info.bestBatchParams.batchTimeout, strerror(-err));
+            info.removeBatchParamsForIdent(ident);
+        }
+    }
+    return err;
+}
+
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
+    if (mSensors == NULL) return NO_INIT;
+    if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
+        samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
+    }
+    Mutex::Autolock _l(mLock);
+    if (isClientDisabledLocked(ident)) return INVALID_OPERATION;
+    Info& info( mActivationCount.editValueFor(handle) );
+    // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
+    // Calling setDelay() in batch mode is an invalid operation.
+    if (info.bestBatchParams.batchTimeout != 0) {
+      return INVALID_OPERATION;
+    }
+    ssize_t index = info.batchParams.indexOfKey(ident);
+    if (index < 0) {
+        return BAD_INDEX;
+    }
+    BatchParams& params = info.batchParams.editValueAt(index);
+    params.batchDelay = samplingPeriodNs;
+    info.selectBatchParams();
+
+    return StatusFromResult(
+            mSensors->setDelay(handle, info.bestBatchParams.batchDelay));
+}
+
+int SensorDevice::getHalDeviceVersion() const {
+    if (mSensors == NULL) return -1;
+    return SENSORS_DEVICE_API_VERSION_1_4;
+}
+
+status_t SensorDevice::flush(void* ident, int handle) {
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
+        return INVALID_OPERATION;
+    }
+    if (isClientDisabled(ident)) return INVALID_OPERATION;
+    ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
+    return StatusFromResult(mSensors->flush(handle));
+}
+
+bool SensorDevice::isClientDisabled(void* ident) {
+    Mutex::Autolock _l(mLock);
+    return isClientDisabledLocked(ident);
+}
+
+bool SensorDevice::isClientDisabledLocked(void* ident) {
+    return mDisabledClients.indexOf(ident) >= 0;
+}
+
+void SensorDevice::enableAllSensors() {
+    Mutex::Autolock _l(mLock);
+    mDisabledClients.clear();
+    ALOGI("cleared mDisabledClients");
+    const int halVersion = getHalDeviceVersion();
+    for (size_t i = 0; i< mActivationCount.size(); ++i) {
+        Info& info = mActivationCount.editValueAt(i);
+        if (info.batchParams.isEmpty()) continue;
+        info.selectBatchParams();
+        const int sensor_handle = mActivationCount.keyAt(i);
+        ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
+                   sensor_handle);
+        status_t err(NO_ERROR);
+        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
+            err = StatusFromResult(
+                    mSensors->batch(
+                        sensor_handle,
+                        info.bestBatchParams.flags,
+                        info.bestBatchParams.batchDelay,
+                        info.bestBatchParams.batchTimeout));
+            ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
+        }
+
+        if (err == NO_ERROR) {
+            err = StatusFromResult(
+                    mSensors->activate(sensor_handle, 1 /* enabled */));
+            ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
+        }
+
+        if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) {
+             err = StatusFromResult(
+                     mSensors->setDelay(
+                         sensor_handle, info.bestBatchParams.batchDelay));
+             ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err));
+        }
+    }
+}
+
+void SensorDevice::disableAllSensors() {
+    Mutex::Autolock _l(mLock);
+   for (size_t i = 0; i< mActivationCount.size(); ++i) {
+        const Info& info = mActivationCount.valueAt(i);
+        // Check if this sensor has been activated previously and disable it.
+        if (info.batchParams.size() > 0) {
+           const int sensor_handle = mActivationCount.keyAt(i);
+           ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
+                   sensor_handle);
+           /* auto result = */mSensors->activate(
+                   sensor_handle, 0 /* enabled */);
+
+           // Add all the connections that were registered for this sensor to the disabled
+           // clients list.
+           for (size_t j = 0; j < info.batchParams.size(); ++j) {
+               mDisabledClients.add(info.batchParams.keyAt(j));
+               ALOGI("added %p to mDisabledClients", info.batchParams.keyAt(j));
+           }
+        }
+    }
+}
+
+status_t SensorDevice::injectSensorData(
+        const sensors_event_t *injected_sensor_event) {
+    ALOGD_IF(DEBUG_CONNECTIONS,
+            "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+            injected_sensor_event->sensor,
+            injected_sensor_event->timestamp, injected_sensor_event->data[0],
+            injected_sensor_event->data[1], injected_sensor_event->data[2],
+            injected_sensor_event->data[3], injected_sensor_event->data[4],
+            injected_sensor_event->data[5]);
+
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+        return INVALID_OPERATION;
+    }
+
+    Event ev;
+    convertFromSensorEvent(*injected_sensor_event, &ev);
+
+    return StatusFromResult(mSensors->injectSensorData(ev));
+}
+
+status_t SensorDevice::setMode(uint32_t mode) {
+     if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+          return INVALID_OPERATION;
+     }
+
+     return StatusFromResult(
+             mSensors->setOperationMode(
+                 static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+}
+
+// ---------------------------------------------------------------------------
+
+int SensorDevice::Info::numActiveClients() {
+    SensorDevice& device(SensorDevice::getInstance());
+    int num = 0;
+    for (size_t i = 0; i < batchParams.size(); ++i) {
+        if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
+            ++num;
+        }
+    }
+    return num;
+}
+
+status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
+                                                    int64_t samplingPeriodNs,
+                                                    int64_t maxBatchReportLatencyNs) {
+    ssize_t index = batchParams.indexOfKey(ident);
+    if (index < 0) {
+        ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%" PRId64 " timeout=%" PRId64 ") failed (%s)",
+              ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
+        return BAD_INDEX;
+    }
+    BatchParams& params = batchParams.editValueAt(index);
+    params.flags = flags;
+    params.batchDelay = samplingPeriodNs;
+    params.batchTimeout = maxBatchReportLatencyNs;
+    return NO_ERROR;
+}
+
+void SensorDevice::Info::selectBatchParams() {
+    BatchParams bestParams(0, -1, -1);
+    SensorDevice& device(SensorDevice::getInstance());
+
+    for (size_t i = 0; i < batchParams.size(); ++i) {
+        if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
+        BatchParams params = batchParams.valueAt(i);
+        if (bestParams.batchDelay == -1 || params.batchDelay < bestParams.batchDelay) {
+            bestParams.batchDelay = params.batchDelay;
+        }
+        if (bestParams.batchTimeout == -1 || params.batchTimeout < bestParams.batchTimeout) {
+            bestParams.batchTimeout = params.batchTimeout;
+        }
+    }
+    bestBatchParams = bestParams;
+}
+
+ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
+    ssize_t idx = batchParams.removeItem(ident);
+    if (idx >= 0) {
+        selectBatchParams();
+    }
+    return idx;
+}
+
+void SensorDevice::notifyConnectionDestroyed(void* ident) {
+    Mutex::Autolock _l(mLock);
+    mDisabledClients.remove(ident);
+}
+
+void SensorDevice::convertToSensorEvent(
+        const Event &src, sensors_event_t *dst) {
+    ::android::hardware::sensors::V1_0::implementation::convertToSensorEvent(
+            src, dst);
+
+    if (src.sensorType == SensorType::SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+        const DynamicSensorInfo &dyn = src.u.dynamic;
+
+        dst->dynamic_sensor_meta.connected = dyn.connected;
+        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
+        if (dyn.connected) {
+            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+            CHECK(it != mConnectedDynamicSensors.end());
+
+            dst->dynamic_sensor_meta.sensor = it->second;
+
+            memcpy(dst->dynamic_sensor_meta.uuid,
+                   dyn.uuid.data(),
+                   sizeof(dst->dynamic_sensor_meta.uuid));
+        }
+    }
+}
+
+void SensorDevice::convertToSensorEvents(
+        const hidl_vec<Event> &src,
+        const hidl_vec<SensorInfo> &dynamicSensorsAdded,
+        sensors_event_t *dst) {
+    // Allocate a sensor_t structure for each dynamic sensor added and insert
+    // it into the dictionary of connected dynamic sensors keyed by handle.
+    for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
+        const SensorInfo &info = dynamicSensorsAdded[i];
+
+        auto it = mConnectedDynamicSensors.find(info.sensorHandle);
+        CHECK(it == mConnectedDynamicSensors.end());
+
+        sensor_t *sensor = new sensor_t;
+        convertToSensor(info, sensor);
+
+        mConnectedDynamicSensors.insert(
+                std::make_pair(sensor->handle, sensor));
+    }
+
+    for (size_t i = 0; i < src.size(); ++i) {
+        convertToSensorEvent(src[i], &dst[i]);
+    }
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 58f71eb..f695edb 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -20,6 +20,7 @@
     SurfaceFlingerConsumer.cpp \
     SurfaceInterceptor.cpp \
     Transform.cpp \
+    DisplayHardware/ComposerHal.cpp \
     DisplayHardware/FramebufferSurface.cpp \
     DisplayHardware/HWC2.cpp \
     DisplayHardware/HWC2On1Adapter.cpp \
@@ -127,10 +128,14 @@
 
 LOCAL_STATIC_LIBRARIES := libtrace_proto libvkjson
 LOCAL_SHARED_LIBRARIES := \
+    android.hardware.graphics.allocator@2.0 \
+    android.hardware.graphics.composer@2.1 \
     libcutils \
     liblog \
     libdl \
     libhardware \
+    libhidl \
+    libhwbinder \
     libutils \
     libEGL \
     libGLESv1_CM \
@@ -140,7 +145,18 @@
     libgui \
     libpowermanager \
     libvulkan \
-    libprotobuf-cpp-full
+    libprotobuf-cpp-full \
+    libhidl \
+    libhwbinder \
+    libbase \
+    libutils \
+    android.hardware.power@1.0
+
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
+    android.hardware.graphics.allocator@2.0 \
+    android.hardware.graphics.composer@2.1 \
+    libhidl \
+    libhwbinder
 
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
new file mode 100644
index 0000000..128e2b0
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -0,0 +1,650 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "HwcComposer"
+
+#include <inttypes.h>
+#include <log/log.h>
+
+#include "ComposerHal.h"
+
+namespace android {
+
+using hardware::Return;
+using hardware::hidl_vec;
+
+namespace Hwc2 {
+
+namespace {
+
+class BufferHandle {
+public:
+    BufferHandle(const native_handle_t* buffer)
+    {
+        // nullptr is not a valid handle to HIDL
+        mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
+    }
+
+    operator const native_handle_t*() const
+    {
+        return mHandle;
+    }
+
+private:
+    NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 0, 0);
+    const native_handle_t* mHandle;
+};
+
+class FenceHandle
+{
+public:
+    FenceHandle(int fd, bool owned)
+        : mOwned(owned)
+    {
+        if (fd >= 0) {
+            mHandle = native_handle_init(mStorage, 1, 0);
+            mHandle->data[0] = fd;
+        } else {
+            // nullptr is not a valid handle to HIDL
+            mHandle = native_handle_init(mStorage, 0, 0);
+        }
+    }
+
+    ~FenceHandle()
+    {
+        if (mOwned) {
+            native_handle_close(mHandle);
+        }
+    }
+
+    operator const native_handle_t*() const
+    {
+        return mHandle;
+    }
+
+private:
+    bool mOwned;
+    NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 1, 0);
+    native_handle_t* mHandle;
+};
+
+// assume NO_RESOURCES when Status::isOk returns false
+constexpr Error kDefaultError = Error::NO_RESOURCES;
+
+template<typename T, typename U>
+T unwrapRet(Return<T>& ret, const U& default_val)
+{
+    return (ret.getStatus().isOk()) ? static_cast<T>(ret) :
+        static_cast<T>(default_val);
+}
+
+Error unwrapRet(Return<Error>& ret)
+{
+    return unwrapRet(ret, kDefaultError);
+}
+
+template<typename T>
+void assignFromHidlVec(std::vector<T>& vec, const hidl_vec<T>& data)
+{
+    vec.clear();
+    vec.insert(vec.begin(), &data[0], &data[data.size()]);
+}
+
+} // anonymous namespace
+
+Composer::Composer()
+{
+    mService = IComposer::getService("hwcomposer");
+    if (mService == nullptr) {
+        LOG_ALWAYS_FATAL("failed to get hwcomposer service");
+    }
+}
+
+std::vector<IComposer::Capability> Composer::getCapabilities() const
+{
+    std::vector<IComposer::Capability> capabilities;
+    mService->getCapabilities(
+            [&](const auto& tmpCapabilities) {
+                assignFromHidlVec(capabilities, tmpCapabilities);
+            });
+
+    return capabilities;
+}
+
+std::string Composer::dumpDebugInfo() const
+{
+    std::string info;
+    mService->dumpDebugInfo([&](const auto& tmpInfo) {
+        info = tmpInfo.c_str();
+    });
+
+    return info;
+}
+
+void Composer::registerCallback(const sp<IComposerCallback>& callback) const
+{
+    auto ret = mService->registerCallback(callback);
+    if (!ret.getStatus().isOk()) {
+        ALOGE("failed to register IComposerCallback");
+    }
+}
+
+uint32_t Composer::getMaxVirtualDisplayCount() const
+{
+    auto ret = mService->getMaxVirtualDisplayCount();
+    return unwrapRet(ret, 0);
+}
+
+Error Composer::createVirtualDisplay(uint32_t width, uint32_t height,
+            PixelFormat& format, Display& display) const
+{
+    Error error = kDefaultError;
+    mService->createVirtualDisplay(width, height, format,
+            [&](const auto& tmpError, const auto& tmpDisplay,
+                const auto& tmpFormat) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                display = tmpDisplay;
+                format = tmpFormat;
+            });
+
+    return error;
+}
+
+Error Composer::destroyVirtualDisplay(Display display) const
+{
+    auto ret = mService->destroyVirtualDisplay(display);
+    return unwrapRet(ret);
+}
+
+Error Composer::acceptDisplayChanges(Display display) const
+{
+    auto ret = mService->acceptDisplayChanges(display);
+    return unwrapRet(ret);
+}
+
+Error Composer::createLayer(Display display, Layer& layer) const
+{
+    Error error = kDefaultError;
+    mService->createLayer(display,
+            [&](const auto& tmpError, const auto& tmpLayer) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                layer = tmpLayer;
+            });
+
+    return error;
+}
+
+Error Composer::destroyLayer(Display display, Layer layer) const
+{
+    auto ret = mService->destroyLayer(display, layer);
+    return unwrapRet(ret);
+}
+
+Error Composer::getActiveConfig(Display display, Config& config) const
+{
+    Error error = kDefaultError;
+    mService->getActiveConfig(display,
+            [&](const auto& tmpError, const auto& tmpConfig) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                config = tmpConfig;
+            });
+
+    return error;
+}
+
+Error Composer::getChangedCompositionTypes(Display display,
+        std::vector<Layer>& layers,
+        std::vector<IComposer::Composition>& types) const
+{
+    Error error = kDefaultError;
+    mService->getChangedCompositionTypes(display,
+            [&](const auto& tmpError, const auto& tmpLayers,
+                const auto& tmpTypes) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                assignFromHidlVec(layers, tmpLayers);
+                assignFromHidlVec(types, tmpTypes);
+            });
+
+    return error;
+}
+
+Error Composer::getColorModes(Display display,
+        std::vector<ColorMode>& modes) const
+{
+    Error error = kDefaultError;
+    mService->getColorModes(display,
+            [&](const auto& tmpError, const auto& tmpModes) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                assignFromHidlVec(modes, tmpModes);
+            });
+
+    return error;
+}
+
+Error Composer::getDisplayAttribute(Display display, Config config,
+        IComposer::Attribute attribute, int32_t& value) const
+{
+    Error error = kDefaultError;
+    mService->getDisplayAttribute(display, config, attribute,
+            [&](const auto& tmpError, const auto& tmpValue) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                value = tmpValue;
+            });
+
+    return error;
+}
+
+Error Composer::getDisplayConfigs(Display display,
+        std::vector<Config>& configs) const
+{
+    Error error = kDefaultError;
+    mService->getDisplayConfigs(display,
+            [&](const auto& tmpError, const auto& tmpConfigs) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                assignFromHidlVec(configs, tmpConfigs);
+            });
+
+    return error;
+}
+
+Error Composer::getDisplayName(Display display, std::string& name) const
+{
+    Error error = kDefaultError;
+    mService->getDisplayName(display,
+            [&](const auto& tmpError, const auto& tmpName) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                name = tmpName.c_str();
+            });
+
+    return error;
+}
+
+Error Composer::getDisplayRequests(Display display,
+        uint32_t& displayRequestMask, std::vector<Layer>& layers,
+        std::vector<uint32_t>& layerRequestMasks) const
+{
+    Error error = kDefaultError;
+    mService->getDisplayRequests(display,
+            [&](const auto& tmpError, const auto& tmpDisplayRequestMask,
+                const auto& tmpLayers, const auto& tmpLayerRequestMasks) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                displayRequestMask = tmpDisplayRequestMask;
+                assignFromHidlVec(layers, tmpLayers);
+                assignFromHidlVec(layerRequestMasks, tmpLayerRequestMasks);
+            });
+
+    return error;
+}
+
+Error Composer::getDisplayType(Display display, IComposer::DisplayType& type) const
+{
+    Error error = kDefaultError;
+    mService->getDisplayType(display,
+            [&](const auto& tmpError, const auto& tmpType) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                type = tmpType;
+            });
+
+    return error;
+}
+
+Error Composer::getDozeSupport(Display display, bool& support) const
+{
+    Error error = kDefaultError;
+    mService->getDozeSupport(display,
+            [&](const auto& tmpError, const auto& tmpSupport) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                support = tmpSupport;
+            });
+
+    return error;
+}
+
+Error Composer::getHdrCapabilities(Display display, std::vector<Hdr>& types,
+        float& maxLuminance, float& maxAverageLuminance,
+        float& minLuminance) const
+{
+    Error error = kDefaultError;
+    mService->getHdrCapabilities(display,
+            [&](const auto& tmpError, const auto& tmpTypes,
+                const auto& tmpMaxLuminance,
+                const auto& tmpMaxAverageLuminance,
+                const auto& tmpMinLuminance) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                assignFromHidlVec(types, tmpTypes);
+                maxLuminance = tmpMaxLuminance;
+                maxAverageLuminance = tmpMaxAverageLuminance;
+                minLuminance = tmpMinLuminance;
+            });
+
+    return error;
+}
+
+Error Composer::getReleaseFences(Display display, std::vector<Layer>& layers,
+        std::vector<int>& releaseFences) const
+{
+    Error error = kDefaultError;
+    mService->getReleaseFences(display,
+            [&](const auto& tmpError, const auto& tmpLayers,
+                const auto& tmpReleaseFences) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                if (static_cast<int>(tmpLayers.size()) !=
+                        tmpReleaseFences->numFds) {
+                    ALOGE("invalid releaseFences outputs: "
+                          "layer count %zu != fence count %d",
+                          tmpLayers.size(), tmpReleaseFences->numFds);
+                    error = Error::NO_RESOURCES;
+                    return;
+                }
+
+                // dup the file descriptors
+                std::vector<int> tmpFds;
+                tmpFds.reserve(tmpReleaseFences->numFds);
+                for (int i = 0; i < tmpReleaseFences->numFds; i++) {
+                    int fd = dup(tmpReleaseFences->data[i]);
+                    if (fd < 0) {
+                        break;
+                    }
+                    tmpFds.push_back(fd);
+                }
+                if (static_cast<int>(tmpFds.size()) <
+                        tmpReleaseFences->numFds) {
+                    for (auto fd : tmpFds) {
+                        close(fd);
+                    }
+
+                    error = Error::NO_RESOURCES;
+                    return;
+                }
+
+                assignFromHidlVec(layers, tmpLayers);
+                releaseFences = std::move(tmpFds);
+            });
+
+    return error;
+}
+
+Error Composer::presentDisplay(Display display, int& presentFence) const
+{
+    Error error = kDefaultError;
+    mService->presentDisplay(display,
+            [&](const auto& tmpError, const auto& tmpPresentFence) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                if (tmpPresentFence->numFds == 1) {
+                    int fd = dup(tmpPresentFence->data[0]);
+                    if (fd >= 0) {
+                        presentFence = fd;
+                    } else {
+                        error = Error::NO_RESOURCES;
+                    }
+                } else {
+                    presentFence = -1;
+                }
+            });
+
+    return error;
+}
+
+Error Composer::setActiveConfig(Display display, Config config) const
+{
+    auto ret = mService->setActiveConfig(display, config);
+    return unwrapRet(ret);
+}
+
+Error Composer::setClientTarget(Display display, const native_handle_t* target,
+        int acquireFence, Dataspace dataspace,
+        const std::vector<IComposer::Rect>& damage) const
+{
+    BufferHandle tmpTarget(target);
+    FenceHandle tmpAcquireFence(acquireFence, true);
+
+    hidl_vec<IComposer::Rect> tmpDamage;
+    tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
+            damage.size());
+
+    auto ret = mService->setClientTarget(display, tmpTarget,
+            tmpAcquireFence, dataspace, tmpDamage);
+    return unwrapRet(ret);
+}
+
+Error Composer::setColorMode(Display display, ColorMode mode) const
+{
+    auto ret = mService->setColorMode(display, mode);
+    return unwrapRet(ret);
+}
+
+Error Composer::setColorTransform(Display display, const float* matrix,
+        ColorTransform hint) const
+{
+    hidl_vec<float> tmpMatrix;
+    tmpMatrix.setToExternal(const_cast<float*>(matrix), 16);
+
+    auto ret = mService->setColorTransform(display, tmpMatrix, hint);
+    return unwrapRet(ret);
+}
+
+Error Composer::setOutputBuffer(Display display, const native_handle_t* buffer,
+        int releaseFence) const
+{
+    BufferHandle tmpBuffer(buffer);
+    FenceHandle tmpReleaseFence(releaseFence, false);
+
+    auto ret = mService->setOutputBuffer(display, tmpBuffer, tmpReleaseFence);
+    return unwrapRet(ret);
+}
+
+Error Composer::setPowerMode(Display display, IComposer::PowerMode mode) const
+{
+    auto ret = mService->setPowerMode(display, mode);
+    return unwrapRet(ret);
+}
+
+Error Composer::setVsyncEnabled(Display display, IComposer::Vsync enabled) const
+{
+    auto ret = mService->setVsyncEnabled(display, enabled);
+    return unwrapRet(ret);
+}
+
+Error Composer::validateDisplay(Display display, uint32_t& numTypes, uint32_t&
+        numRequests) const
+{
+    Error error = kDefaultError;
+    mService->validateDisplay(display,
+            [&](const auto& tmpError, const auto& tmpNumTypes,
+                const auto& tmpNumRequests) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                numTypes = tmpNumTypes;
+                numRequests = tmpNumRequests;
+            });
+
+    return error;
+}
+
+Error Composer::setCursorPosition(Display display, Layer layer,
+        int32_t x, int32_t y) const
+{
+    auto ret = mService->setCursorPosition(display, layer, x, y);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerBuffer(Display display, Layer layer,
+        const native_handle_t* buffer, int acquireFence) const
+{
+    BufferHandle tmpBuffer(buffer);
+    FenceHandle tmpAcquireFence(acquireFence, true);
+
+    auto ret = mService->setLayerBuffer(display, layer,
+            tmpBuffer, tmpAcquireFence);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerSurfaceDamage(Display display, Layer layer,
+        const std::vector<IComposer::Rect>& damage) const
+{
+    hidl_vec<IComposer::Rect> tmpDamage;
+    tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
+            damage.size());
+
+    auto ret = mService->setLayerSurfaceDamage(display, layer, tmpDamage);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerBlendMode(Display display, Layer layer,
+        IComposer::BlendMode mode) const
+{
+    auto ret = mService->setLayerBlendMode(display, layer, mode);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerColor(Display display, Layer layer,
+        const IComposer::Color& color) const
+{
+    auto ret = mService->setLayerColor(display, layer, color);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerCompositionType(Display display, Layer layer,
+        IComposer::Composition type) const
+{
+    auto ret = mService->setLayerCompositionType(display, layer, type);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerDataspace(Display display, Layer layer,
+        Dataspace dataspace) const
+{
+    auto ret = mService->setLayerDataspace(display, layer, dataspace);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerDisplayFrame(Display display, Layer layer,
+        const IComposer::Rect& frame) const
+{
+    auto ret = mService->setLayerDisplayFrame(display, layer, frame);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerPlaneAlpha(Display display, Layer layer,
+        float alpha) const
+{
+    auto ret = mService->setLayerPlaneAlpha(display, layer, alpha);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerSidebandStream(Display display, Layer layer,
+        const native_handle_t* stream) const
+{
+    BufferHandle tmpStream(stream);
+
+    auto ret = mService->setLayerSidebandStream(display, layer, tmpStream);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerSourceCrop(Display display, Layer layer,
+        const IComposer::FRect& crop) const
+{
+    auto ret = mService->setLayerSourceCrop(display, layer, crop);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerTransform(Display display, Layer layer,
+        Transform transform) const
+{
+    auto ret = mService->setLayerTransform(display, layer, transform);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerVisibleRegion(Display display, Layer layer,
+        const std::vector<IComposer::Rect>& visible) const
+{
+    hidl_vec<IComposer::Rect> tmpVisible;
+    tmpVisible.setToExternal(const_cast<IComposer::Rect*>(visible.data()),
+            visible.size());
+
+    auto ret = mService->setLayerVisibleRegion(display, layer, tmpVisible);
+    return unwrapRet(ret);
+}
+
+Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z) const
+{
+    auto ret = mService->setLayerZOrder(display, layer, z);
+    return unwrapRet(ret);
+}
+
+} // namespace Hwc2
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
new file mode 100644
index 0000000..fd74a92
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_COMPOSER_HAL_H
+#define ANDROID_SF_COMPOSER_HAL_H
+
+#include <string>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace Hwc2 {
+
+using android::hardware::graphics::allocator::V2_0::PixelFormat;
+
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::Display;
+using android::hardware::graphics::composer::V2_1::Layer;
+using android::hardware::graphics::composer::V2_1::Config;
+
+using android::hardware::graphics::composer::V2_1::ColorMode;
+using android::hardware::graphics::composer::V2_1::Hdr;
+using android::hardware::graphics::composer::V2_1::Dataspace;
+using android::hardware::graphics::composer::V2_1::ColorTransform;
+using android::hardware::graphics::composer::V2_1::Transform;
+
+// Composer is a wrapper to IComposer, a proxy to server-side composer.
+class Composer {
+public:
+    Composer();
+
+    std::vector<IComposer::Capability> getCapabilities() const;
+    std::string dumpDebugInfo() const;
+
+    void registerCallback(const sp<IComposerCallback>& callback) const;
+
+    uint32_t getMaxVirtualDisplayCount() const;
+    Error createVirtualDisplay(uint32_t width, uint32_t height,
+            PixelFormat& format, Display& display) const;
+    Error destroyVirtualDisplay(Display display) const;
+
+    Error acceptDisplayChanges(Display display) const;
+
+    Error createLayer(Display display, Layer& layer) const;
+    Error destroyLayer(Display display, Layer layer) const;
+
+    Error getActiveConfig(Display display, Config& config) const;
+    Error getChangedCompositionTypes(Display display,
+            std::vector<Layer>& layers,
+            std::vector<IComposer::Composition>& types) const;
+    Error getColorModes(Display display, std::vector<ColorMode>& modes) const;
+    Error getDisplayAttribute(Display display, Config config,
+            IComposer::Attribute attribute, int32_t& value) const;
+    Error getDisplayConfigs(Display display,
+            std::vector<Config>& configs) const;
+    Error getDisplayName(Display display, std::string& name) const;
+
+    Error getDisplayRequests(Display display, uint32_t& displayRequestMask,
+            std::vector<Layer>& layers,
+            std::vector<uint32_t>& layerRequestMasks) const;
+
+    Error getDisplayType(Display display, IComposer::DisplayType& type) const;
+    Error getDozeSupport(Display display, bool& support) const;
+    Error getHdrCapabilities(Display display, std::vector<Hdr>& types,
+            float& maxLuminance, float& maxAverageLuminance,
+            float& minLuminance) const;
+
+    Error getReleaseFences(Display display, std::vector<Layer>& layers,
+            std::vector<int>& releaseFences) const;
+
+    Error presentDisplay(Display display, int& presentFence) const;
+
+    Error setActiveConfig(Display display, Config config) const;
+    Error setClientTarget(Display display, const native_handle_t* target,
+            int acquireFence, Dataspace dataspace,
+            const std::vector<IComposer::Rect>& damage) const;
+    Error setColorMode(Display display, ColorMode mode) const;
+    Error setColorTransform(Display display, const float* matrix,
+            ColorTransform hint) const;
+    Error setOutputBuffer(Display display, const native_handle_t* buffer,
+            int releaseFence) const;
+    Error setPowerMode(Display display, IComposer::PowerMode mode) const;
+    Error setVsyncEnabled(Display display, IComposer::Vsync enabled) const;
+
+    Error validateDisplay(Display display, uint32_t& numTypes,
+            uint32_t& numRequests) const;
+
+    Error setCursorPosition(Display display, Layer layer,
+            int32_t x, int32_t y) const;
+    Error setLayerBuffer(Display display, Layer layer,
+            const native_handle_t* buffer, int acquireFence) const;
+    Error setLayerSurfaceDamage(Display display, Layer layer,
+            const std::vector<IComposer::Rect>& damage) const;
+    Error setLayerBlendMode(Display display, Layer layer,
+            IComposer::BlendMode mode) const;
+    Error setLayerColor(Display display, Layer layer,
+            const IComposer::Color& color) const;
+    Error setLayerCompositionType(Display display, Layer layer,
+            IComposer::Composition type) const;
+    Error setLayerDataspace(Display display, Layer layer,
+            Dataspace dataspace) const;
+    Error setLayerDisplayFrame(Display display, Layer layer,
+            const IComposer::Rect& frame) const;
+    Error setLayerPlaneAlpha(Display display, Layer layer,
+            float alpha) const;
+    Error setLayerSidebandStream(Display display, Layer layer,
+            const native_handle_t* stream) const;
+    Error setLayerSourceCrop(Display display, Layer layer,
+            const IComposer::FRect& crop) const;
+    Error setLayerTransform(Display display, Layer layer,
+            Transform transform) const;
+    Error setLayerVisibleRegion(Display display, Layer layer,
+            const std::vector<IComposer::Rect>& visible) const;
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z) const;
+
+private:
+    sp<IComposer> mService;
+};
+
+} // namespace Hwc2
+
+} // namespace android
+
+#endif // ANDROID_SF_COMPOSER_HAL_H
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 4fe3cfd..c79caf4 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -21,6 +21,7 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include "HWC2.h"
+#include "ComposerHal.h"
 
 #include "FloatRect.h"
 
@@ -79,11 +80,16 @@
 using android::Rect;
 using android::Region;
 using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
 
 namespace HWC2 {
 
+namespace Hwc2 = android::Hwc2;
+
 // Device methods
 
+#ifdef BYPASS_IHWC
 Device::Device(hwc2_device_t* device)
   : mHwcDevice(device),
     mCreateVirtualDisplay(nullptr),
@@ -128,6 +134,10 @@
     mSetLayerTransform(nullptr),
     mSetLayerVisibleRegion(nullptr),
     mSetLayerZOrder(nullptr),
+#else
+Device::Device()
+  : mComposer(std::make_unique<Hwc2::Composer>()),
+#endif // BYPASS_IHWC
     mCapabilities(),
     mDisplays(),
     mHotplug(),
@@ -144,9 +154,11 @@
 
 Device::~Device()
 {
+#ifdef BYPASS_IHWC
     if (mHwcDevice == nullptr) {
         return;
     }
+#endif
 
     for (auto element : mDisplays) {
         auto display = element.second.lock();
@@ -175,13 +187,16 @@
         }
     }
 
+#ifdef BYPASS_IHWC
     hwc2_close(mHwcDevice);
+#endif
 }
 
 // Required by HWC2 device
 
 std::string Device::dump() const
 {
+#ifdef BYPASS_IHWC
     uint32_t numBytes = 0;
     mDump(mHwcDevice, &numBytes, nullptr);
 
@@ -189,11 +204,18 @@
     mDump(mHwcDevice, &numBytes, buffer.data());
 
     return std::string(buffer.data(), buffer.size());
+#else
+    return mComposer->dumpDebugInfo();
+#endif
 }
 
 uint32_t Device::getMaxVirtualDisplayCount() const
 {
+#ifdef BYPASS_IHWC
     return mGetMaxVirtualDisplayCount(mHwcDevice);
+#else
+    return mComposer->getMaxVirtualDisplayCount();
+#endif
 }
 
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
@@ -202,9 +224,15 @@
     ALOGI("Creating virtual display");
 
     hwc2_display_t displayId = 0;
+#ifdef BYPASS_IHWC
     int32_t intFormat = static_cast<int32_t>(*format);
     int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
             &intFormat, &displayId);
+#else
+    auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
+    auto intError = mComposer->createVirtualDisplay(width, height,
+            intFormat, displayId);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -315,6 +343,7 @@
 {
     static_assert(sizeof(Capability) == sizeof(int32_t),
             "Capability size has changed");
+#ifdef BYPASS_IHWC
     uint32_t numCapabilities = 0;
     mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
     std::vector<Capability> capabilities(numCapabilities);
@@ -323,6 +352,12 @@
     for (auto capability : capabilities) {
         mCapabilities.emplace(capability);
     }
+#else
+    auto capabilities = mComposer->getCapabilities();
+    for (auto capability : capabilities) {
+        mCapabilities.emplace(static_cast<Capability>(capability));
+    }
+#endif
 }
 
 bool Device::hasCapability(HWC2::Capability capability) const
@@ -333,6 +368,7 @@
 
 void Device::loadFunctionPointers()
 {
+#ifdef BYPASS_IHWC
     // For all of these early returns, we log an error message inside
     // loadFunctionPointer specifying which function failed to load
 
@@ -426,13 +462,48 @@
             mSetLayerVisibleRegion)) return;
     if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
             mSetLayerZOrder)) return;
+#endif // BYPASS_IHWC
 }
 
+namespace {
+class ComposerCallback : public Hwc2::IComposerCallback {
+public:
+    ComposerCallback(Device* device) : mDevice(device) {}
+
+    Return<void> onHotplug(Hwc2::Display display,
+            Connection connected) override
+    {
+        hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
+        return Void();
+    }
+
+    Return<void> onRefresh(Hwc2::Display display) override
+    {
+        refresh_hook(mDevice, display);
+        return Void();
+    }
+
+    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
+    {
+        vsync_hook(mDevice, display, timestamp);
+        return Void();
+    }
+
+private:
+    Device* mDevice;
+};
+} // namespace anonymous
+
 void Device::registerCallbacks()
 {
+#ifdef BYPASS_IHWC
     registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
     registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
     registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
+#else
+    sp<ComposerCallback> callback = new ComposerCallback(this);
+    mComposer->registerCallback(callback);
+#endif
 }
 
 
@@ -441,7 +512,11 @@
 void Device::destroyVirtualDisplay(hwc2_display_t display)
 {
     ALOGI("Destroying virtual display");
+#ifdef BYPASS_IHWC
     int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
+#else
+    auto intError = mComposer->destroyVirtualDisplay(display);
+#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
             " %s (%d)", display, to_string(error).c_str(), intError);
@@ -498,14 +573,22 @@
 
 Error Display::acceptChanges()
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
+#else
+    auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
 {
     hwc2_layer_t layerId = 0;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
+#else
+    auto intError = mDevice.mComposer->createLayer(mId, layerId);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -522,8 +605,12 @@
 {
     ALOGV("[%" PRIu64 "] getActiveConfig", mId);
     hwc2_config_t configId = 0;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
             &configId);
+#else
+    auto intError = mDevice.mComposer->getActiveConfig(mId, configId);
+#endif
     auto error = static_cast<Error>(intError);
 
     if (error != Error::None) {
@@ -546,6 +633,7 @@
 Error Display::getChangedCompositionTypes(
         std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
 {
+#ifdef BYPASS_IHWC
     uint32_t numElements = 0;
     int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
             mId, &numElements, nullptr, nullptr);
@@ -558,6 +646,14 @@
     std::vector<int32_t> types(numElements);
     intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
             &numElements, layerIds.data(), types.data());
+#else
+    std::vector<Hwc2::Layer> layerIds;
+    std::vector<Hwc2::IComposer::Composition> types;
+    auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
+            layerIds, types);
+    uint32_t numElements = layerIds.size();
+    auto error = static_cast<Error>(intError);
+#endif
     error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -583,6 +679,7 @@
 
 Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
+#ifdef BYPASS_IHWC
     uint32_t numModes = 0;
     int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
             &numModes, nullptr);
@@ -595,6 +692,12 @@
     intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
             modes.data());
     error = static_cast<Error>(intError);
+#else
+    std::vector<Hwc2::ColorMode> modes;
+    auto intError = mDevice.mComposer->getColorModes(mId, modes);
+    uint32_t numModes = modes.size();
+    auto error = static_cast<Error>(intError);
+#endif
     if (error != Error::None) {
         return error;
     }
@@ -617,6 +720,7 @@
 
 Error Display::getName(std::string* outName) const
 {
+#ifdef BYPASS_IHWC
     uint32_t size;
     int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
             nullptr);
@@ -635,12 +739,17 @@
 
     *outName = std::string(rawName.cbegin(), rawName.cend());
     return Error::None;
+#else
+    auto intError = mDevice.mComposer->getDisplayName(mId, *outName);
+    return static_cast<Error>(intError);
+#endif
 }
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
         std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
                 outLayerRequests)
 {
+#ifdef BYPASS_IHWC
     int32_t intDisplayRequests = 0;
     uint32_t numElements = 0;
     int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
@@ -656,6 +765,15 @@
             &intDisplayRequests, &numElements, layerIds.data(),
             layerRequests.data());
     error = static_cast<Error>(intError);
+#else
+    uint32_t intDisplayRequests;
+    std::vector<Hwc2::Layer> layerIds;
+    std::vector<uint32_t> layerRequests;
+    auto intError = mDevice.mComposer->getDisplayRequests(mId,
+            intDisplayRequests, layerIds, layerRequests);
+    uint32_t numElements = layerIds.size();
+    auto error = static_cast<Error>(intError);
+#endif
     if (error != Error::None) {
         return error;
     }
@@ -680,9 +798,15 @@
 
 Error Display::getType(DisplayType* outType) const
 {
+#ifdef BYPASS_IHWC
     int32_t intType = 0;
     int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
             &intType);
+#else
+    Hwc2::IComposer::DisplayType intType =
+        Hwc2::IComposer::DisplayType::INVALID;
+    auto intError = mDevice.mComposer->getDisplayType(mId, intType);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -694,9 +818,14 @@
 
 Error Display::supportsDoze(bool* outSupport) const
 {
+#ifdef BYPASS_IHWC
     int32_t intSupport = 0;
     int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
             &intSupport);
+#else
+    bool intSupport = false;
+    auto intError = mDevice.mComposer->getDozeSupport(mId, intSupport);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -712,6 +841,7 @@
     float maxLuminance = -1.0f;
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
             &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
             &minLuminance);
@@ -724,6 +854,18 @@
     intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
             types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
     error = static_cast<HWC2::Error>(intError);
+#else
+    std::vector<Hwc2::Hdr> intTypes;
+    auto intError = mDevice.mComposer->getHdrCapabilities(mId, intTypes,
+            maxLuminance, maxAverageLuminance, minLuminance);
+    auto error = static_cast<HWC2::Error>(intError);
+
+    std::vector<int32_t> types;
+    for (auto type : intTypes) {
+        types.push_back(static_cast<int32_t>(type));
+    }
+    numTypes = types.size();
+#endif
     if (error != Error::None) {
         return error;
     }
@@ -736,6 +878,7 @@
 Error Display::getReleaseFences(
         std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
 {
+#ifdef BYPASS_IHWC
     uint32_t numElements = 0;
     int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
             &numElements, nullptr, nullptr);
@@ -749,6 +892,14 @@
     intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
             layerIds.data(), fenceFds.data());
     error = static_cast<Error>(intError);
+#else
+    std::vector<Hwc2::Layer> layerIds;
+    std::vector<int> fenceFds;
+    auto intError = mDevice.mComposer->getReleaseFences(mId,
+            layerIds, fenceFds);
+    auto error = static_cast<Error>(intError);
+    uint32_t numElements = layerIds.size();
+#endif
     if (error != Error::None) {
         return error;
     }
@@ -774,8 +925,12 @@
 Error Display::present(sp<Fence>* outRetireFence)
 {
     int32_t retireFenceFd = 0;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
             &retireFenceFd);
+#else
+    auto intError = mDevice.mComposer->presentDisplay(mId, retireFenceFd);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -793,8 +948,12 @@
                 config->getDisplayId(), mId);
         return Error::BadConfig;
     }
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
             config->getId());
+#else
+    auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -803,22 +962,38 @@
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
             fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
+#else
+    auto intError = mDevice.mComposer->setClientTarget(mId, target, fenceFd,
+            static_cast<Hwc2::Dataspace>(dataspace),
+            std::vector<Hwc2::IComposer::Rect>());
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorMode(android_color_mode_t mode)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
+#else
+    auto intError = mDevice.mComposer->setColorMode(mId,
+            static_cast<Hwc2::ColorMode>(mode));
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorTransform(const android::mat4& matrix,
         android_color_transform_t hint)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
             matrix.asArray(), static_cast<int32_t>(hint));
+#else
+    auto intError = mDevice.mComposer->setColorTransform(mId,
+            matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -827,24 +1002,38 @@
 {
     int32_t fenceFd = releaseFence->dup();
     auto handle = buffer->getNativeBuffer()->handle;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
             fenceFd);
+#else
+    auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
+#endif
     close(fenceFd);
     return static_cast<Error>(intError);
 }
 
 Error Display::setPowerMode(PowerMode mode)
 {
+#ifdef BYPASS_IHWC
     auto intMode = static_cast<int32_t>(mode);
     int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
+#else
+    auto intMode = static_cast<Hwc2::IComposer::PowerMode>(mode);
+    auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Display::setVsyncEnabled(Vsync enabled)
 {
+#ifdef BYPASS_IHWC
     auto intEnabled = static_cast<int32_t>(enabled);
     int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
             intEnabled);
+#else
+    auto intEnabled = static_cast<Hwc2::IComposer::Vsync>(enabled);
+    auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -852,8 +1041,13 @@
 {
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
             &numTypes, &numRequests);
+#else
+    auto intError = mDevice.mComposer->validateDisplay(mId,
+            numTypes, numRequests);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -869,8 +1063,14 @@
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
             configId, static_cast<int32_t>(attribute), &value);
+#else
+    auto intError = mDevice.mComposer->getDisplayAttribute(mId,
+            configId, static_cast<Hwc2::IComposer::Attribute>(attribute),
+            value);
+#endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
@@ -899,6 +1099,7 @@
 {
     ALOGV("[%" PRIu64 "] loadConfigs", mId);
 
+#ifdef BYPASS_IHWC
     uint32_t numConfigs = 0;
     int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
             &numConfigs, nullptr);
@@ -913,6 +1114,11 @@
     intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
             configIds.data());
     error = static_cast<Error>(intError);
+#else
+    std::vector<Hwc2::Config> configIds;
+    auto intError = mDevice.mComposer->getDisplayConfigs(mId, configIds);
+    auto error = static_cast<Error>(intError);
+#endif
     if (error != Error::None) {
         ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
                 to_string(error).c_str(), intError);
@@ -928,7 +1134,11 @@
 
 void Display::destroyLayer(hwc2_layer_t layerId)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
+#else
+    auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
+#endif
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
             " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
@@ -970,8 +1180,13 @@
 
 Error Layer::setCursorPosition(int32_t x, int32_t y)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
             mDisplayId, mId, x, y);
+#else
+    auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
+            mId, x, y);
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -979,8 +1194,13 @@
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
             mId, buffer, fenceFd);
+#else
+    auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
+            mId, buffer, fenceFd);
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -988,26 +1208,44 @@
 {
     // We encode default full-screen damage as INVALID_RECT upstream, but as 0
     // rects for HWC
+#ifdef BYPASS_IHWC
     int32_t intError = 0;
+#else
+    Hwc2::Error intError = Hwc2::Error::NONE;
+#endif
     if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
+#ifdef BYPASS_IHWC
         intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
                 mDisplayId, mId, {0, nullptr});
+#else
+        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+                mId, std::vector<Hwc2::IComposer::Rect>());
+#endif
     } else {
         size_t rectCount = 0;
         auto rectArray = damage.getArray(&rectCount);
 
+#ifdef BYPASS_IHWC
         std::vector<hwc_rect_t> hwcRects;
+#else
+        std::vector<Hwc2::IComposer::Rect> hwcRects;
+#endif
         for (size_t rect = 0; rect < rectCount; ++rect) {
             hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                     rectArray[rect].right, rectArray[rect].bottom});
         }
 
+#ifdef BYPASS_IHWC
         hwc_region_t hwcRegion = {};
         hwcRegion.numRects = rectCount;
         hwcRegion.rects = hwcRects.data();
 
         intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
                 mDisplayId, mId, hwcRegion);
+#else
+        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+                mId, hwcRects);
+#endif
     }
 
     return static_cast<Error>(intError);
@@ -1015,47 +1253,83 @@
 
 Error Layer::setBlendMode(BlendMode mode)
 {
+#ifdef BYPASS_IHWC
     auto intMode = static_cast<int32_t>(mode);
     int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
             mDisplayId, mId, intMode);
+#else
+    auto intMode = static_cast<Hwc2::IComposer::BlendMode>(mode);
+    auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
+            mId, intMode);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setColor(hwc_color_t color)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
             mId, color);
+#else
+    Hwc2::IComposer::Color hwcColor{color.r, color.g, color.b, color.a};
+    auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
+            mId, hwcColor);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setCompositionType(Composition type)
 {
+#ifdef BYPASS_IHWC
     auto intType = static_cast<int32_t>(type);
     int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
             mDisplayId, mId, intType);
+#else
+    auto intType = static_cast<Hwc2::IComposer::Composition>(type);
+    auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
+            mId, intType);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDataspace(android_dataspace_t dataspace)
 {
+#ifdef BYPASS_IHWC
     auto intDataspace = static_cast<int32_t>(dataspace);
     int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
             mDisplayId, mId, intDataspace);
+#else
+    auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
+    auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
+            mId, intDataspace);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setDisplayFrame(const Rect& frame)
 {
+#ifdef BYPASS_IHWC
     hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
     int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
             mDisplayId, mId, hwcRect);
+#else
+    Hwc2::IComposer::Rect hwcRect{frame.left, frame.top,
+        frame.right, frame.bottom};
+    auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
+            mId, hwcRect);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setPlaneAlpha(float alpha)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
             mDisplayId, mId, alpha);
+#else
+    auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
+            mId, alpha);
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -1066,24 +1340,42 @@
                 "device supports sideband streams");
         return Error::Unsupported;
     }
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
             mDisplayId, mId, stream);
+#else
+    auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
+            mId, stream);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setSourceCrop(const FloatRect& crop)
 {
+#ifdef BYPASS_IHWC
     hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
     int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
             mDisplayId, mId, hwcRect);
+#else
+    Hwc2::IComposer::FRect hwcRect{
+        crop.left, crop.top, crop.right, crop.bottom};
+    auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
+            mId, hwcRect);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setTransform(Transform transform)
 {
+#ifdef BYPASS_IHWC
     auto intTransform = static_cast<int32_t>(transform);
     int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
             mDisplayId, mId, intTransform);
+#else
+    auto intTransform = static_cast<Hwc2::Transform>(transform);
+    auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
+            mId, intTransform);
+#endif
     return static_cast<Error>(intError);
 }
 
@@ -1092,25 +1384,38 @@
     size_t rectCount = 0;
     auto rectArray = region.getArray(&rectCount);
 
+#ifdef BYPASS_IHWC
     std::vector<hwc_rect_t> hwcRects;
+#else
+    std::vector<Hwc2::IComposer::Rect> hwcRects;
+#endif
     for (size_t rect = 0; rect < rectCount; ++rect) {
         hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
                 rectArray[rect].right, rectArray[rect].bottom});
     }
 
+#ifdef BYPASS_IHWC
     hwc_region_t hwcRegion = {};
     hwcRegion.numRects = rectCount;
     hwcRegion.rects = hwcRects.data();
 
     int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
             mDisplayId, mId, hwcRegion);
+#else
+    auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
+            mId, hwcRects);
+#endif
     return static_cast<Error>(intError);
 }
 
 Error Layer::setZOrder(uint32_t z)
 {
+#ifdef BYPASS_IHWC
     int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
             mId, z);
+#else
+    auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
+#endif
     return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 32a9de0..1145ba1 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -17,6 +17,10 @@
 #ifndef ANDROID_SF_HWC2_H
 #define ANDROID_SF_HWC2_H
 
+#ifndef USE_HWC2
+#define BYPASS_IHWC
+#endif
+
 #define HWC2_INCLUDE_STRINGIFICATION
 #define HWC2_USE_CPP11
 #include <hardware/hwcomposer2.h>
@@ -42,6 +46,9 @@
     class GraphicBuffer;
     class Rect;
     class Region;
+    namespace Hwc2 {
+        class Composer;
+    };
 }
 
 namespace HWC2 {
@@ -57,7 +64,11 @@
 class Device
 {
 public:
+#ifdef BYPASS_IHWC
     explicit Device(hwc2_device_t* device);
+#else
+    Device();
+#endif
     ~Device();
 
     friend class HWC2::Display;
@@ -98,6 +109,7 @@
 private:
     // Initialization methods
 
+#ifdef BYPASS_IHWC
     template <typename PFN>
     [[clang::warn_unused_result]] bool loadFunctionPointer(
             FunctionDescriptor desc, PFN& outPFN) {
@@ -121,6 +133,7 @@
         auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
         mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
     }
+#endif
 
     void loadCapabilities();
     void loadFunctionPointers();
@@ -132,6 +145,7 @@
 
     // Member variables
 
+#ifdef BYPASS_IHWC
     hwc2_device_t* mHwcDevice;
 
     // Device function pointers
@@ -181,6 +195,9 @@
     HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
     HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
     HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
+#else
+    std::unique_ptr<android::Hwc2::Composer> mComposer;
+#endif // BYPASS_IHWC
 
     std::unordered_set<Capability> mCapabilities;
     std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c87ba72..bb2e45a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -109,6 +109,7 @@
 {
     ALOGV("loadHwcModule");
 
+#ifdef BYPASS_IHWC
     hw_module_t const* module;
 
     if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
@@ -140,6 +141,9 @@
         mHwcDevice = std::make_unique<HWC2::Device>(
                 static_cast<hwc2_device_t*>(mAdapter.get()));
     }
+#else
+    mHwcDevice = std::make_unique<HWC2::Device>();
+#endif
 
     mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
index bd50b4a..1c0a1fe 100644
--- a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android/hardware/power/1.0/IPower.h>
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -26,6 +27,7 @@
 
 #include "PowerHAL.h"
 
+using android::hardware::power::V1_0::PowerHint;
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -39,7 +41,9 @@
         }
         mPowerManager = interface_cast<IPowerManager>(bs);
     }
-    status_t status = mPowerManager->powerHint(POWER_HINT_VSYNC, enabled ? 1 : 0);
+    status_t status;
+    status = mPowerManager->powerHint(static_cast<int>(PowerHint::VSYNC),
+            enabled ? 1 : 0);
     if(status == DEAD_OBJECT) {
         mPowerManager = NULL;
     }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6a3d62b..d420f0f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1803,127 +1803,81 @@
     }
 
     Region outDirtyRegion;
-    if (mQueuedFrames > 0 || mAutoRefresh) {
+    if (mQueuedFrames <= 0 && !mAutoRefresh) {
+        return outDirtyRegion;
+    }
 
-        // if we've already called updateTexImage() without going through
-        // a composition step, we have to skip this layer at this point
-        // because we cannot call updateTeximage() without a corresponding
-        // compositionComplete() call.
-        // we'll trigger an update in onPreComposition().
-        if (mRefreshPending) {
-            return outDirtyRegion;
+    // if we've already called updateTexImage() without going through
+    // a composition step, we have to skip this layer at this point
+    // because we cannot call updateTeximage() without a corresponding
+    // compositionComplete() call.
+    // we'll trigger an update in onPreComposition().
+    if (mRefreshPending) {
+        return outDirtyRegion;
+    }
+
+    // If the head buffer's acquire fence hasn't signaled yet, return and
+    // try again later
+    if (!headFenceHasSignaled()) {
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    }
+
+    // Capture the old state of the layer for comparisons later
+    const State& s(getDrawingState());
+    const bool oldOpacity = isOpaque(s);
+    sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
+
+    struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
+        Layer::State& front;
+        Layer::State& current;
+        bool& recomputeVisibleRegions;
+        bool stickyTransformSet;
+        const char* name;
+        int32_t overrideScalingMode;
+        bool& freezePositionUpdates;
+
+        Reject(Layer::State& front, Layer::State& current,
+                bool& recomputeVisibleRegions, bool stickySet,
+                const char* name,
+                int32_t overrideScalingMode,
+                bool& freezePositionUpdates)
+            : front(front), current(current),
+              recomputeVisibleRegions(recomputeVisibleRegions),
+              stickyTransformSet(stickySet),
+              name(name),
+              overrideScalingMode(overrideScalingMode),
+              freezePositionUpdates(freezePositionUpdates) {
         }
 
-        // If the head buffer's acquire fence hasn't signaled yet, return and
-        // try again later
-        if (!headFenceHasSignaled()) {
-            mFlinger->signalLayerUpdate();
-            return outDirtyRegion;
-        }
-
-        // Capture the old state of the layer for comparisons later
-        const State& s(getDrawingState());
-        const bool oldOpacity = isOpaque(s);
-        sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
-
-        struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
-            Layer::State& front;
-            Layer::State& current;
-            bool& recomputeVisibleRegions;
-            bool stickyTransformSet;
-            const char* name;
-            int32_t overrideScalingMode;
-            bool& freezePositionUpdates;
-
-            Reject(Layer::State& front, Layer::State& current,
-                    bool& recomputeVisibleRegions, bool stickySet,
-                    const char* name,
-                    int32_t overrideScalingMode,
-                    bool& freezePositionUpdates)
-                : front(front), current(current),
-                  recomputeVisibleRegions(recomputeVisibleRegions),
-                  stickyTransformSet(stickySet),
-                  name(name),
-                  overrideScalingMode(overrideScalingMode),
-                  freezePositionUpdates(freezePositionUpdates) {
+        virtual bool reject(const sp<GraphicBuffer>& buf,
+                const BufferItem& item) {
+            if (buf == NULL) {
+                return false;
             }
 
-            virtual bool reject(const sp<GraphicBuffer>& buf,
-                    const BufferItem& item) {
-                if (buf == NULL) {
-                    return false;
-                }
+            uint32_t bufWidth  = buf->getWidth();
+            uint32_t bufHeight = buf->getHeight();
 
-                uint32_t bufWidth  = buf->getWidth();
-                uint32_t bufHeight = buf->getHeight();
+            // check that we received a buffer of the right size
+            // (Take the buffer's orientation into account)
+            if (item.mTransform & Transform::ROT_90) {
+                swap(bufWidth, bufHeight);
+            }
 
-                // check that we received a buffer of the right size
-                // (Take the buffer's orientation into account)
-                if (item.mTransform & Transform::ROT_90) {
-                    swap(bufWidth, bufHeight);
-                }
+            int actualScalingMode = overrideScalingMode >= 0 ?
+                    overrideScalingMode : item.mScalingMode;
+            bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+            if (front.active != front.requested) {
 
-                int actualScalingMode = overrideScalingMode >= 0 ?
-                        overrideScalingMode : item.mScalingMode;
-                bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-                if (front.active != front.requested) {
-
-                    if (isFixedSize ||
-                            (bufWidth == front.requested.w &&
-                             bufHeight == front.requested.h))
-                    {
-                        // Here we pretend the transaction happened by updating the
-                        // current and drawing states. Drawing state is only accessed
-                        // in this thread, no need to have it locked
-                        front.active = front.requested;
-
-                        // We also need to update the current state so that
-                        // we don't end-up overwriting the drawing state with
-                        // this stale current state during the next transaction
-                        //
-                        // NOTE: We don't need to hold the transaction lock here
-                        // because State::active is only accessed from this thread.
-                        current.active = front.active;
-                        current.modified = true;
-
-                        // recompute visible region
-                        recomputeVisibleRegions = true;
-                    }
-
-                    ALOGD_IF(DEBUG_RESIZE,
-                            "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
-                            "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                            "            requested={ wh={%4u,%4u} }}\n",
-                            name,
-                            bufWidth, bufHeight, item.mTransform, item.mScalingMode,
-                            front.active.w, front.active.h,
-                            front.crop.left,
-                            front.crop.top,
-                            front.crop.right,
-                            front.crop.bottom,
-                            front.crop.getWidth(),
-                            front.crop.getHeight(),
-                            front.requested.w, front.requested.h);
-                }
-
-                if (!isFixedSize && !stickyTransformSet) {
-                    if (front.active.w != bufWidth ||
-                        front.active.h != bufHeight) {
-                        // reject this buffer
-                        ALOGE("[%s] rejecting buffer: "
-                                "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
-                                name, bufWidth, bufHeight, front.active.w, front.active.h);
-                        return true;
-                    }
-                }
-
-                // if the transparent region has changed (this test is
-                // conservative, but that's fine, worst case we're doing
-                // a bit of extra work), we latch the new one and we
-                // trigger a visible-region recompute.
-                if (!front.activeTransparentRegion.isTriviallyEqual(
-                        front.requestedTransparentRegion)) {
-                    front.activeTransparentRegion = front.requestedTransparentRegion;
+                if (isFixedSize ||
+                        (bufWidth == front.requested.w &&
+                         bufHeight == front.requested.h))
+                {
+                    // Here we pretend the transaction happened by updating the
+                    // current and drawing states. Drawing state is only accessed
+                    // in this thread, no need to have it locked
+                    front.active = front.requested;
 
                     // We also need to update the current state so that
                     // we don't end-up overwriting the drawing state with
@@ -1931,206 +1885,254 @@
                     //
                     // NOTE: We don't need to hold the transaction lock here
                     // because State::active is only accessed from this thread.
-                    current.activeTransparentRegion = front.activeTransparentRegion;
+                    current.active = front.active;
+                    current.modified = true;
 
                     // recompute visible region
                     recomputeVisibleRegions = true;
                 }
 
-                if (front.crop != front.requestedCrop) {
-                    front.crop = front.requestedCrop;
-                    current.crop = front.requestedCrop;
-                    recomputeVisibleRegions = true;
+                ALOGD_IF(DEBUG_RESIZE,
+                        "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+                        "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+                        "            requested={ wh={%4u,%4u} }}\n",
+                        name,
+                        bufWidth, bufHeight, item.mTransform, item.mScalingMode,
+                        front.active.w, front.active.h,
+                        front.crop.left,
+                        front.crop.top,
+                        front.crop.right,
+                        front.crop.bottom,
+                        front.crop.getWidth(),
+                        front.crop.getHeight(),
+                        front.requested.w, front.requested.h);
+            }
+
+            if (!isFixedSize && !stickyTransformSet) {
+                if (front.active.w != bufWidth ||
+                    front.active.h != bufHeight) {
+                    // reject this buffer
+                    ALOGE("[%s] rejecting buffer: "
+                            "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
+                            name, bufWidth, bufHeight, front.active.w, front.active.h);
+                    return true;
                 }
-                freezePositionUpdates = false;
-
-                return false;
-            }
-        };
-
-        Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                getProducerStickyTransform() != 0, mName.string(),
-                mOverrideScalingMode, mFreezePositionUpdates);
-
-
-        // Check all of our local sync points to ensure that all transactions
-        // which need to have been applied prior to the frame which is about to
-        // be latched have signaled
-
-        auto headFrameNumber = getHeadFrameNumber();
-        bool matchingFramesFound = false;
-        bool allTransactionsApplied = true;
-        {
-            Mutex::Autolock lock(mLocalSyncPointMutex);
-            for (auto& point : mLocalSyncPoints) {
-                if (point->getFrameNumber() > headFrameNumber) {
-                    break;
-                }
-
-                matchingFramesFound = true;
-
-                if (!point->frameIsAvailable()) {
-                    // We haven't notified the remote layer that the frame for
-                    // this point is available yet. Notify it now, and then
-                    // abort this attempt to latch.
-                    point->setFrameAvailable();
-                    allTransactionsApplied = false;
-                    break;
-                }
-
-                allTransactionsApplied &= point->transactionIsApplied();
-            }
-        }
-
-        if (matchingFramesFound && !allTransactionsApplied) {
-            mFlinger->signalLayerUpdate();
-            return outDirtyRegion;
-        }
-
-        // This boolean is used to make sure that SurfaceFlinger's shadow copy
-        // of the buffer queue isn't modified when the buffer queue is returning
-        // BufferItem's that weren't actually queued. This can happen in shared
-        // buffer mode.
-        bool queuedBuffer = false;
-        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
-                mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
-                mLastFrameNumberReceived);
-        if (updateResult == BufferQueue::PRESENT_LATER) {
-            // Producer doesn't want buffer to be displayed yet.  Signal a
-            // layer update so we check again at the next opportunity.
-            mFlinger->signalLayerUpdate();
-            return outDirtyRegion;
-        } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
-            // If the buffer has been rejected, remove it from the shadow queue
-            // and return early
-            if (queuedBuffer) {
-                Mutex::Autolock lock(mQueueItemLock);
-                mQueueItems.removeAt(0);
-                android_atomic_dec(&mQueuedFrames);
-            }
-            return outDirtyRegion;
-        } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
-            // This can occur if something goes wrong when trying to create the
-            // EGLImage for this buffer. If this happens, the buffer has already
-            // been released, so we need to clean up the queue and bug out
-            // early.
-            if (queuedBuffer) {
-                Mutex::Autolock lock(mQueueItemLock);
-                mQueueItems.clear();
-                android_atomic_and(0, &mQueuedFrames);
             }
 
-            // Once we have hit this state, the shadow queue may no longer
-            // correctly reflect the incoming BufferQueue's contents, so even if
-            // updateTexImage starts working, the only safe course of action is
-            // to continue to ignore updates.
-            mUpdateTexImageFailed = true;
+            // if the transparent region has changed (this test is
+            // conservative, but that's fine, worst case we're doing
+            // a bit of extra work), we latch the new one and we
+            // trigger a visible-region recompute.
+            if (!front.activeTransparentRegion.isTriviallyEqual(
+                    front.requestedTransparentRegion)) {
+                front.activeTransparentRegion = front.requestedTransparentRegion;
 
-            return outDirtyRegion;
-        }
+                // We also need to update the current state so that
+                // we don't end-up overwriting the drawing state with
+                // this stale current state during the next transaction
+                //
+                // NOTE: We don't need to hold the transaction lock here
+                // because State::active is only accessed from this thread.
+                current.activeTransparentRegion = front.activeTransparentRegion;
 
-        if (queuedBuffer) {
-            // Autolock scope
-            auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
-            Mutex::Autolock lock(mQueueItemLock);
-
-            // Remove any stale buffers that have been dropped during
-            // updateTexImage
-            while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
-                mQueueItems.removeAt(0);
-                android_atomic_dec(&mQueuedFrames);
-            }
-
-            mQueueItems.removeAt(0);
-        }
-
-
-        // Decrement the queued-frames count.  Signal another event if we
-        // have more frames pending.
-        if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
-                || mAutoRefresh) {
-            mFlinger->signalLayerUpdate();
-        }
-
-        if (updateResult != NO_ERROR) {
-            // something happened!
-            recomputeVisibleRegions = true;
-            return outDirtyRegion;
-        }
-
-        // update the active buffer
-        mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
-        if (mActiveBuffer == NULL) {
-            // this can only happen if the very first buffer was rejected.
-            return outDirtyRegion;
-        }
-
-        mRefreshPending = true;
-        mFrameLatencyNeeded = true;
-        if (oldActiveBuffer == NULL) {
-             // the first time we receive a buffer, we need to trigger a
-             // geometry invalidation.
-            recomputeVisibleRegions = true;
-         }
-
-        Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
-        const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
-        const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
-        if ((crop != mCurrentCrop) ||
-            (transform != mCurrentTransform) ||
-            (scalingMode != mCurrentScalingMode))
-        {
-            mCurrentCrop = crop;
-            mCurrentTransform = transform;
-            mCurrentScalingMode = scalingMode;
-            recomputeVisibleRegions = true;
-        }
-
-        if (oldActiveBuffer != NULL) {
-            uint32_t bufWidth  = mActiveBuffer->getWidth();
-            uint32_t bufHeight = mActiveBuffer->getHeight();
-            if (bufWidth != uint32_t(oldActiveBuffer->width) ||
-                bufHeight != uint32_t(oldActiveBuffer->height)) {
+                // recompute visible region
                 recomputeVisibleRegions = true;
             }
+
+            if (front.crop != front.requestedCrop) {
+                front.crop = front.requestedCrop;
+                current.crop = front.requestedCrop;
+                recomputeVisibleRegions = true;
+            }
+            freezePositionUpdates = false;
+
+            return false;
+        }
+    };
+
+    Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
+            getProducerStickyTransform() != 0, mName.string(),
+            mOverrideScalingMode, mFreezePositionUpdates);
+
+
+    // Check all of our local sync points to ensure that all transactions
+    // which need to have been applied prior to the frame which is about to
+    // be latched have signaled
+
+    auto headFrameNumber = getHeadFrameNumber();
+    bool matchingFramesFound = false;
+    bool allTransactionsApplied = true;
+    {
+        Mutex::Autolock lock(mLocalSyncPointMutex);
+        for (auto& point : mLocalSyncPoints) {
+            if (point->getFrameNumber() > headFrameNumber) {
+                break;
+            }
+
+            matchingFramesFound = true;
+
+            if (!point->frameIsAvailable()) {
+                // We haven't notified the remote layer that the frame for
+                // this point is available yet. Notify it now, and then
+                // abort this attempt to latch.
+                point->setFrameAvailable();
+                allTransactionsApplied = false;
+                break;
+            }
+
+            allTransactionsApplied &= point->transactionIsApplied();
+        }
+    }
+
+    if (matchingFramesFound && !allTransactionsApplied) {
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    }
+
+    // This boolean is used to make sure that SurfaceFlinger's shadow copy
+    // of the buffer queue isn't modified when the buffer queue is returning
+    // BufferItem's that weren't actually queued. This can happen in shared
+    // buffer mode.
+    bool queuedBuffer = false;
+    status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
+            mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
+            mLastFrameNumberReceived);
+    if (updateResult == BufferQueue::PRESENT_LATER) {
+        // Producer doesn't want buffer to be displayed yet.  Signal a
+        // layer update so we check again at the next opportunity.
+        mFlinger->signalLayerUpdate();
+        return outDirtyRegion;
+    } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
+        // If the buffer has been rejected, remove it from the shadow queue
+        // and return early
+        if (queuedBuffer) {
+            Mutex::Autolock lock(mQueueItemLock);
+            mQueueItems.removeAt(0);
+            android_atomic_dec(&mQueuedFrames);
+        }
+        return outDirtyRegion;
+    } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
+        // This can occur if something goes wrong when trying to create the
+        // EGLImage for this buffer. If this happens, the buffer has already
+        // been released, so we need to clean up the queue and bug out
+        // early.
+        if (queuedBuffer) {
+            Mutex::Autolock lock(mQueueItemLock);
+            mQueueItems.clear();
+            android_atomic_and(0, &mQueuedFrames);
         }
 
-        mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
-        if (oldOpacity != isOpaque(s)) {
+        // Once we have hit this state, the shadow queue may no longer
+        // correctly reflect the incoming BufferQueue's contents, so even if
+        // updateTexImage starts working, the only safe course of action is
+        // to continue to ignore updates.
+        mUpdateTexImageFailed = true;
+
+        return outDirtyRegion;
+    }
+
+    if (queuedBuffer) {
+        // Autolock scope
+        auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+        Mutex::Autolock lock(mQueueItemLock);
+
+        // Remove any stale buffers that have been dropped during
+        // updateTexImage
+        while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+            mQueueItems.removeAt(0);
+            android_atomic_dec(&mQueuedFrames);
+        }
+
+        mQueueItems.removeAt(0);
+    }
+
+
+    // Decrement the queued-frames count.  Signal another event if we
+    // have more frames pending.
+    if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
+            || mAutoRefresh) {
+        mFlinger->signalLayerUpdate();
+    }
+
+    if (updateResult != NO_ERROR) {
+        // something happened!
+        recomputeVisibleRegions = true;
+        return outDirtyRegion;
+    }
+
+    // update the active buffer
+    mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
+    if (mActiveBuffer == NULL) {
+        // this can only happen if the very first buffer was rejected.
+        return outDirtyRegion;
+    }
+
+    mRefreshPending = true;
+    mFrameLatencyNeeded = true;
+    if (oldActiveBuffer == NULL) {
+         // the first time we receive a buffer, we need to trigger a
+         // geometry invalidation.
+        recomputeVisibleRegions = true;
+     }
+
+    Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
+    const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
+    const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
+    if ((crop != mCurrentCrop) ||
+        (transform != mCurrentTransform) ||
+        (scalingMode != mCurrentScalingMode))
+    {
+        mCurrentCrop = crop;
+        mCurrentTransform = transform;
+        mCurrentScalingMode = scalingMode;
+        recomputeVisibleRegions = true;
+    }
+
+    if (oldActiveBuffer != NULL) {
+        uint32_t bufWidth  = mActiveBuffer->getWidth();
+        uint32_t bufHeight = mActiveBuffer->getHeight();
+        if (bufWidth != uint32_t(oldActiveBuffer->width) ||
+            bufHeight != uint32_t(oldActiveBuffer->height)) {
             recomputeVisibleRegions = true;
         }
+    }
 
-        mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+    mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
+    if (oldOpacity != isOpaque(s)) {
+        recomputeVisibleRegions = true;
+    }
 
-        // Remove any sync points corresponding to the buffer which was just
-        // latched
-        {
-            Mutex::Autolock lock(mLocalSyncPointMutex);
-            auto point = mLocalSyncPoints.begin();
-            while (point != mLocalSyncPoints.end()) {
-                if (!(*point)->frameIsAvailable() ||
-                        !(*point)->transactionIsApplied()) {
-                    // This sync point must have been added since we started
-                    // latching. Don't drop it yet.
-                    ++point;
-                    continue;
-                }
+    mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
 
-                if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
-                    point = mLocalSyncPoints.erase(point);
-                } else {
-                    ++point;
-                }
+    // Remove any sync points corresponding to the buffer which was just
+    // latched
+    {
+        Mutex::Autolock lock(mLocalSyncPointMutex);
+        auto point = mLocalSyncPoints.begin();
+        while (point != mLocalSyncPoints.end()) {
+            if (!(*point)->frameIsAvailable() ||
+                    !(*point)->transactionIsApplied()) {
+                // This sync point must have been added since we started
+                // latching. Don't drop it yet.
+                ++point;
+                continue;
+            }
+
+            if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+                point = mLocalSyncPoints.erase(point);
+            } else {
+                ++point;
             }
         }
-
-        // FIXME: postedRegion should be dirty & bounds
-        Region dirtyRegion(Rect(s.active.w, s.active.h));
-
-        // transform the dirty region to window-manager space
-        outDirtyRegion = (s.active.transform.transform(dirtyRegion));
     }
+
+    // FIXME: postedRegion should be dirty & bounds
+    Region dirtyRegion(Rect(s.active.w, s.active.h));
+
+    // transform the dirty region to window-manager space
+    outDirtyRegion = (s.active.transform.transform(dirtyRegion));
+
     return outDirtyRegion;
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a0e040b..e5b57f5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1836,9 +1836,12 @@
 
 void SurfaceFlinger::commitTransaction()
 {
-    if (!mLayersPendingRemoval.isEmpty()) {
+    sp<const DisplayDevice> hw = getDefaultDisplayDevice();
+
+    if (!mLayersPendingRemoval.isEmpty() && hw->isDisplayOn()) {
         // Notify removed layers now that they can't be drawn from
         for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
+            mCurrentState.layersSortedByZ.remove(mLayersPendingRemoval[i]);
             recordBufferingStats(mLayersPendingRemoval[i]->getName().string(),
                     mLayersPendingRemoval[i]->getOccupancyHistory(true));
             mLayersPendingRemoval[i]->onRemoved();
@@ -2285,14 +2288,10 @@
         return NO_ERROR;
     }
 
-    ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
-    if (index >= 0) {
-        mLayersPendingRemoval.push(layer);
-        mLayersRemoved = true;
-        setTransactionFlags(eTransactionNeeded);
-        return NO_ERROR;
-    }
-    return status_t(index);
+    mLayersPendingRemoval.push(layer);
+    mLayersRemoved = true;
+    setTransactionFlags(eTransactionNeeded);
+    return NO_ERROR;
 }
 
 uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t /* flags */) {
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index e0e4c61..6f2520b 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -70,6 +70,14 @@
         return err;
     }
 
+    if (autoRefresh) {
+        *autoRefresh = item.mAutoRefresh;
+    }
+
+    if (queuedBuffer) {
+        *queuedBuffer = item.mQueuedBuffer;
+    }
+
     // We call the rejecter here, in case the caller has a reason to
     // not accept this buffer.  This is used by SurfaceFlinger to
     // reject buffers which have the wrong size
@@ -79,14 +87,6 @@
         return BUFFER_REJECTED;
     }
 
-    if (autoRefresh) {
-        *autoRefresh = item.mAutoRefresh;
-    }
-
-    if (queuedBuffer) {
-        *queuedBuffer = item.mQueuedBuffer;
-    }
-
     // Release the previous buffer.
 #ifdef USE_HWC2
     err = updateAndReleaseLocked(item, &mPendingRelease);
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index e5dffe5..4f1a8e6 100644
--- a/services/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
@@ -3,8 +3,6 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
-LOCAL_CFLAGS := -std=c++14
-
 LOCAL_MODULE := SurfaceFlinger_test
 
 LOCAL_MODULE_TAGS := tests