Merge "GpuStats: track Vulkan apps not doing pre-rotation correctly"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 064a268..75dec37 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -138,6 +138,7 @@
 
 cc_binary {
     name: "otapreopt_chroot",
+    defaults: ["libapexd-deps"],
     cflags: [
         "-Wall",
         "-Werror",
@@ -150,22 +151,11 @@
     ],
     shared_libs: [
         "libbase",
-        "libbinder",
-        "libcrypto",
         "liblog",
-        "libprotobuf-cpp-full",
-        "libselinux",
         "libutils",
-        "libziparchive",
     ],
     static_libs: [
-        "libapex",
         "libapexd",
-        "lib_apex_manifest_proto",
-        "libavb",
-        "libdm",
-        "libverity_tree",
-        "libvold_binder",
     ],
 }
 
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index f7dd8c8..495cc80 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -72,14 +72,18 @@
 
 cc_test {
     name: "lshal_test",
+    test_suites: ["device-tests"],
     defaults: ["lshal_defaults"],
     gtest: true,
     static_libs: [
-        "libgmock"
+        "android.hardware.tests.baz@1.0",
+        "libgmock",
     ],
     shared_libs: [
+        "libhwbinder",
+        "libhidlbase",
+        "libhidltransport",
         "libvintf",
-        "android.hardware.tests.baz@1.0"
     ],
     srcs: [
         "test.cpp"
diff --git a/cmds/lshal/TEST_MAPPING b/cmds/lshal/TEST_MAPPING
new file mode 100644
index 0000000..0320624
--- /dev/null
+++ b/cmds/lshal/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+  "presubmit": [
+    {
+      "name": "lshal_test"
+    }
+  ]
+}
+
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index fc8d58b..76f7c7f 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -493,19 +493,19 @@
 TEST_F(ListTest, DumpDefault) {
     const std::string expected =
         "[fake description 0]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
-        "Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     N a.h.foo1@1.0::IFoo/1 11/21      1      2 4\n"
+        "X     Y a.h.foo2@2.0::IFoo/2 12/22      2      3 5\n"
         "\n"
         "[fake description 1]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
-        "? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     ? a.h.foo3@3.0::IFoo/3 N/A        N/A    4 6\n"
+        "X     ? a.h.foo4@4.0::IFoo/4 N/A        N/A    5 7\n"
         "\n"
         "[fake description 2]\n"
-        "R Interface            Thread Use Server Clients\n"
-        "? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
-        "? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
+        "VINTF R Interface            Thread Use Server Clients\n"
+        "X     ? a.h.foo5@5.0::IFoo/5 N/A        N/A    6 8\n"
+        "X     ? a.h.foo6@6.0::IFoo/6 N/A        N/A    7 9\n"
         "\n";
 
     optind = 1; // mimic Lshal::parseArg()
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
new file mode 100644
index 0000000..f4005c4
--- /dev/null
+++ b/cmds/servicemanager/Access.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 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 "Access.h"
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+#include <log/log_safetynet.h>
+#include <selinux/android.h>
+#include <selinux/avc.h>
+
+namespace android {
+
+#ifdef VENDORSERVICEMANAGER
+constexpr bool kIsVendor = true;
+#else
+constexpr bool kIsVendor = false;
+#endif
+
+static std::string getPidcon(pid_t pid) {
+    android_errorWriteLog(0x534e4554, "121035042");
+
+    char* lookup = nullptr;
+    if (getpidcon(pid, &lookup) < 0) {
+        LOG(ERROR) << "SELinux: getpidcon(pid=" << pid << ") failed to retrieve pid context";
+        return "";
+    }
+    std::string result = lookup;
+    freecon(lookup);
+    return result;
+}
+
+static struct selabel_handle* getSehandle() {
+    static struct selabel_handle* gSehandle = nullptr;
+
+    if (gSehandle != nullptr && selinux_status_updated()) {
+        selabel_close(gSehandle);
+        gSehandle = nullptr;
+    }
+
+    if (gSehandle == nullptr) {
+        gSehandle = kIsVendor
+            ? selinux_android_vendor_service_context_handle()
+            : selinux_android_service_context_handle();
+    }
+
+    CHECK(gSehandle != nullptr);
+    return gSehandle;
+}
+
+static int auditCallback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
+    const Access::CallingContext* ad = reinterpret_cast<Access::CallingContext*>(data);
+
+    if (!ad) {
+        LOG(ERROR) << "No service manager audit data";
+        return 0;
+    }
+
+    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name.c_str(), ad->debugPid, ad->uid);
+    return 0;
+}
+
+Access::Access() {
+    union selinux_callback cb;
+
+    cb.func_audit = auditCallback;
+    selinux_set_callback(SELINUX_CB_AUDIT, cb);
+
+    cb.func_log = kIsVendor ? selinux_vendor_log_callback : selinux_log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+    CHECK(selinux_status_open(true /*fallback*/) >= 0);
+
+    CHECK(getcon(&mThisProcessContext) == 0);
+}
+
+Access::~Access() {
+    freecon(mThisProcessContext);
+}
+
+Access::CallingContext Access::getCallingContext(const std::string& name) {
+    IPCThreadState* ipc = IPCThreadState::self();
+
+    const char* callingSid = ipc->getCallingSid();
+    pid_t callingPid = ipc->getCallingPid();
+
+    return CallingContext {
+        .debugPid = callingPid,
+        .uid = ipc->getCallingUid(),
+        .sid = callingSid ? std::string(callingSid) : getPidcon(callingPid),
+        .name = name,
+    };
+}
+
+bool Access::canFind(const CallingContext& ctx) {
+    return actionAllowedFromLookup(ctx, "find");
+}
+
+bool Access::canAdd(const CallingContext& ctx) {
+    return actionAllowedFromLookup(ctx, "add");
+}
+
+bool Access::canList(const CallingContext& ctx) {
+    CHECK(ctx.name == "");
+
+    return actionAllowed(ctx, mThisProcessContext, "list");
+}
+
+bool Access::actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm) {
+    const char* tclass = "service_manager";
+
+    return 0 == selinux_check_access(sctx.sid.c_str(), tctx, tclass, perm, reinterpret_cast<void*>(const_cast<CallingContext*>((&sctx))));
+}
+
+bool Access::actionAllowedFromLookup(const CallingContext& sctx, const char *perm) {
+    char *tctx = nullptr;
+    if (selabel_lookup(getSehandle(), &tctx, sctx.name.c_str(), 0) != 0) {
+        LOG(ERROR) << "SELinux: No match for " << sctx.name << " in service_contexts.\n";
+        return false;
+    }
+
+    bool allowed = actionAllowed(sctx, tctx, perm);
+    freecon(tctx);
+    return allowed;
+}
+
+}  // android
diff --git a/cmds/servicemanager/Access.h b/cmds/servicemanager/Access.h
new file mode 100644
index 0000000..b2c78cc
--- /dev/null
+++ b/cmds/servicemanager/Access.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <sys/types.h>
+
+namespace android {
+
+// singleton
+class Access {
+public:
+    Access();
+    virtual ~Access();
+
+    Access(const Access&) = delete;
+    Access& operator=(const Access&) = delete;
+    Access(Access&&) = delete;
+    Access& operator=(Access&&) = delete;
+
+    struct CallingContext {
+        pid_t debugPid;
+        uid_t uid;
+        std::string sid;
+
+        // name of the service
+        //
+        // empty if call is unrelated to service (e.g. list)
+        std::string name;
+    };
+
+    virtual CallingContext getCallingContext(const std::string& name);
+
+    virtual bool canFind(const CallingContext& ctx);
+    virtual bool canAdd(const CallingContext& ctx);
+    virtual bool canList(const CallingContext& ctx);
+
+private:
+    bool actionAllowed(const CallingContext& sctx, const char* tctx, const char* perm);
+    bool actionAllowedFromLookup(const CallingContext& sctx, const char *perm);
+
+    char* mThisProcessContext = nullptr;
+};
+
+};
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 428561b..9cf3c5c 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,51 +1,51 @@
 cc_defaults {
-    name: "servicemanager_flags",
+    name: "servicemanager_defaults",
 
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
     ],
-    product_variables: {
-        binder32bit: {
-            cflags: ["-DBINDER_IPC_32BIT=1"],
-        },
-    },
 
-    shared_libs: ["liblog"],
-}
-
-cc_binary {
-    name: "bctest",
-    defaults: ["servicemanager_flags"],
     srcs: [
-        "bctest.c",
-        "binder.c",
+        "Access.cpp",
+        "ServiceManager.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder", // also contains servicemanager_interface
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libselinux",
     ],
 }
 
 cc_binary {
     name: "servicemanager",
-    defaults: ["servicemanager_flags"],
-    srcs: [
-        "service_manager.c",
-        "binder.c",
-    ],
-    shared_libs: ["libcutils", "libselinux"],
+    defaults: ["servicemanager_defaults"],
     init_rc: ["servicemanager.rc"],
+    srcs: ["main.cpp"],
 }
 
 cc_binary {
     name: "vndservicemanager",
-    defaults: ["servicemanager_flags"],
+    defaults: ["servicemanager_defaults"],
+    init_rc: ["vndservicemanager.rc"],
     vendor: true,
-    srcs: [
-        "service_manager.c",
-        "binder.c",
-    ],
     cflags: [
         "-DVENDORSERVICEMANAGER=1",
     ],
-    shared_libs: ["libcutils", "libselinux"],
-    init_rc: ["vndservicemanager.rc"],
+    srcs: ["main.cpp"],
+}
+
+cc_test {
+    name: "servicemanager_test",
+    test_suites: ["device-tests"],
+    defaults: ["servicemanager_defaults"],
+    srcs: [
+        "test_sm.cpp",
+    ],
+    static_libs: ["libgmock"],
 }
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
new file mode 100644
index 0000000..b88b67d
--- /dev/null
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 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 "ServiceManager.h"
+
+#include <android-base/logging.h>
+#include <cutils/android_filesystem_config.h>
+#include <cutils/multiuser.h>
+
+using ::android::binder::Status;
+
+namespace android {
+
+ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
+
+Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
+    // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons.
+    return checkService(name, outBinder);
+}
+
+Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+    auto ctx = mAccess->getCallingContext(name);
+
+    auto it = mNameToService.find(name);
+    if (it == mNameToService.end()) {
+        *outBinder = nullptr;
+        return Status::ok();
+    }
+
+    const Service& service = it->second;
+
+    if (!service.allowIsolated) {
+        uid_t appid = multiuser_get_app_id(ctx.uid);
+        bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
+
+        if (isIsolated) {
+            *outBinder = nullptr;
+            return Status::ok();
+        }
+    }
+
+    // TODO(b/136023468): move this check to be first
+    if (!mAccess->canFind(ctx)) {
+        // returns ok and null for legacy reasons
+        *outBinder = nullptr;
+        return Status::ok();
+    }
+
+    *outBinder = service.binder;
+    return Status::ok();
+}
+
+Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
+    auto ctx = mAccess->getCallingContext(name);
+
+    // apps cannot add services
+    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    if (!mAccess->canAdd(ctx)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    if (binder == nullptr) {
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    }
+
+    // match legacy rules
+    if (name.size() == 0 || name.size() > 127) {
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (OK != binder->linkToDeath(this)) {
+        LOG(ERROR) << "Could not linkToDeath when adding " << name;
+        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
+    }
+
+    auto it = mNameToService.find(name);
+    if (it != mNameToService.end()) {
+        if (OK != it->second.binder->unlinkToDeath(this)) {
+            LOG(WARNING) << "Could not unlinkToDeath when adding " << name;
+        }
+    }
+
+    mNameToService[name] = Service {
+        .binder = binder,
+        .allowIsolated = allowIsolated,
+        .dumpPriority = dumpPriority,
+    };
+
+    return Status::ok();
+}
+
+Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
+    if (!mAccess->canList(mAccess->getCallingContext(""))) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    size_t toReserve = 0;
+    for (auto const& [name, service] : mNameToService) {
+        (void) name;
+
+        if (service.dumpPriority & dumpPriority) ++toReserve;
+    }
+
+    CHECK(outList->empty());
+
+    outList->reserve(toReserve);
+    for (auto const& [name, service] : mNameToService) {
+        (void) service;
+
+        if (service.dumpPriority & dumpPriority) {
+            outList->push_back(name);
+        }
+    }
+
+    return Status::ok();
+}
+
+void ServiceManager::binderDied(const wp<IBinder>& who) {
+    for (auto it = mNameToService.begin(); it != mNameToService.end();) {
+        if (who == it->second.binder) {
+            it = mNameToService.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
new file mode 100644
index 0000000..78e4805
--- /dev/null
+++ b/cmds/servicemanager/ServiceManager.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <android/os/BnServiceManager.h>
+
+#include "Access.h"
+
+namespace android {
+
+class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
+public:
+    ServiceManager(std::unique_ptr<Access>&& access);
+
+    binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
+    binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
+    binder::Status addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) override;
+    binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
+
+    void binderDied(const wp<IBinder>& who) override;
+
+private:
+    struct Service {
+        sp<IBinder> binder;
+        bool allowIsolated;
+        int32_t dumpPriority;
+    };
+
+    std::map<std::string, Service> mNameToService;
+    std::unique_ptr<Access> mAccess;
+};
+
+}  // namespace android
diff --git a/cmds/servicemanager/TEST_MAPPING b/cmds/servicemanager/TEST_MAPPING
new file mode 100644
index 0000000..3e47269
--- /dev/null
+++ b/cmds/servicemanager/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "servicemanager_test"
+    }
+  ]
+}
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
deleted file mode 100644
index 354df67..0000000
--- a/cmds/servicemanager/bctest.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "binder.h"
-
-uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
-{
-    uint32_t handle;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
-        return 0;
-
-    handle = bio_get_ref(&reply);
-
-    if (handle)
-        binder_acquire(bs, handle);
-
-    binder_done(bs, &msg, &reply);
-
-    return handle;
-}
-
-int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
-{
-    int status;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-    bio_put_obj(&msg, ptr);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
-        return -1;
-
-    status = bio_get_uint32(&reply);
-
-    binder_done(bs, &msg, &reply);
-
-    return status;
-}
-
-unsigned token;
-
-int main(int argc, char **argv)
-{
-    struct binder_state *bs;
-    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
-    uint32_t handle;
-
-    bs = binder_open("/dev/binder", 128*1024);
-    if (!bs) {
-        fprintf(stderr, "failed to open binder driver\n");
-        return -1;
-    }
-
-    argc--;
-    argv++;
-    while (argc > 0) {
-        if (!strcmp(argv[0],"alt")) {
-            handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
-            if (!handle) {
-                fprintf(stderr,"cannot find alt_svc_mgr\n");
-                return -1;
-            }
-            svcmgr = handle;
-            fprintf(stderr,"svcmgr is via %x\n", handle);
-        } else if (!strcmp(argv[0],"lookup")) {
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            handle = svcmgr_lookup(bs, svcmgr, argv[1]);
-            fprintf(stderr,"lookup(%s) = %x\n", argv[1], handle);
-            argc--;
-            argv++;
-        } else if (!strcmp(argv[0],"publish")) {
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            svcmgr_publish(bs, svcmgr, argv[1], &token);
-            argc--;
-            argv++;
-        } else {
-            fprintf(stderr,"unknown command %s\n", argv[0]);
-            return -1;
-        }
-        argc--;
-        argv++;
-    }
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
deleted file mode 100644
index cf3b172..0000000
--- a/cmds/servicemanager/binder.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#define LOG_TAG "Binder"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include "binder.h"
-
-#define MAX_BIO_SIZE (1 << 30)
-
-#define TRACE 0
-
-void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
-
-#if TRACE
-void hexdump(void *_data, size_t len)
-{
-    unsigned char *data = _data;
-    size_t count;
-
-    for (count = 0; count < len; count++) {
-        if ((count & 15) == 0)
-            fprintf(stderr,"%04zu:", count);
-        fprintf(stderr," %02x %c", *data,
-                (*data < 32) || (*data > 126) ? '.' : *data);
-        data++;
-        if ((count & 15) == 15)
-            fprintf(stderr,"\n");
-    }
-    if ((count & 15) != 0)
-        fprintf(stderr,"\n");
-}
-
-void binder_dump_txn(struct binder_transaction_data *txn)
-{
-    struct flat_binder_object *obj;
-    binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
-    size_t count = txn->offsets_size / sizeof(binder_size_t);
-
-    fprintf(stderr,"  target %016"PRIx64"  cookie %016"PRIx64"  code %08x  flags %08x\n",
-            (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
-    fprintf(stderr,"  pid %8d  uid %8d  data %"PRIu64"  offs %"PRIu64"\n",
-            txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
-    hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
-    while (count--) {
-        obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
-        fprintf(stderr,"  - type %08x  flags %08x  ptr %016"PRIx64"  cookie %016"PRIx64"\n",
-                obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
-    }
-}
-
-#define NAME(n) case n: return #n
-const char *cmd_name(uint32_t cmd)
-{
-    switch(cmd) {
-        NAME(BR_NOOP);
-        NAME(BR_TRANSACTION_COMPLETE);
-        NAME(BR_INCREFS);
-        NAME(BR_ACQUIRE);
-        NAME(BR_RELEASE);
-        NAME(BR_DECREFS);
-        NAME(BR_TRANSACTION);
-        NAME(BR_REPLY);
-        NAME(BR_FAILED_REPLY);
-        NAME(BR_DEAD_REPLY);
-        NAME(BR_DEAD_BINDER);
-    default: return "???";
-    }
-}
-#else
-#define hexdump(a,b) do{} while (0)
-#define binder_dump_txn(txn)  do{} while (0)
-#endif
-
-#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
-#define BIO_F_OVERFLOW  0x02  /* ran out of space */
-#define BIO_F_IOERROR   0x04
-#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
-
-struct binder_state
-{
-    int fd;
-    void *mapped;
-    size_t mapsize;
-};
-
-struct binder_state *binder_open(const char* driver, size_t mapsize)
-{
-    struct binder_state *bs;
-    struct binder_version vers;
-
-    bs = malloc(sizeof(*bs));
-    if (!bs) {
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
-    if (bs->fd < 0) {
-        fprintf(stderr,"binder: cannot open %s (%s)\n",
-                driver, strerror(errno));
-        goto fail_open;
-    }
-
-    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
-        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
-        fprintf(stderr,
-                "binder: kernel driver version (%d) differs from user space version (%d)\n",
-                vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
-        goto fail_open;
-    }
-
-    bs->mapsize = mapsize;
-    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
-    if (bs->mapped == MAP_FAILED) {
-        fprintf(stderr,"binder: cannot map device (%s)\n",
-                strerror(errno));
-        goto fail_map;
-    }
-
-    return bs;
-
-fail_map:
-    close(bs->fd);
-fail_open:
-    free(bs);
-    return NULL;
-}
-
-void binder_close(struct binder_state *bs)
-{
-    munmap(bs->mapped, bs->mapsize);
-    close(bs->fd);
-    free(bs);
-}
-
-int binder_become_context_manager(struct binder_state *bs)
-{
-    struct flat_binder_object obj;
-    memset(&obj, 0, sizeof(obj));
-    obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
-
-    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
-
-    // fallback to original method
-    if (result != 0) {
-        android_errorWriteLog(0x534e4554, "121035042");
-
-        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
-    }
-    return result;
-}
-
-int binder_write(struct binder_state *bs, void *data, size_t len)
-{
-    struct binder_write_read bwr;
-    int res;
-
-    bwr.write_size = len;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (uintptr_t) data;
-    bwr.read_size = 0;
-    bwr.read_consumed = 0;
-    bwr.read_buffer = 0;
-    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-    if (res < 0) {
-        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
-                strerror(errno));
-    }
-    return res;
-}
-
-void binder_free_buffer(struct binder_state *bs,
-                        binder_uintptr_t buffer_to_free)
-{
-    struct {
-        uint32_t cmd_free;
-        binder_uintptr_t buffer;
-    } __attribute__((packed)) data;
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
-    binder_write(bs, &data, sizeof(data));
-}
-
-void binder_send_reply(struct binder_state *bs,
-                       struct binder_io *reply,
-                       binder_uintptr_t buffer_to_free,
-                       int status)
-{
-    struct {
-        uint32_t cmd_free;
-        binder_uintptr_t buffer;
-        uint32_t cmd_reply;
-        struct binder_transaction_data txn;
-    } __attribute__((packed)) data;
-
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
-    data.cmd_reply = BC_REPLY;
-    data.txn.target.ptr = 0;
-    data.txn.cookie = 0;
-    data.txn.code = 0;
-    if (status) {
-        data.txn.flags = TF_STATUS_CODE;
-        data.txn.data_size = sizeof(int);
-        data.txn.offsets_size = 0;
-        data.txn.data.ptr.buffer = (uintptr_t)&status;
-        data.txn.data.ptr.offsets = 0;
-    } else {
-        data.txn.flags = 0;
-        data.txn.data_size = reply->data - reply->data0;
-        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
-        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
-        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
-    }
-    binder_write(bs, &data, sizeof(data));
-}
-
-int binder_parse(struct binder_state *bs, struct binder_io *bio,
-                 uintptr_t ptr, size_t size, binder_handler func)
-{
-    int r = 1;
-    uintptr_t end = ptr + (uintptr_t) size;
-
-    while (ptr < end) {
-        uint32_t cmd = *(uint32_t *) ptr;
-        ptr += sizeof(uint32_t);
-#if TRACE
-        fprintf(stderr,"%s:\n", cmd_name(cmd));
-#endif
-        switch(cmd) {
-        case BR_NOOP:
-            break;
-        case BR_TRANSACTION_COMPLETE:
-            break;
-        case BR_INCREFS:
-        case BR_ACQUIRE:
-        case BR_RELEASE:
-        case BR_DECREFS:
-#if TRACE
-            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
-#endif
-            ptr += sizeof(struct binder_ptr_cookie);
-            break;
-        case BR_TRANSACTION_SEC_CTX:
-        case BR_TRANSACTION: {
-            struct binder_transaction_data_secctx txn;
-            if (cmd == BR_TRANSACTION_SEC_CTX) {
-                if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
-                    ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
-                    return -1;
-                }
-                memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
-                ptr += sizeof(struct binder_transaction_data_secctx);
-            } else /* BR_TRANSACTION */ {
-                if ((end - ptr) < sizeof(struct binder_transaction_data)) {
-                    ALOGE("parse: txn too small (binder_transaction_data)!\n");
-                    return -1;
-                }
-                memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
-                ptr += sizeof(struct binder_transaction_data);
-
-                txn.secctx = 0;
-            }
-
-            binder_dump_txn(&txn.transaction_data);
-            if (func) {
-                unsigned rdata[256/4];
-                struct binder_io msg;
-                struct binder_io reply;
-                int res;
-
-                bio_init(&reply, rdata, sizeof(rdata), 4);
-                bio_init_from_txn(&msg, &txn.transaction_data);
-                res = func(bs, &txn, &msg, &reply);
-                if (txn.transaction_data.flags & TF_ONE_WAY) {
-                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
-                } else {
-                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
-                }
-            }
-            break;
-        }
-        case BR_REPLY: {
-            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
-            if ((end - ptr) < sizeof(*txn)) {
-                ALOGE("parse: reply too small!\n");
-                return -1;
-            }
-            binder_dump_txn(txn);
-            if (bio) {
-                bio_init_from_txn(bio, txn);
-                bio = 0;
-            } else {
-                /* todo FREE BUFFER */
-            }
-            ptr += sizeof(*txn);
-            r = 0;
-            break;
-        }
-        case BR_DEAD_BINDER: {
-            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
-            ptr += sizeof(binder_uintptr_t);
-            death->func(bs, death->ptr);
-            break;
-        }
-        case BR_FAILED_REPLY:
-            r = -1;
-            break;
-        case BR_DEAD_REPLY:
-            r = -1;
-            break;
-        default:
-            ALOGE("parse: OOPS %d\n", cmd);
-            return -1;
-        }
-    }
-
-    return r;
-}
-
-void binder_acquire(struct binder_state *bs, uint32_t target)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_ACQUIRE;
-    cmd[1] = target;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_release(struct binder_state *bs, uint32_t target)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_RELEASE;
-    cmd[1] = target;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
-{
-    struct {
-        uint32_t cmd;
-        struct binder_handle_cookie payload;
-    } __attribute__((packed)) data;
-
-    data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
-    data.payload.handle = target;
-    data.payload.cookie = (uintptr_t) death;
-    binder_write(bs, &data, sizeof(data));
-}
-
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                uint32_t target, uint32_t code)
-{
-    int res;
-    struct binder_write_read bwr;
-    struct {
-        uint32_t cmd;
-        struct binder_transaction_data txn;
-    } __attribute__((packed)) writebuf;
-    unsigned readbuf[32];
-
-    if (msg->flags & BIO_F_OVERFLOW) {
-        fprintf(stderr,"binder: txn buffer overflow\n");
-        goto fail;
-    }
-
-    writebuf.cmd = BC_TRANSACTION;
-    writebuf.txn.target.handle = target;
-    writebuf.txn.code = code;
-    writebuf.txn.flags = 0;
-    writebuf.txn.data_size = msg->data - msg->data0;
-    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
-    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
-    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
-
-    bwr.write_size = sizeof(writebuf);
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (uintptr_t) &writebuf;
-
-    hexdump(msg->data0, msg->data - msg->data0);
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (uintptr_t) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
-            goto fail;
-        }
-
-        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
-        if (res == 0) return 0;
-        if (res < 0) goto fail;
-    }
-
-fail:
-    memset(reply, 0, sizeof(*reply));
-    reply->flags |= BIO_F_IOERROR;
-    return -1;
-}
-
-void binder_loop(struct binder_state *bs, binder_handler func)
-{
-    int res;
-    struct binder_write_read bwr;
-    uint32_t readbuf[32];
-
-    bwr.write_size = 0;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = 0;
-
-    readbuf[0] = BC_ENTER_LOOPER;
-    binder_write(bs, readbuf, sizeof(uint32_t));
-
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (uintptr_t) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
-            break;
-        }
-
-        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
-        if (res == 0) {
-            ALOGE("binder_loop: unexpected reply?!\n");
-            break;
-        }
-        if (res < 0) {
-            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
-            break;
-        }
-    }
-}
-
-void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
-{
-    bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
-    bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
-    bio->data_avail = txn->data_size;
-    bio->offs_avail = txn->offsets_size / sizeof(size_t);
-    bio->flags = BIO_F_SHARED;
-}
-
-void bio_init(struct binder_io *bio, void *data,
-              size_t maxdata, size_t maxoffs)
-{
-    size_t n = maxoffs * sizeof(size_t);
-
-    if (n > maxdata) {
-        bio->flags = BIO_F_OVERFLOW;
-        bio->data_avail = 0;
-        bio->offs_avail = 0;
-        return;
-    }
-
-    bio->data = bio->data0 = (char *) data + n;
-    bio->offs = bio->offs0 = data;
-    bio->data_avail = maxdata - n;
-    bio->offs_avail = maxoffs;
-    bio->flags = 0;
-}
-
-static void *bio_alloc(struct binder_io *bio, size_t size)
-{
-    size = (size + 3) & (~3);
-    if (size > bio->data_avail) {
-        bio->flags |= BIO_F_OVERFLOW;
-        return NULL;
-    } else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-void binder_done(struct binder_state *bs,
-                 __unused struct binder_io *msg,
-                 struct binder_io *reply)
-{
-    struct {
-        uint32_t cmd;
-        uintptr_t buffer;
-    } __attribute__((packed)) data;
-
-    if (reply->flags & BIO_F_SHARED) {
-        data.cmd = BC_FREE_BUFFER;
-        data.buffer = (uintptr_t) reply->data0;
-        binder_write(bs, &data, sizeof(data));
-        reply->flags = 0;
-    }
-}
-
-static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
-{
-    struct flat_binder_object *obj;
-
-    obj = bio_alloc(bio, sizeof(*obj));
-
-    if (obj && bio->offs_avail) {
-        bio->offs_avail--;
-        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
-        return obj;
-    }
-
-    bio->flags |= BIO_F_OVERFLOW;
-    return NULL;
-}
-
-void bio_put_uint32(struct binder_io *bio, uint32_t n)
-{
-    uint32_t *ptr = bio_alloc(bio, sizeof(n));
-    if (ptr)
-        *ptr = n;
-}
-
-void bio_put_obj(struct binder_io *bio, void *ptr)
-{
-    struct flat_binder_object *obj;
-
-    obj = bio_alloc_obj(bio);
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->hdr.type = BINDER_TYPE_BINDER;
-    obj->binder = (uintptr_t)ptr;
-    obj->cookie = 0;
-}
-
-void bio_put_ref(struct binder_io *bio, uint32_t handle)
-{
-    struct flat_binder_object *obj;
-
-    if (handle)
-        obj = bio_alloc_obj(bio);
-    else
-        obj = bio_alloc(bio, sizeof(*obj));
-
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->hdr.type = BINDER_TYPE_HANDLE;
-    obj->handle = handle;
-    obj->cookie = 0;
-}
-
-void bio_put_string16(struct binder_io *bio, const uint16_t *str)
-{
-    size_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = 0;
-    while (str[len]) len++;
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    bio_put_uint32(bio, (uint32_t) len);
-    len = (len + 1) * sizeof(uint16_t);
-    ptr = bio_alloc(bio, len);
-    if (ptr)
-        memcpy(ptr, str, len);
-}
-
-void bio_put_string16_x(struct binder_io *bio, const char *_str)
-{
-    unsigned char *str = (unsigned char*) _str;
-    size_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = strlen(_str);
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    bio_put_uint32(bio, len);
-    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
-    if (!ptr)
-        return;
-
-    while (*str)
-        *ptr++ = *str++;
-    *ptr++ = 0;
-}
-
-static void *bio_get(struct binder_io *bio, size_t size)
-{
-    size = (size + 3) & (~3);
-
-    if (bio->data_avail < size){
-        bio->data_avail = 0;
-        bio->flags |= BIO_F_OVERFLOW;
-        return NULL;
-    }  else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-uint32_t bio_get_uint32(struct binder_io *bio)
-{
-    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
-    return ptr ? *ptr : 0;
-}
-
-uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
-{
-    size_t len;
-
-    /* Note: The payload will carry 32bit size instead of size_t */
-    len = (size_t) bio_get_uint32(bio);
-    if (sz)
-        *sz = len;
-    return bio_get(bio, (len + 1) * sizeof(uint16_t));
-}
-
-static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
-{
-    size_t n;
-    size_t off = bio->data - bio->data0;
-
-    /* TODO: be smarter about this? */
-    for (n = 0; n < bio->offs_avail; n++) {
-        if (bio->offs[n] == off)
-            return bio_get(bio, sizeof(struct flat_binder_object));
-    }
-
-    bio->data_avail = 0;
-    bio->flags |= BIO_F_OVERFLOW;
-    return NULL;
-}
-
-uint32_t bio_get_ref(struct binder_io *bio)
-{
-    struct flat_binder_object *obj;
-
-    obj = _bio_get_obj(bio);
-    if (!obj)
-        return 0;
-
-    if (obj->hdr.type == BINDER_TYPE_HANDLE)
-        return obj->handle;
-
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
deleted file mode 100644
index a9ccc74..0000000
--- a/cmds/servicemanager/binder.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#ifndef _BINDER_H_
-#define _BINDER_H_
-
-#include <linux/android/binder.h>
-#include <sys/ioctl.h>
-
-struct binder_state;
-
-struct binder_io
-{
-    char *data;            /* pointer to read/write from */
-    binder_size_t *offs;   /* array of offsets */
-    size_t data_avail;     /* bytes available in data buffer */
-    size_t offs_avail;     /* entries available in offsets array */
-
-    char *data0;           /* start of data buffer */
-    binder_size_t *offs0;  /* start of offsets buffer */
-    uint32_t flags;
-    uint32_t unused;
-};
-
-struct binder_death {
-    void (*func)(struct binder_state *bs, void *ptr);
-    void *ptr;
-};
-
-/* the one magic handle */
-#define BINDER_SERVICE_MANAGER  0U
-
-#define SVC_MGR_NAME "android.os.IServiceManager"
-
-enum {
-    /* Must match definitions in IBinder.h and IServiceManager.h */
-    PING_TRANSACTION  = B_PACK_CHARS('_','P','N','G'),
-    SVC_MGR_GET_SERVICE = 1,
-    SVC_MGR_CHECK_SERVICE,
-    SVC_MGR_ADD_SERVICE,
-    SVC_MGR_LIST_SERVICES,
-};
-
-typedef int (*binder_handler)(struct binder_state *bs,
-                              struct binder_transaction_data_secctx *txn,
-                              struct binder_io *msg,
-                              struct binder_io *reply);
-
-struct binder_state *binder_open(const char* driver, size_t mapsize);
-void binder_close(struct binder_state *bs);
-
-/* initiate a blocking binder call
- * - returns zero on success
- */
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                uint32_t target, uint32_t code);
-
-/* release any state associate with the binder_io
- * - call once any necessary data has been extracted from the
- *   binder_io after binder_call() returns
- * - can safely be called even if binder_call() fails
- */
-void binder_done(struct binder_state *bs,
-                 struct binder_io *msg, struct binder_io *reply);
-
-/* manipulate strong references */
-void binder_acquire(struct binder_state *bs, uint32_t target);
-void binder_release(struct binder_state *bs, uint32_t target);
-
-void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death);
-
-void binder_loop(struct binder_state *bs, binder_handler func);
-
-int binder_become_context_manager(struct binder_state *bs);
-
-/* allocate a binder_io, providing a stack-allocated working
- * buffer, size of the working buffer, and how many object
- * offset entries to reserve from the buffer
- */
-void bio_init(struct binder_io *bio, void *data,
-           size_t maxdata, size_t maxobjects);
-
-void bio_put_obj(struct binder_io *bio, void *ptr);
-void bio_put_ref(struct binder_io *bio, uint32_t handle);
-void bio_put_uint32(struct binder_io *bio, uint32_t n);
-void bio_put_string16(struct binder_io *bio, const uint16_t *str);
-void bio_put_string16_x(struct binder_io *bio, const char *_str);
-
-uint32_t bio_get_uint32(struct binder_io *bio);
-uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz);
-uint32_t bio_get_ref(struct binder_io *bio);
-
-#endif
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
new file mode 100644
index 0000000..c8ceb42
--- /dev/null
+++ b/cmds/servicemanager/main.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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 <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/Status.h>
+#include <utils/StrongPointer.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using ::android::sp;
+using ::android::ProcessState;
+using ::android::IPCThreadState;
+using ::android::ServiceManager;
+using ::android::Access;
+
+int main(int argc, char** argv) {
+    if (argc > 2) {
+        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
+    }
+
+    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
+
+    android::base::InitLogging(nullptr, &android::base::KernelLogger);
+
+    ProcessState::self()->initWithDriver(driver);
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    ProcessState::self()->setCallRestriction(
+        ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
+
+    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
+    IPCThreadState::self()->setTheContextObject(manager);
+    ProcessState::self()->becomeContextManager(nullptr, nullptr);
+
+    IPCThreadState::self()->joinThreadPool();
+
+    // should not be reached
+    return EXIT_FAILURE;
+}
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
deleted file mode 100644
index ec3fac5..0000000
--- a/cmds/servicemanager/service_manager.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <cutils/android_filesystem_config.h>
-#include <cutils/multiuser.h>
-
-#include <selinux/android.h>
-#include <selinux/avc.h>
-
-#include "binder.h"
-
-#ifdef VENDORSERVICEMANAGER
-#define LOG_TAG "VendorServiceManager"
-#else
-#define LOG_TAG "ServiceManager"
-#endif
-#include <log/log.h>
-
-struct audit_data {
-    pid_t pid;
-    uid_t uid;
-    const char *name;
-};
-
-const char *str8(const uint16_t *x, size_t x_len)
-{
-    static char buf[128];
-    size_t max = 127;
-    char *p = buf;
-
-    if (x_len < max) {
-        max = x_len;
-    }
-
-    if (x) {
-        while ((max > 0) && (*x != '\0')) {
-            *p++ = *x++;
-            max--;
-        }
-    }
-    *p++ = 0;
-    return buf;
-}
-
-int str16eq(const uint16_t *a, const char *b)
-{
-    while (*a && *b)
-        if (*a++ != *b++) return 0;
-    if (*a || *b)
-        return 0;
-    return 1;
-}
-
-static char *service_manager_context;
-static struct selabel_handle* sehandle;
-
-static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
-{
-    char *lookup_sid = NULL;
-    const char *class = "service_manager";
-    bool allowed;
-    struct audit_data ad;
-
-    if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
-        ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
-        return false;
-    }
-
-    ad.pid = spid;
-    ad.uid = uid;
-    ad.name = name;
-
-    if (sid == NULL) {
-        android_errorWriteLog(0x534e4554, "121035042");
-    }
-
-    int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
-    allowed = (result == 0);
-
-    freecon(lookup_sid);
-    return allowed;
-}
-
-static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
-{
-    return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
-}
-
-static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
-{
-    bool allowed;
-    char *tctx = NULL;
-
-    if (!sehandle) {
-        ALOGE("SELinux: Failed to find sehandle. Aborting service_manager.\n");
-        abort();
-    }
-
-    if (selabel_lookup(sehandle, &tctx, name, 0) != 0) {
-        ALOGE("SELinux: No match for %s in service_contexts.\n", name);
-        return false;
-    }
-
-    allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
-    freecon(tctx);
-    return allowed;
-}
-
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "add";
-
-    if (multiuser_get_app_id(uid) >= AID_APP) {
-        return 0; /* Don't allow apps to register services */
-    }
-
-    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
-}
-
-static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "list";
-    return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
-}
-
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
-{
-    const char *perm = "find";
-    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
-}
-
-struct svcinfo
-{
-    struct svcinfo *next;
-    uint32_t handle;
-    struct binder_death death;
-    int allow_isolated;
-    uint32_t dumpsys_priority;
-    size_t len;
-    uint16_t name[0];
-};
-
-struct svcinfo *svclist = NULL;
-
-struct svcinfo *find_svc(const uint16_t *s16, size_t len)
-{
-    struct svcinfo *si;
-
-    for (si = svclist; si; si = si->next) {
-        if ((len == si->len) &&
-            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
-            return si;
-        }
-    }
-    return NULL;
-}
-
-void svcinfo_death(struct binder_state *bs, void *ptr)
-{
-    struct svcinfo *si = (struct svcinfo* ) ptr;
-
-    ALOGI("service '%s' died\n", str8(si->name, si->len));
-    if (si->handle) {
-        binder_release(bs, si->handle);
-        si->handle = 0;
-    }
-}
-
-uint16_t svcmgr_id[] = {
-    'a','n','d','r','o','i','d','.','o','s','.',
-    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r'
-};
-
-
-uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
-{
-    struct svcinfo *si = find_svc(s, len);
-
-    if (!si || !si->handle) {
-        return 0;
-    }
-
-    if (!si->allow_isolated) {
-        // If this service doesn't allow access from isolated processes,
-        // then check the uid to see if it is isolated.
-        uid_t appid = uid % AID_USER;
-        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
-            return 0;
-        }
-    }
-
-    if (!svc_can_find(s, len, spid, sid, uid)) {
-        return 0;
-    }
-
-    return si->handle;
-}
-
-int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
-                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
-    struct svcinfo *si;
-
-    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
-    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
-
-    if (!handle || (len == 0) || (len > 127))
-        return -1;
-
-    if (!svc_can_register(s, len, spid, sid, uid)) {
-        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
-             str8(s, len), handle, uid);
-        return -1;
-    }
-
-    si = find_svc(s, len);
-    if (si) {
-        if (si->handle) {
-            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
-                 str8(s, len), handle, uid);
-            svcinfo_death(bs, si);
-        }
-        si->handle = handle;
-    } else {
-        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
-        if (!si) {
-            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
-                 str8(s, len), handle, uid);
-            return -1;
-        }
-        si->handle = handle;
-        si->len = len;
-        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
-        si->name[len] = '\0';
-        si->death.func = (void*) svcinfo_death;
-        si->death.ptr = si;
-        si->allow_isolated = allow_isolated;
-        si->dumpsys_priority = dumpsys_priority;
-        si->next = svclist;
-        svclist = si;
-    }
-
-    binder_acquire(bs, handle);
-    binder_link_to_death(bs, handle, &si->death);
-    return 0;
-}
-
-int svcmgr_handler(struct binder_state *bs,
-                   struct binder_transaction_data_secctx *txn_secctx,
-                   struct binder_io *msg,
-                   struct binder_io *reply)
-{
-    struct svcinfo *si;
-    uint16_t *s;
-    size_t len;
-    uint32_t handle;
-    uint32_t strict_policy;
-    int allow_isolated;
-    uint32_t dumpsys_priority;
-
-    struct binder_transaction_data *txn = &txn_secctx->transaction_data;
-
-    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
-    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
-
-    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
-        return -1;
-
-    if (txn->code == PING_TRANSACTION)
-        return 0;
-
-    // Equivalent to Parcel::enforceInterface(), reading the RPC
-    // header with the strict mode policy mask and the interface name.
-    // Note that we ignore the strict_policy and don't propagate it
-    // further (since we do no outbound RPCs anyway).
-    strict_policy = bio_get_uint32(msg);
-    bio_get_uint32(msg);  // Ignore worksource header.
-    s = bio_get_string16(msg, &len);
-    if (s == NULL) {
-        return -1;
-    }
-
-    if ((len != (sizeof(svcmgr_id) / 2)) ||
-        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
-        fprintf(stderr,"invalid id %s\n", str8(s, len));
-        return -1;
-    }
-
-    if (sehandle && selinux_status_updated() > 0) {
-#ifdef VENDORSERVICEMANAGER
-        struct selabel_handle *tmp_sehandle = selinux_android_vendor_service_context_handle();
-#else
-        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
-#endif
-        if (tmp_sehandle) {
-            selabel_close(sehandle);
-            sehandle = tmp_sehandle;
-        }
-    }
-
-    switch(txn->code) {
-    case SVC_MGR_GET_SERVICE:
-    case SVC_MGR_CHECK_SERVICE:
-        s = bio_get_string16(msg, &len);
-        if (s == NULL) {
-            return -1;
-        }
-        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
-                                 (const char*) txn_secctx->secctx);
-        if (!handle)
-            break;
-        bio_put_ref(reply, handle);
-        return 0;
-
-    case SVC_MGR_ADD_SERVICE:
-        s = bio_get_string16(msg, &len);
-        if (s == NULL) {
-            return -1;
-        }
-        handle = bio_get_ref(msg);
-        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
-        dumpsys_priority = bio_get_uint32(msg);
-        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
-                           txn->sender_pid, (const char*) txn_secctx->secctx))
-            return -1;
-        break;
-
-    case SVC_MGR_LIST_SERVICES: {
-        uint32_t n = bio_get_uint32(msg);
-        uint32_t req_dumpsys_priority = bio_get_uint32(msg);
-
-        if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
-            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
-                    txn->sender_euid);
-            return -1;
-        }
-        si = svclist;
-        // walk through the list of services n times skipping services that
-        // do not support the requested priority
-        while (si) {
-            if (si->dumpsys_priority & req_dumpsys_priority) {
-                if (n == 0) break;
-                n--;
-            }
-            si = si->next;
-        }
-        if (si) {
-            bio_put_string16(reply, si->name);
-            return 0;
-        }
-        return -1;
-    }
-    default:
-        ALOGE("unknown code %d\n", txn->code);
-        return -1;
-    }
-
-    bio_put_uint32(reply, 0);
-    return 0;
-}
-
-
-static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
-{
-    struct audit_data *ad = (struct audit_data *)data;
-
-    if (!ad || !ad->name) {
-        ALOGE("No service manager audit data");
-        return 0;
-    }
-
-    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
-    return 0;
-}
-
-int main(int argc, char** argv)
-{
-    struct binder_state *bs;
-    union selinux_callback cb;
-    char *driver;
-
-    if (argc > 1) {
-        driver = argv[1];
-    } else {
-        driver = "/dev/binder";
-    }
-
-    bs = binder_open(driver, 128*1024);
-    if (!bs) {
-#ifdef VENDORSERVICEMANAGER
-        ALOGW("failed to open binder driver %s\n", driver);
-        while (true) {
-            sleep(UINT_MAX);
-        }
-#else
-        ALOGE("failed to open binder driver %s\n", driver);
-#endif
-        return -1;
-    }
-
-    if (binder_become_context_manager(bs)) {
-        ALOGE("cannot become context manager (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    cb.func_audit = audit_callback;
-    selinux_set_callback(SELINUX_CB_AUDIT, cb);
-#ifdef VENDORSERVICEMANAGER
-    cb.func_log = selinux_vendor_log_callback;
-#else
-    cb.func_log = selinux_log_callback;
-#endif
-    selinux_set_callback(SELINUX_CB_LOG, cb);
-
-#ifdef VENDORSERVICEMANAGER
-    sehandle = selinux_android_vendor_service_context_handle();
-#else
-    sehandle = selinux_android_service_context_handle();
-#endif
-    selinux_status_open(true);
-
-    if (sehandle == NULL) {
-        ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
-        abort();
-    }
-
-    if (getcon(&service_manager_context) != 0) {
-        ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
-        abort();
-    }
-
-
-    binder_loop(bs, svcmgr_handler);
-
-    return 0;
-}
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
new file mode 100644
index 0000000..812d5ca
--- /dev/null
+++ b/cmds/servicemanager/test_sm.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 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 <binder/ProcessState.h>
+#include <cutils/android_filesystem_config.h>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "Access.h"
+#include "ServiceManager.h"
+
+using android::sp;
+using android::Access;
+using android::IBinder;
+using android::ServiceManager;
+using android::os::IServiceManager;
+using testing::_;
+using testing::ElementsAre;
+using testing::NiceMock;
+using testing::Return;
+
+static sp<IBinder> getBinder() {
+    // It doesn't matter what remote binder it is, we just need one so that linkToDeath will work.
+    // The context manager (servicemanager) is easy to get and is in another process.
+    return android::ProcessState::self()->getContextObject(nullptr);
+}
+
+class MockAccess : public Access {
+public:
+    MOCK_METHOD1(getCallingContext, CallingContext(const std::string& name));
+    MOCK_METHOD1(canAdd, bool(const CallingContext&));
+    MOCK_METHOD1(canFind, bool(const CallingContext&));
+    MOCK_METHOD1(canList, bool(const CallingContext&));
+};
+
+static sp<ServiceManager> getPermissiveServiceManager() {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    ON_CALL(*access, getCallingContext(_)).WillByDefault(Return(Access::CallingContext{}));
+    ON_CALL(*access, canAdd(_)).WillByDefault(Return(true));
+    ON_CALL(*access, canFind(_)).WillByDefault(Return(true));
+    ON_CALL(*access, canList(_)).WillByDefault(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    return sm;
+}
+
+TEST(AddService, HappyHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, EmptyNameDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService("", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, JustShortEnoughServiceNameHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService(std::string(127, 'a'), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, TooLongNameDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService(std::string(128, 'a'), getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, AddNullServiceDisallowed) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_FALSE(sm->addService("foo", nullptr, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, AddDisallowedFromApp) {
+    for (uid_t uid : { AID_APP_START, AID_APP_START + 1, AID_APP_END }) {
+        std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+        EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{
+            .debugPid = 1337,
+            .uid = uid,
+        }));
+        EXPECT_CALL(*access, canAdd(_)).Times(0);
+        sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+        EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+            IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    }
+
+}
+
+TEST(AddService, HappyOverExistingService) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(AddService, NoPermissions) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+}
+
+TEST(GetService, HappyHappy) {
+    auto sm = getPermissiveServiceManager();
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(getBinder(), out);
+}
+
+TEST(GetService, NonExistant) {
+    auto sm = getPermissiveServiceManager();
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(GetService, NoPermissionsForGettingService) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext(_)).WillRepeatedly(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true));
+    EXPECT_CALL(*access, canFind(_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    // returns nullptr but has OK status for legacy compatibility
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(GetService, AllowedFromIsolated) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext(_))
+        // something adds it
+        .WillOnce(Return(Access::CallingContext{}))
+        // next call is from isolated app
+        .WillOnce(Return(Access::CallingContext{
+            .uid = AID_ISOLATED_START,
+        }));
+    EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true));
+    EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), true /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(getBinder(), out.get());
+}
+
+TEST(GetService, NotAllowedFromIsolated) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext(_))
+        // something adds it
+        .WillOnce(Return(Access::CallingContext{}))
+        // next call is from isolated app
+        .WillOnce(Return(Access::CallingContext{
+            .uid = AID_ISOLATED_START,
+        }));
+    EXPECT_CALL(*access, canAdd(_)).WillOnce(Return(true));
+
+    // TODO(b/136023468): when security check is first, this should be called first
+    // EXPECT_CALL(*access, canFind(_)).WillOnce(Return(true));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> out;
+    // returns nullptr but has OK status for legacy compatibility
+    EXPECT_TRUE(sm->getService("foo", &out).isOk());
+    EXPECT_EQ(nullptr, out.get());
+}
+
+TEST(ListServices, NoPermissions) {
+    std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
+
+    EXPECT_CALL(*access, getCallingContext(_)).WillOnce(Return(Access::CallingContext{}));
+    EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
+
+    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+
+    std::vector<std::string> out;
+    EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
+    EXPECT_TRUE(out.empty());
+}
+
+TEST(ListServices, AllServices) {
+    auto sm = getPermissiveServiceManager();
+
+    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
+    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
+    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
+
+    std::vector<std::string> out;
+    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
+
+    // all there and in the right order
+    EXPECT_THAT(out, ElementsAre("sa", "sb", "sc", "sd"));
+}
+
+TEST(ListServices, CriticalServices) {
+    auto sm = getPermissiveServiceManager();
+
+    EXPECT_TRUE(sm->addService("sd", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+    EXPECT_TRUE(sm->addService("sc", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_NORMAL).isOk());
+    EXPECT_TRUE(sm->addService("sb", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_HIGH).isOk());
+    EXPECT_TRUE(sm->addService("sa", getBinder(), false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL).isOk());
+
+    std::vector<std::string> out;
+    EXPECT_TRUE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, &out).isOk());
+
+    // all there and in the right order
+    EXPECT_THAT(out, ElementsAre("sa"));
+}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 905b25f..760d55b 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -94,7 +94,6 @@
                 "PermissionController.cpp",
                 "ProcessInfoService.cpp",
                 "IpPrefix.cpp",
-                ":libbinder_aidl",
             ],
         },
     },
@@ -142,8 +141,7 @@
     name: "libbinder_aidl",
     srcs: [
         "aidl/android/content/pm/IPackageManagerNative.aidl",
+        "aidl/android/os/IServiceManager.aidl",
     ],
     path: "aidl",
 }
-
-subdirs = ["tests"]
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index a2d10ab..3424c28 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1062,7 +1062,7 @@
 
 sp<BBinder> the_context_object;
 
-void setTheContextObject(sp<BBinder> obj)
+void IPCThreadState::setTheContextObject(sp<BBinder> obj)
 {
     the_context_object = obj;
 }
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 0203d41..07550fb 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -18,6 +18,7 @@
 
 #include <binder/IServiceManager.h>
 
+#include <android/os/IServiceManager.h>
 #include <utils/Log.h>
 #include <binder/IPCThreadState.h>
 #ifndef __ANDROID_VNDK__
@@ -34,6 +35,9 @@
 
 namespace android {
 
+using AidlServiceManager = android::os::IServiceManager;
+using android::binder::Status;
+
 sp<IServiceManager> defaultServiceManager()
 {
     static Mutex gDefaultServiceManagerLock;
@@ -142,11 +146,12 @@
 {
 public:
     explicit BpServiceManager(const sp<IBinder>& impl)
-        : BpInterface<IServiceManager>(impl)
+        : BpInterface<IServiceManager>(impl),
+          mTheRealServiceManager(interface_cast<AidlServiceManager>(impl))
     {
     }
 
-    virtual sp<IBinder> getService(const String16& name) const
+    sp<IBinder> getService(const String16& name) const override
     {
         static bool gSystemBootCompleted = false;
 
@@ -179,43 +184,36 @@
         return nullptr;
     }
 
-    virtual sp<IBinder> checkService( const String16& name) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
-        data.writeString16(name);
-        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
-        return reply.readStrongBinder();
+    sp<IBinder> checkService(const String16& name) const override {
+        sp<IBinder> ret;
+        if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
+            return nullptr;
+        }
+        return ret;
     }
 
-    virtual status_t addService(const String16& name, const sp<IBinder>& service,
-                                bool allowIsolated, int dumpsysPriority) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
-        data.writeString16(name);
-        data.writeStrongBinder(service);
-        data.writeInt32(allowIsolated ? 1 : 0);
-        data.writeInt32(dumpsysPriority);
-        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
-        return err == NO_ERROR ? reply.readExceptionCode() : err;
+    status_t addService(const String16& name, const sp<IBinder>& service,
+                        bool allowIsolated, int dumpsysPriority) override {
+        Status status = mTheRealServiceManager->addService(String8(name).c_str(), service, allowIsolated, dumpsysPriority);
+        return status.exceptionCode();
     }
 
     virtual Vector<String16> listServices(int dumpsysPriority) {
-        Vector<String16> res;
-        int n = 0;
+        std::vector<std::string> ret;
+        if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
+            return {};
+        }
 
-        for (;;) {
-            Parcel data, reply;
-            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
-            data.writeInt32(n++);
-            data.writeInt32(dumpsysPriority);
-            status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
-            if (err != NO_ERROR)
-                break;
-            res.add(reply.readString16());
+        Vector<String16> res;
+        res.setCapacity(ret.size());
+        for (const std::string& name : ret) {
+            res.push(String16(name.c_str()));
         }
         return res;
     }
+
+private:
+    sp<AidlServiceManager> mTheRealServiceManager;
 };
 
 IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
new file mode 100644
index 0000000..50a72aa
--- /dev/null
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+package android.os;
+
+/**
+ * Basic interface for finding and publishing system services.
+ *
+ * You likely want to use android.os.ServiceManager in Java or
+ * android::IServiceManager in C++ in order to use this interface.
+ *
+ * @hide
+ */
+interface IServiceManager {
+    /*
+     * Must update values in IServiceManager.h
+     */
+    /* Allows services to dump sections according to priorities. */
+    const int DUMP_FLAG_PRIORITY_CRITICAL = 1; // 1 << 0
+    const int DUMP_FLAG_PRIORITY_HIGH = 2; // 1 << 1
+    const int DUMP_FLAG_PRIORITY_NORMAL = 4; // 1 << 2
+    /**
+     * Services are by default registered with a DEFAULT dump priority. DEFAULT priority has the
+     * same priority as NORMAL priority but the services are not called with dump priority
+     * arguments.
+     */
+    const int DUMP_FLAG_PRIORITY_DEFAULT = 8; // 1 << 3
+
+    const int DUMP_FLAG_PRIORITY_ALL = 15;
+             // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
+             // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
+
+    /* Allows services to dump sections in protobuf format. */
+    const int DUMP_FLAG_PROTO = 16; // 1 << 4
+
+    /**
+     * Retrieve an existing service called @a name from the
+     * service manager.
+     *
+     * This is the same as checkService (returns immediately) but
+     * exists for legacy purposes.
+     *
+     * Returns null if the service does not exist.
+     */
+    @UnsupportedAppUsage
+    IBinder getService(@utf8InCpp String name);
+
+    /**
+     * Retrieve an existing service called @a name from the service
+     * manager. Non-blocking. Returns null if the service does not
+     * exist.
+     */
+    @UnsupportedAppUsage
+    IBinder checkService(@utf8InCpp String name);
+
+    /**
+     * Place a new @a service called @a name into the service
+     * manager.
+     */
+    void addService(@utf8InCpp String name, IBinder service,
+        boolean allowIsolated, int dumpPriority);
+
+    /**
+     * Return a list of all currently running services.
+     */
+    @utf8InCpp String[] listServices(int dumpPriority);
+}
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 614b0b3..b810f7e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -110,6 +110,8 @@
             // the maximum number of binder threads threads allowed for this process.
             void                blockUntilThreadAvailable();
 
+            // Service manager registration
+            void                setTheContextObject(sp<BBinder> obj);
 
             // Is this thread currently serving a binder call. This method
             // returns true if while traversing backwards from the function call
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 46a8e9e..6e7ec33 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -456,10 +456,6 @@
                                            mFeatureFlags & USE_COLOR_MANAGEMENT);
 }
 
-bool GLESRenderEngine::isCurrent() const {
-    return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
-}
-
 base::unique_fd GLESRenderEngine::flush() {
     ATRACE_CALL();
     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
@@ -795,7 +791,6 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
 
     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
     ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
              glStatus);
 
@@ -1013,33 +1008,6 @@
     return NO_ERROR;
 }
 
-void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                                ui::Transform::orientation_flags rotation) {
-    setViewportAndProjection(Rect(vpw, vph), sourceCrop);
-
-    if (rotation == ui::Transform::ROT_0) {
-        return;
-    }
-
-    // Apply custom rotation to the projection.
-    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
-    mat4 m = mState.projectionMatrix;
-    switch (rotation) {
-        case ui::Transform::ROT_90:
-            m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_180:
-            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
-            break;
-        case ui::Transform::ROT_270:
-            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
-            break;
-        default:
-            break;
-    }
-    mState.projectionMatrix = m;
-}
-
 void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
     ATRACE_CALL();
     mVpWidth = viewport.getWidth();
@@ -1103,14 +1071,6 @@
     mState.textureEnabled = true;
 }
 
-void GLESRenderEngine::setupLayerBlackedOut() {
-    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
-    Texture texture(Texture::TEXTURE_2D, mProtectedTexName);
-    texture.setDimensions(1, 1); // FIXME: we should get that from somewhere
-    mState.texture = texture;
-    mState.textureEnabled = true;
-}
-
 void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
     mState.colorMatrix = colorTransform;
 }
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index de793c2..70b704a 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -50,7 +50,6 @@
 public:
     static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags,
                                                     uint32_t imageCacheSize);
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
     GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
                      EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
@@ -58,17 +57,7 @@
                      uint32_t imageCacheSize);
     ~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
 
-    std::unique_ptr<Framebuffer> createFramebuffer() override;
-    std::unique_ptr<Image> createImage() override;
-
     void primeCache() const override;
-    bool isCurrent() const override;
-    base::unique_fd flush() override;
-    bool finish() override;
-    bool waitFence(base::unique_fd fenceFd) override;
-    void clearWithColor(float red, float green, float blue, float alpha) override;
-    void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                             float alpha) override;
     void genTextures(size_t count, uint32_t* names) override;
     void deleteTextures(size_t count, uint32_t const* names) override;
     void bindExternalTextureImage(uint32_t texName, const Image& image) override;
@@ -78,7 +67,6 @@
     void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex);
     status_t bindFrameBuffer(Framebuffer* framebuffer) override;
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
-    void checkErrors() const override;
 
     bool isProtected() const override { return mInProtectedContext; }
     bool supportsProtectedContent() const override;
@@ -88,9 +76,7 @@
                         base::unique_fd&& bufferFence, base::unique_fd* drawFence)
             EXCLUDES(mRenderingMutex) override;
 
-    // internal to RenderEngine
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
-    EGLConfig getEGLConfig() const { return mEGLConfig; }
     // Creates an output image for rendering to
     EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
                                                bool useFramebufferCache);
@@ -104,27 +90,6 @@
 protected:
     Framebuffer* getFramebufferForDrawing() override;
     void dump(std::string& result) override;
-    void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                  ui::Transform::orientation_flags rotation) override;
-    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                            const half4& color, float cornerRadius) override;
-    void setupLayerTexturing(const Texture& texture) override;
-    void setupLayerBlackedOut() override;
-    void setupFillWithColor(float r, float g, float b, float a) override;
-    void setColorTransform(const mat4& colorTransform) override;
-    void disableTexturing() override;
-    void disableBlending() override;
-    void setupCornerRadiusCropSize(float width, float height) override;
-
-    // HDR and color management related functions and state
-    void setSourceY410BT2020(bool enable) override;
-    void setSourceDataSpace(ui::Dataspace source) override;
-    void setOutputDataSpace(ui::Dataspace dataspace) override;
-    void setDisplayMaxLuminance(const float maxLuminance) override;
-
-    // drawing
-    void drawMesh(const Mesh& mesh) override;
-
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
@@ -136,12 +101,16 @@
         GLES_VERSION_3_0 = 0x30000,
     };
 
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
     static GlesVersion parseGlesVersion(const char* str);
     static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                        EGLContext shareContext, bool useContextPriority,
                                        Protection protection);
     static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                    int hwcFormat, Protection protection);
+    std::unique_ptr<Framebuffer> createFramebuffer();
+    std::unique_ptr<Image> createImage();
+    void checkErrors() const;
     void setScissor(const Rect& region);
     void disableScissor();
     bool waitSync(EGLSyncKHR sync, EGLint flags);
@@ -165,6 +134,28 @@
     // blending is an expensive operation, we want to turn off blending when it's not necessary.
     void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer,
                               const Mesh& mesh);
+    base::unique_fd flush();
+    bool finish();
+    bool waitFence(base::unique_fd fenceFd);
+    void clearWithColor(float red, float green, float blue, float alpha);
+    void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha);
+    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                            const half4& color, float cornerRadius);
+    void setupLayerTexturing(const Texture& texture);
+    void setupFillWithColor(float r, float g, float b, float a);
+    void setColorTransform(const mat4& colorTransform);
+    void disableTexturing();
+    void disableBlending();
+    void setupCornerRadiusCropSize(float width, float height);
+
+    // HDR and color management related functions and state
+    void setSourceY410BT2020(bool enable);
+    void setSourceDataSpace(ui::Dataspace source);
+    void setOutputDataSpace(ui::Dataspace dataspace);
+    void setDisplayMaxLuminance(const float maxLuminance);
+
+    // drawing
+    void drawMesh(const Mesh& mesh);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index e707004..8a798ee 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -77,10 +77,6 @@
     // This interface, while still in use until a suitable replacement is built,
     // should be considered deprecated, minus some methods which still may be
     // used to support legacy behavior.
-
-    virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
-    virtual std::unique_ptr<Image> createImage() = 0;
-
     virtual void primeCache() const = 0;
 
     // dump the extension strings. always call the base class.
@@ -88,24 +84,6 @@
 
     virtual bool useNativeFenceSync() const = 0;
     virtual bool useWaitSync() const = 0;
-
-    virtual bool isCurrent() const = 0;
-
-    // helpers
-    // flush submits RenderEngine command stream for execution and returns a
-    // native fence fd that is signaled when the execution has completed.  It
-    // returns -1 on errors.
-    virtual base::unique_fd flush() = 0;
-    // finish waits until RenderEngine command stream has been executed.  It
-    // returns false on errors.
-    virtual bool finish() = 0;
-    // waitFence inserts a wait on an external fence fd to RenderEngine
-    // command stream.  It returns false on errors.
-    virtual bool waitFence(base::unique_fd fenceFd) = 0;
-
-    virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
-    virtual void fillRegionWithColor(const Region& region, float red, float green, float blue,
-                                     float alpha) = 0;
     virtual void genTextures(size_t count, uint32_t* names) = 0;
     virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
     virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
@@ -126,40 +104,6 @@
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
     virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
 
-    // set-up
-    virtual void checkErrors() const = 0;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                          ui::Transform::orientation_flags rotation) = 0;
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                                    const half4& color, float cornerRadius) = 0;
-    virtual void setupLayerTexturing(const Texture& texture) = 0;
-    virtual void setupLayerBlackedOut() = 0;
-    virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
-    // Sets up the crop size for corner radius clipping.
-    //
-    // Having corner radius will force GPU composition on the layer and its children, drawing it
-    // with a special shader. The shader will receive the radius and the crop rectangle as input,
-    // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
-    // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
-    // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
-    // in local layer coordinate space, so we have to take the layer transform into account when
-    // walking up the tree.
-    virtual void setupCornerRadiusCropSize(float width, float height) = 0;
-
-    // Set a color transform matrix that is applied in linear space right before OETF.
-    virtual void setColorTransform(const mat4& /* colorTransform */) = 0;
-    virtual void disableTexturing() = 0;
-    virtual void disableBlending() = 0;
-
-    // HDR and color management support
-    virtual void setSourceY410BT2020(bool enable) = 0;
-    virtual void setSourceDataSpace(ui::Dataspace source) = 0;
-    virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0;
-    virtual void setDisplayMaxLuminance(const float maxLuminance) = 0;
-
-    // drawing
-    virtual void drawMesh(const Mesh& mesh) = 0;
-
     // queries
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index e33bcfd..f099cd2 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -34,20 +34,12 @@
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
-    MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(std::string&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
-    MOCK_METHOD0(flush, base::unique_fd());
-    MOCK_METHOD0(finish, bool());
-    MOCK_METHOD1(waitFence, bool(base::unique_fd*));
-    bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
-    MOCK_METHOD4(clearWithColor, void(float, float, float, float));
-    MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float));
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
     MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
@@ -55,22 +47,6 @@
     MOCK_METHOD3(bindExternalTextureBuffer,
                  status_t(uint32_t, const sp<GraphicBuffer>&, const sp<Fence>&));
     MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t));
-    MOCK_CONST_METHOD0(checkErrors, void());
-    MOCK_METHOD4(setViewportAndProjection,
-                 void(size_t, size_t, Rect, ui::Transform::orientation_flags));
-    MOCK_METHOD5(setupLayerBlending, void(bool, bool, bool, const half4&, float));
-    MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
-    MOCK_METHOD0(setupLayerBlackedOut, void());
-    MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
-    MOCK_METHOD2(setupCornerRadiusCropSize, void(float, float));
-    MOCK_METHOD1(setColorTransform, void(const mat4&));
-    MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
-    MOCK_METHOD0(disableTexturing, void());
-    MOCK_METHOD0(disableBlending, void());
-    MOCK_METHOD1(setSourceY410BT2020, void(bool));
-    MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
-    MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
     MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*));
     MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*));
     MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index 5840d51..96d5eb9 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -94,7 +94,7 @@
 
 SensorManager::SensorManager(const String16& opPackageName)
     : mSensorList(nullptr), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {
-    // okay we're not locked here, but it's not needed during construction
+    Mutex::Autolock _l(mLock);
     assertStateLocked();
 }
 
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index da91a97..1dfc1e9 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "BufferHubBuffer"
 #include <poll.h>
 
 #include <android-base/unique_fd.h>
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3fc6a2d..579e68e 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -626,7 +626,7 @@
                            bufferHubBuffer->desc().layers, bufferHubBuffer->desc().usage,
                            bufferHubBuffer->desc().stride);
     mBufferId = bufferHubBuffer->id();
-    mBufferHubBuffer.reset(std::move(bufferHubBuffer.get()));
+    mBufferHubBuffer = std::move(bufferHubBuffer);
 
     return NO_ERROR;
 }
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 373fa4f..c5170d0 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -46,6 +46,24 @@
     cflags: ["-Wall", "-Werror"],
 }
 
+// This test has a main method, and requires a separate binary to be built.
+cc_test {
+    name: "GraphicBufferOverBinder_test",
+    srcs: ["GraphicBufferOverBinder_test.cpp"],
+    cflags: ["-Wall", "-Werror"],
+    header_libs: [
+        "libdvr_headers",
+    ],
+    shared_libs: [
+        "android.frameworks.bufferhub@1.0",
+        "libbinder",
+        "libgui",
+        "liblog",
+        "libui",
+        "libutils",
+    ],
+}
+
 cc_test {
     name: "BufferHub_test",
     header_libs: [
diff --git a/libs/ui/tests/GraphicBufferOverBinder_test.cpp b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
new file mode 100644
index 0000000..7c0a44a
--- /dev/null
+++ b/libs/ui/tests/GraphicBufferOverBinder_test.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 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 "GraphicBufferOverBinder_test"
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <ui/BufferHubBuffer.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Log.h>
+
+namespace android {
+
+constexpr uint32_t kTestWidth = 1024;
+constexpr uint32_t kTestHeight = 1;
+constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB;
+constexpr uint32_t kTestLayerCount = 1;
+constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+static const String16 kTestServiceName = String16("GraphicBufferOverBinderTestService");
+enum GraphicBufferOverBinderTestServiceCode {
+    GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER,
+};
+
+class GraphicBufferOverBinderTestService : public BBinder {
+public:
+    GraphicBufferOverBinderTestService() {
+        // GraphicBuffer
+        mGraphicBuffer = new GraphicBuffer(kTestWidth, kTestHeight, kTestFormat, kTestLayerCount,
+                                           kTestUsage);
+        ALOGI("mGraphicBuffer id %" PRIi32, mGraphicBuffer->getBufferId());
+
+        // BufferHub-backed GraphicBuffer
+        std::unique_ptr<BufferHubBuffer> bufferHubBuffer =
+                BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+                                        kTestUsage, /*userMetadataSize=*/0);
+        mBufferhubBackedGraphicBuffer = new GraphicBuffer(std::move(bufferHubBuffer));
+        if (!mBufferhubBackedGraphicBuffer->isBufferHubBuffer()) {
+            ALOGE("Failed to back GraphicBuffer with BufferHub.");
+        }
+        if (bufferHubBuffer != nullptr) {
+            ALOGE("Failed to move BufferHubBuffer to GraphicBuffer");
+        }
+        ALOGI("mBufferhubBackedGraphicBuffer id %" PRIi32,
+              mBufferhubBackedGraphicBuffer->getBufferId());
+    }
+
+    ~GraphicBufferOverBinderTestService() = default;
+
+    virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
+                                uint32_t /*flags*/ = 0) {
+        switch (code) {
+            case GRAPHIC_BUFFER: {
+                return reply->write(*mGraphicBuffer);
+            }
+            case GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER: {
+                return reply->write(*mBufferhubBackedGraphicBuffer);
+            }
+            default:
+                return UNKNOWN_TRANSACTION;
+        };
+    }
+
+protected:
+    sp<GraphicBuffer> mGraphicBuffer;
+    sp<GraphicBuffer> mBufferhubBackedGraphicBuffer;
+};
+
+static int runBinderServer() {
+    ProcessState::self()->startThreadPool();
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<GraphicBufferOverBinderTestService> service = new GraphicBufferOverBinderTestService;
+    sm->addService(kTestServiceName, service, false);
+
+    ALOGI("Binder server running...");
+
+    while (true) {
+        int stat, retval;
+        retval = wait(&stat);
+        if (retval == -1 && errno == ECHILD) {
+            break;
+        }
+    }
+
+    ALOGI("Binder server exiting...");
+    return 0;
+}
+
+class GraphicBufferOverBinderTest : public ::testing::TestWithParam<uint32_t> {
+protected:
+    virtual void SetUp() {
+        mService = defaultServiceManager()->getService(kTestServiceName);
+        if (mService == nullptr) {
+            ALOGE("Failed to connect to the test service.");
+            return;
+        }
+
+        ALOGI("Binder service is ready for client.");
+    }
+
+    status_t GetGraphicBuffer(sp<GraphicBuffer>* outBuf, uint32_t opCode) {
+        Parcel data;
+        Parcel reply;
+        status_t error = mService->transact(opCode, data, &reply);
+        if (error != NO_ERROR) {
+            ALOGE("Failed to get graphic buffer over binder, error=%d.", error);
+            return error;
+        }
+
+        *outBuf = new GraphicBuffer();
+        return reply.read(**outBuf);
+    }
+
+private:
+    sp<IBinder> mService;
+};
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER), OK);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_FALSE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+TEST_F(GraphicBufferOverBinderTest, SendGraphicBufferFromBufferHubBufferOverBinder) {
+    sp<GraphicBuffer> gb;
+    EXPECT_EQ(GetGraphicBuffer(&gb, GRAPHIC_BUFFER_FROM_BUFFER_HUB_BUFFER), NO_ERROR);
+    EXPECT_NE(gb, nullptr);
+    EXPECT_TRUE(gb->isBufferHubBuffer());
+    void* vaddr;
+    EXPECT_EQ(gb->lock(kTestUsage, &vaddr), OK);
+    EXPECT_EQ(gb->unlock(), OK);
+}
+
+} // namespace android
+
+int main(int argc, char** argv) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        android::ProcessState::self()->startThreadPool();
+        ::testing::InitGoogleTest(&argc, argv);
+        return RUN_ALL_TESTS();
+
+    } else {
+        ALOGI("Test process pid: %d.", pid);
+        return android::runBinderServer();
+    }
+}
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 6a7f279..7c061c5 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -276,7 +276,7 @@
     bool eventAdded = mEvents.push(std::move(event));
     if (!eventAdded) {
         // If the queue is full, suspect the HAL is slow in processing the events.
-        ALOGE("Dropped event with eventTime %" PRId64, event.args->eventTime);
+        ALOGE("Could not add the event to the queue. Resetting");
         reset();
     }
 }
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 6709fb4..096cd1a 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -419,30 +419,6 @@
     return mCurrentFenceTime;
 }
 
-status_t BufferLayerConsumer::doFenceWaitLocked() const {
-    if (mCurrentFence->isValid()) {
-        if (mRE.useWaitSync()) {
-            base::unique_fd fenceFd(mCurrentFence->dup());
-            if (fenceFd == -1) {
-                BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
-                return -errno;
-            }
-            if (!mRE.waitFence(std::move(fenceFd))) {
-                BLC_LOGE("doFenceWait: failed to wait on fence fd");
-                return UNKNOWN_ERROR;
-            }
-        } else {
-            status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked");
-            if (err != NO_ERROR) {
-                BLC_LOGE("doFenceWait: error waiting for fence: %d", err);
-                return err;
-            }
-        }
-    }
-
-    return NO_ERROR;
-}
-
 void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
     BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     std::lock_guard<std::mutex> lock(mImagesMutex);
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index e3f6100..144686c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -252,11 +252,6 @@
     // mCurrentTextureImage must not be nullptr.
     void computeCurrentTransformMatrixLocked();
 
-    // doFenceWaitLocked inserts a wait command into the RenderEngine command
-    // stream to ensure that it is safe for future RenderEngine commands to
-    // access the current texture buffer.
-    status_t doFenceWaitLocked() const;
-
     // getCurrentCropLocked returns the cropping rectangle of the current buffer.
     Rect getCurrentCropLocked() const;
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index e21128c..9bff73e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -83,10 +83,6 @@
     // Called after the HWC calls are made to present the display
     virtual void onPresentDisplayCompleted() = 0;
 
-    // Called to set the viewport and projection state for rendering into this
-    // surface
-    virtual void setViewportAndProjection() = 0;
-
     // Called after the surface has been rendering to signal the surface should
     // be made ready for displaying
     virtual void flip() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 0f57315..e4c9c80 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -56,7 +56,6 @@
     sp<GraphicBuffer> dequeueBuffer(base::unique_fd* bufferFence) override;
     void queueBuffer(base::unique_fd&& readyFence) override;
     void onPresentDisplayCompleted() override;
-    void setViewportAndProjection() override;
     void flip() override;
 
     // Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index ca2299a..146a2ea 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -41,7 +41,6 @@
     MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
     MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
-    MOCK_METHOD0(setViewportAndProjection, void());
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
     MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 3fcd9d1..8a91316 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -215,13 +215,6 @@
     mDisplaySurface->onFrameCommitted();
 }
 
-void RenderSurface::setViewportAndProjection() {
-    auto& renderEngine = mCompositionEngine.getRenderEngine();
-    Rect sourceCrop = Rect(mSize);
-    renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop,
-                                          ui::Transform::ROT_0);
-}
-
 void RenderSurface::flip() {
     mPageFlipCount++;
 }
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index f75a4dc..87419ea 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -364,20 +364,6 @@
 }
 
 /* ------------------------------------------------------------------------
- * RenderSurface::setViewportAndProjection()
- */
-
-TEST_F(RenderSurfaceTest, setViewportAndProjectionAppliesChang) {
-    mSurface.setSizeForTest(ui::Size(100, 200));
-
-    EXPECT_CALL(mRenderEngine,
-                setViewportAndProjection(100, 200, Rect(100, 200), ui::Transform::ROT_0))
-            .Times(1);
-
-    mSurface.setViewportAndProjection();
-}
-
-/* ------------------------------------------------------------------------
  * RenderSurface::flip()
  */
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b2df91d..414c8dd 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -619,32 +619,6 @@
 // local state
 // ----------------------------------------------------------------------------
 
-void Layer::computeGeometry(const RenderArea& renderArea,
-                            renderengine::Mesh& mesh,
-                            bool useIdentityTransform) const {
-    const ui::Transform renderAreaTransform(renderArea.getTransform());
-    FloatRect win = getBounds();
-
-    vec2 lt = vec2(win.left, win.top);
-    vec2 lb = vec2(win.left, win.bottom);
-    vec2 rb = vec2(win.right, win.bottom);
-    vec2 rt = vec2(win.right, win.top);
-
-    ui::Transform layerTransform = getTransform();
-    if (!useIdentityTransform) {
-        lt = layerTransform.transform(lt);
-        lb = layerTransform.transform(lb);
-        rb = layerTransform.transform(rb);
-        rt = layerTransform.transform(rt);
-    }
-
-    renderengine::Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    position[0] = renderAreaTransform.transform(lt);
-    position[1] = renderAreaTransform.transform(lb);
-    position[2] = renderAreaTransform.transform(rb);
-    position[3] = renderAreaTransform.transform(rt);
-}
-
 bool Layer::isSecure() const {
     const State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
@@ -1231,6 +1205,14 @@
     if (parent != nullptr && parent->isHiddenByPolicy()) {
         return true;
     }
+    if (usingRelativeZ(LayerVector::StateSet::Drawing)) {
+        auto zOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote();
+        if (zOrderRelativeOf != nullptr) {
+            if (zOrderRelativeOf->isHiddenByPolicy()) {
+                return true;
+            }
+        }
+    }
     return s.flags & layer_state_t::eLayerHidden;
 }
 
@@ -1612,7 +1594,7 @@
     return mDrawingState.z;
 }
 
-bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) {
+bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const State& state = useDrawing ? mDrawingState : mCurrentState;
     return state.zOrderRelativeOf != nullptr;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6db6beb..b693a47 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -357,8 +357,6 @@
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
-    void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
-                         bool useIdentityTransform) const;
     FloatRect getBounds(const Region& activeTransparentRegion) const;
     FloatRect getBounds() const;
 
@@ -826,7 +824,7 @@
 
 protected:
     // -----------------------------------------------------------------------
-    bool usingRelativeZ(LayerVector::StateSet stateSet);
+    bool usingRelativeZ(LayerVector::StateSet stateSet) const;
 
     bool mPremultipliedAlpha{true};
     String8 mName;
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 72bbf5d..07fdead 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -44,11 +44,14 @@
 enum class samplingStep {
     noWorkNeeded,
     idleTimerWaiting,
+    waitForQuietFrame,
     waitForZeroPhase,
     waitForSamplePhase,
     sample
 };
 
+constexpr auto timeForRegionSampling = 5000000ns;
+constexpr auto maxRegionSamplingSkips = 10;
 constexpr auto defaultRegionSamplingOffset = -3ms;
 constexpr auto defaultRegionSamplingPeriod = 100ms;
 constexpr auto defaultRegionSamplingTimerTimeout = 100ms;
@@ -215,9 +218,9 @@
 void RegionSamplingThread::checkForStaleLuma() {
     std::lock_guard lock(mThreadControlMutex);
 
-    if (mDiscardedFrames) {
+    if (mDiscardedFrames > 0) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForZeroPhase));
-        mDiscardedFrames = false;
+        mDiscardedFrames = 0;
         mPhaseCallback->startVsyncListener();
     }
 }
@@ -235,13 +238,25 @@
     auto now = std::chrono::nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     if (lastSampleTime + mTunables.mSamplingPeriod > now) {
         ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::idleTimerWaiting));
-        mDiscardedFrames = true;
+        if (mDiscardedFrames == 0) mDiscardedFrames++;
         return;
     }
+    if (mDiscardedFrames < maxRegionSamplingSkips) {
+        // If there is relatively little time left for surfaceflinger
+        // until the next vsync deadline, defer this sampling work
+        // to a later frame, when hopefully there will be more time.
+        DisplayStatInfo stats;
+        mScheduler.getDisplayStatInfo(&stats);
+        if (std::chrono::nanoseconds(stats.vsyncTime) - now < timeForRegionSampling) {
+            ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::waitForQuietFrame));
+            mDiscardedFrames++;
+            return;
+        }
+    }
 
     ATRACE_INT(lumaSamplingStepTag, static_cast<int>(samplingStep::sample));
 
-    mDiscardedFrames = false;
+    mDiscardedFrames = 0;
     lastSampleTime = now;
 
     mIdleTimer.reset();
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index ac7339c..99c07c2 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -117,7 +117,7 @@
     std::condition_variable_any mCondition;
     bool mRunning GUARDED_BY(mThreadControlMutex) = true;
     bool mSampleRequested GUARDED_BY(mThreadControlMutex) = false;
-    bool mDiscardedFrames GUARDED_BY(mThreadControlMutex) = false;
+    uint32_t mDiscardedFrames GUARDED_BY(mThreadControlMutex) = 0;
     std::chrono::nanoseconds lastSampleTime GUARDED_BY(mThreadControlMutex);
 
     std::mutex mSamplingMutex;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 65f0e40..27f42d2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -518,22 +518,19 @@
         return RefreshRateType::PERFORMANCE;
     }
 
-    // Content detection is on, find the appropriate refresh rate
-    // Start with the smallest refresh rate which is within a margin of the content
-    RefreshRateType currRefreshRateType = RefreshRateType::PERFORMANCE;
-    constexpr float MARGIN = 0.05f;
-    auto iter = mRefreshRateConfigs.getRefreshRates().cbegin();
-    while (iter != mRefreshRateConfigs.getRefreshRates().cend()) {
-        if (iter->second->fps >= mContentRefreshRate * (1 - MARGIN)) {
-            currRefreshRateType = iter->first;
-            break;
-        }
-        ++iter;
-    }
+    // Content detection is on, find the appropriate refresh rate with minimal error
+    auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
+                            mRefreshRateConfigs.getRefreshRates().cend(),
+                            [rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
+                                return std::abs(l.second->fps - static_cast<float>(rate)) <
+                                        std::abs(r.second->fps - static_cast<float>(rate));
+                            });
+    RefreshRateType currRefreshRateType = iter->first;
 
     // Some content aligns better on higher refresh rate. For example for 45fps we should choose
     // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
     // align well with both
+    constexpr float MARGIN = 0.05f;
     float ratio = mRefreshRateConfigs.getRefreshRate(currRefreshRateType)->fps /
             float(mContentRefreshRate);
     if (std::abs(std::round(ratio) - ratio) > MARGIN) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e5896f9..2cb2544 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3534,11 +3534,6 @@
     return true;
 }
 
-void SurfaceFlinger::drawWormhole(const Region& region) const {
-    auto& engine(getRenderEngine());
-    engine.fillRegionWithColor(region, 0, 0, 0, 0);
-}
-
 status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                                         const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
                                         const sp<IBinder>& parentHandle,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6d4b2d7..1a9dcdd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -790,7 +790,6 @@
 
     void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
-    void drawWormhole(const Region& region) const;
 
     /* ------------------------------------------------------------------------
      * Display management
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index f83b3ea..d5f6534 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1115,6 +1115,56 @@
     }
 }
 
+TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) {
+    sp<SurfaceControl> parent =
+            LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */,
+                                              ISurfaceComposerClient::eFXSurfaceColor);
+    sp<SurfaceControl> relativeParent =
+            LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */,
+                    0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceColor);
+
+    sp<SurfaceControl> childLayer;
+    ASSERT_NO_FATAL_FAILURE(
+            childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */,
+                                                           0 /* buffer height */,
+                                                           ISurfaceComposerClient::eFXSurfaceColor,
+                                                           parent.get()));
+    Transaction()
+            .setColor(childLayer, half3{1.0f, 0.0f, 0.0f})
+            .setColor(parent, half3{0.0f, 0.0f, 0.0f})
+            .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f})
+            .show(childLayer)
+            .show(parent)
+            .show(relativeParent)
+            .setLayer(parent, mLayerZBase - 1)
+            .setLayer(relativeParent, mLayerZBase)
+            .apply();
+
+    Transaction()
+            .setRelativeLayer(childLayer, relativeParent->getHandle(), 1)
+            .apply();
+
+    {
+        SCOPED_TRACE("setLayer above");
+        // Set layer should get applied and place the child above.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED);
+    }
+
+    Transaction()
+        .hide(relativeParent)
+        .apply();
+
+    {
+        SCOPED_TRACE("hide relative parent");
+        // The relative should no longer be visible.
+        std::unique_ptr<ScreenCapture> screenshot;
+        ScreenCapture::captureScreen(&screenshot);
+        screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK);
+    }
+}
+
 void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) {
     sp<SurfaceControl> layerR;
     sp<SurfaceControl> layerG;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 4f8ed1a..e6211c4 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -303,11 +303,6 @@
         EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1);
 
         EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
-        // TODO: remove once we verify that we can just grab the fence from the
-        // FramebufferSurface.
-        EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
-            return base::unique_fd();
-        }));
 
         EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
         EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
new file mode 100644
index 0000000..05dc995
--- /dev/null
+++ b/vulkan/scripts/api_generator.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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.
+#
+# This script provides the functions required for generating the
+# vulkan api framework directly from the vulkan registry (vk.xml)
+
+import os
+import generator_common as gencom
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
+    return True
+  return False
+
+def api_genh():
+
+  header = """#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+#include "driver_gen.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+
+  tail = """
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_API_GEN_H
+"""
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen2.h')
+  with open(genfile, 'w') as f:
+    instanceDispatchTableEntries = []
+    deviceDispatchTableEntries = []
+    for commands in gencom.allCommandsList:
+      if commands not in gencom.aliasDict:
+        if gencom.isInstanceDispatchTableEntry(commands):
+          instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+        elif gencom.isDeviceDispatchTableEntry(commands):
+          deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write (header)
+    f.write ('struct InstanceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in instanceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n\n')
+
+    f.write ('struct DeviceDispatchTable {\n')
+    gencom.clang_off(f,1)
+    for functions in deviceDispatchTableEntries:
+      f.write(gencom.clang_off_spaces + functions + '\n')
+    gencom.clang_on(f,1)
+    f.write ('};\n')
+
+    f.write (tail)
+    f.close()
+
+def defineInitProc(name, f):
+  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
+  f.write ('\n')
+  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.""" + name + """.proc =                                           \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.""" + name + """.proc)) {               \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)\n\n""")
+
+def defineInitProcExt(f):
+  f.write ('// Exported extension functions may be invoked even when their extensions\n')
+  f.write ('// are disabled.  Dispatch to stubs when that happens.\n')
+  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc)  \\
+    do {                                         \\
+        if (extensions[driver::ProcHook::ext])   \\
+            INIT_PROC(required, obj, proc);      \\
+        else                                     \\
+            data.dispatch.proc = disabled##proc; \\
+    } while (0)\n\n""")
+
+def defineExtensionStub(functionName, f):
+  if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
+    extname = gencom.extensionsDict[functionName]
+    base_name = functionName[2:]
+    pList = gencom.paramDict[functionName]
+    firstParam = pList[0][0] + pList[0][1]
+    tailParams = [x[0][:-1] for x in pList[1:]]
+    tailP = ', '.join(tailParams)
+    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
+    f.write (gencom.clang_off_spaces)
+    f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
+    if gencom.returnTypeDict[functionName] != 'void':
+      f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
+    f.write ('}\n\n')
+
+def isIntercepted(functionName):
+  if gencom.isFunctionSupported(functionName):
+    if gencom.isGloballyDispatched(functionName):
+      return True
+    elif functionName == 'vkCreateDevice':
+      return True
+    elif functionName == 'vkEnumerateDeviceLayerProperties':
+      return True
+    elif functionName == 'vkEnumerateDeviceExtensionProperties':
+      return True
+    elif functionName == 'vkDestroyInstance':
+      return True
+    elif functionName == 'vkDestroyDevice':
+      return True
+  return False
+
+def interceptInstanceProcAddr(functionName, f):
+  indent = 1
+  f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
+  indent = indent + 1
+  for cmds in gencom.allCommandsList:
+    if gencom.isGloballyDispatched(cmds):
+      f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+
+  f.write ('\n')
+  f.write ("""        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+        return nullptr;
+    }
+
+    static const struct Hook {
+        const char* name;
+        PFN_vkVoidFunction proc;
+    } hooks[] = {\n""")
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionExported(cmds):
+      if gencom.isGloballyDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
+      elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
+        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
+  f.write (gencom.clang_off_spaces + """};
+    // clang-format on
+    constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+    auto hook = std::lower_bound(
+        hooks, hooks + count, pName,
+        [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+    if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
+        if (!hook->proc) {
+            vulkan::driver::Logger(instance).Err(
+                instance, "invalid vkGetInstanceProcAddr(%p, \\\"%s\\\") call",
+                instance, pName);
+        }
+        return hook->proc;
+    }
+    // clang-format off\n\n""")
+
+def interceptDeviceProcAddr(functionName, f):
+  f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+        ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
+        return nullptr;
+    }\n\n""")
+  f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
+  sortedCommandsList = sorted(gencom.allCommandsList)
+  for cmds in sortedCommandsList:
+    if gencom.isFunctionSupported(cmds):
+      if not gencom.isDeviceDispatched(cmds):
+        f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
+  f.write(gencom.clang_off_spaces + '};\n')
+  f.write(gencom.clang_off_spaces + """// clang-format on
+    constexpr size_t count =
+        sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
+    if (!pName ||
+        std::binary_search(
+            known_non_device_names, known_non_device_names + count, pName,
+            [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+        vulkan::driver::Logger(device).Err(
+            device, "invalid vkGetDeviceProcAddr(%p, \\\"%s\\\") call", device,
+            (pName) ? pName : "(null)");
+        return nullptr;
+    }
+    // clang-format off\n\n""")
+  for cmds in gencom.allCommandsList:
+    if gencom.isDeviceDispatched(cmds):
+      if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
+        f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
+  f.write ('\n')
+
+def apiDispatch(functionName, f):
+  assert not isIntercepted(functionName)
+
+  f.write (gencom.clang_off_spaces)
+  if gencom.returnTypeDict[functionName] != 'void':
+    f.write ('return ')
+
+  paramList = gencom.paramDict[functionName]
+  p0 = paramList[0][1]
+  f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+
+
+def api_gencpp():
+  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen2.cpp')
+  header = """#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {
+
+"""
+  with open(genfile, 'w') as f:
+    f.write (gencom.copyright)
+    f.write (gencom.warning)
+    f.write ("""#include <log/log.h>
+#include <string.h>
+
+#include <algorithm>
+
+// to catch mismatches between vulkan.h and this file
+#undef VK_NO_PROTOTYPES
+#include "api.h"
+
+namespace vulkan {
+namespace api {\n\n""")
+    defineInitProc('dispatch',f)
+    defineInitProcExt(f)
+    f.write ('namespace {\n\n')
+    gencom.clang_off(f,0)
+    f.write ('\n')
+    for cmds in gencom.allCommandsList:
+      defineExtensionStub(cmds,f)
+    gencom.clang_on(f,0)
+    f.write ('\n}  // namespace\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;\n\n""")
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isInstanceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+    f.write ("""bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;\n\n""")
+
+    gencom.clang_off(f,1)
+    for cmds in gencom.allCommandsList:
+      if gencom.isDeviceDispatchTableEntry(cmds):
+        gencom.initProc(cmds, f)
+    gencom.clang_on(f,1)
+    f.write ('\n')
+    f.write ('    return success;\n}\n\n')
+
+    gencom.clang_off(f,0)
+
+    f.write ('\nnamespace {\n\n')
+    f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+
+    f.write ('\n')
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
+        if cmds == 'vkGetInstanceProcAddr':
+          interceptInstanceProcAddr(cmds, f)
+        elif cmds == 'vkGetDeviceProcAddr':
+          interceptDeviceProcAddr(cmds, f)
+        apiDispatch(cmds, f)
+        f.write('}\n\n')
+    f.write ("""\n}  // anonymous namespace
+
+// clang-format on
+
+}  // namespace api
+}  // namespace vulkan
+
+// clang-format off\n\n""")
+
+    for cmds in gencom.allCommandsList:
+      if gencom.isFunctionExported(cmds):
+        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
+        f.write ('__attribute__((visibility("default")))\n')
+        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
+        f.write (gencom.clang_off_spaces)
+        if gencom.returnTypeDict[cmds] != 'void':
+          f.write ('return ')
+        paramList = gencom.paramDict[cmds]
+        f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+        f.write ('}\n\n')
+
+    gencom.clang_on(f, 0)
+
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
new file mode 100644
index 0000000..91c0d30
--- /dev/null
+++ b/vulkan/scripts/code_generator.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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.
+#
+# This script provides the main function for generating
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+import generator_common as gencom
+import api_generator as apigen
+
+if __name__ == '__main__':
+  gencom.parseVulkanRegistry()
+  apigen.api_genh()
+  apigen.api_gencpp()
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
new file mode 100644
index 0000000..313357d
--- /dev/null
+++ b/vulkan/scripts/generator_common.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 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.
+#
+# This script provides the common functions for generating the
+# vulkan framework directly from the vulkan registry (vk.xml).
+
+copyright = """/*
+ * 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.
+ */
+
+"""
+
+warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
+
+blacklistedExtensions = [
+    'VK_KHR_display',
+    'VK_KHR_display_swapchain',
+    'VK_KHR_mir_surface',
+    'VK_KHR_xcb_surface',
+    'VK_KHR_xlib_surface',
+    'VK_KHR_wayland_surface',
+    'VK_KHR_win32_surface',
+    'VK_KHR_external_memory_win32',
+    'VK_KHR_win32_keyed_mutex',
+    'VK_KHR_external_semaphore_win32',
+    'VK_KHR_external_fence_win32',
+    'VK_EXT_acquire_xlib_display',
+    'VK_EXT_direct_mode_display',
+    'VK_EXT_display_surface_counter',
+    'VK_EXT_display_control',
+    'VK_FUCHSIA_imagepipe_surface',
+    'VK_MVK_ios_surface',
+    'VK_MVK_macos_surface',
+    'VK_NN_vi_surface',
+    'VK_NV_external_memory_win32',
+    'VK_NV_win32_keyed_mutex',
+    'VK_EXT_metal_surface', #not present in vulkan.api
+    'VK_NVX_image_view_handle', #not present in vulkan.api
+    'VK_NV_cooperative_matrix' #not present in vulkan.api
+]
+
+exportedExtensions = [
+    'VK_KHR_surface',
+    'VK_KHR_swapchain',
+    'VK_KHR_android_surface',
+    'VK_ANDROID_external_memory_android_hardware_buffer'
+]
+
+def isFunctionSupported(functionName):
+  if functionName not in extensionsDict:
+    return True
+  else:
+    if extensionsDict[functionName] not in blacklistedExtensions:
+      return True
+  return False
+
+def isInstanceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
+
+def isDeviceDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
+
+def isGloballyDispatched(functionName):
+  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
+
+def isExtensionExported(extensionName):
+  if extensionName in exportedExtensions:
+    return True
+  return False
+
+def isFunctionExported(functionName):
+  if isFunctionSupported(functionName):
+    if functionName in extensionsDict:
+      return isExtensionExported(extensionsDict[functionName])
+    return True
+  return False
+
+def getDispatchTableType(functionName):
+  if functionName not in paramDict:
+    return None
+
+  switchCase = {
+      'VkInstance ' : 'Instance',
+      'VkPhysicalDevice ' : 'Instance',
+      'VkDevice ' : 'Device',
+      'VkQueue ' : 'Device',
+      'VkCommandBuffer ' : 'Device'
+  }
+
+  if len(paramDict[functionName])>0:
+    return switchCase.get(paramDict[functionName][0][0], 'Global')
+  return 'Global'
+
+def isInstanceDispatchTableEntry(functionName):
+  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+    return False
+  if isFunctionExported(functionName) and isInstanceDispatched(functionName):
+    return True
+  return False
+
+def isDeviceDispatchTableEntry(functionName):
+  if isFunctionExported(functionName) and isDeviceDispatched(functionName):
+    return True
+  return False
+
+
+def clang_on(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format on\n')
+
+def clang_off(f, indent):
+  f.write (clang_off_spaces * indent + '// clang-format off\n')
+
+clang_off_spaces = ' '*4
+
+parametersList = []
+paramDict = {}
+allCommandsList = []
+extensionsDict = {}
+returnTypeDict = {}
+versionDict = {}
+aliasDict = {}
+
+def parseVulkanRegistry():
+  import xml.etree.ElementTree as ET
+  import os
+  vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
+  tree = ET.parse(vulkan_registry)
+  root = tree.getroot()
+  protoset = False
+  fnName = ""
+  fnType = ""
+  for commands in root.iter('commands'):
+    for command in commands:
+      if command.tag == 'command':
+        if protoset == True:
+          paramDict[fnName] = parametersList.copy()
+        parametersList.clear()
+        protoset = False
+        if command.get('alias') != None:
+          alias = command.get('alias')
+          fnName = command.get('name')
+          aliasDict[fnName] = alias
+          allCommandsList.append(fnName)
+          paramDict[fnName] = paramDict[alias].copy()
+        for params in command:
+          if(params.tag == 'param'):
+            paramtype = ""
+            if params.text!=None:
+              paramtype = params.text
+            typeval = params.find('type')
+            paramtype = paramtype + typeval.text
+            if typeval.tail!=None:
+              paramtype = paramtype + typeval.tail
+            pname = params.find('name')
+            paramname = pname.text
+            if pname.tail != None:
+              parametersList.append((paramtype,paramname,pname.tail))
+            else:
+              parametersList.append((paramtype,paramname))
+          if params.tag == 'proto':
+            for c in params:
+              if c.tag == 'type':
+                fnType = c.text
+              if c.tag == 'name':
+                fnName = c.text
+                protoset = True
+                allCommandsList.append(fnName)
+                returnTypeDict[fnName] = fnType
+
+  for exts in root.iter('extensions'):
+    for extension in exts:
+      apiversion = ""
+      if extension.tag == 'extension':
+        extname = extension.get('name')
+        for req in extension:
+          if req.get('feature')!=None:
+            apiversion = req.get('feature')
+          for commands in req:
+            if commands.tag == 'command':
+              commandname = commands.get('name')
+              if commandname not in extensionsDict:
+                extensionsDict[commandname] = extname
+                if apiversion != "":
+                  versionDict[commandname] = apiversion
+
+  for feature in root.iter('feature'):
+    apiversion = feature.get('name')
+    for req in feature:
+      for command in req:
+        if command.tag == 'command':
+          cmdName = command.get('name')
+          if cmdName in allCommandsList:
+            versionDict[cmdName] = apiversion
+
+
+def initProc(name, f):
+  if name in extensionsDict:
+    f.write ('    INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
+  else:
+    f.write ('    INIT_PROC(')
+
+  if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
+    f.write('false, ')
+  else:
+    f.write('true, ')
+
+  if isInstanceDispatched(name):
+    f.write('instance, ')
+  else:
+    f.write('dev, ')
+
+  f.write(name[2:] + ');\n')
+