Merge "Fixed buffering issues."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index a5efff9..b6f6adc 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -537,7 +537,12 @@
             hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
             hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
             auto getRet = sm->get(fqInterfaceName, instanceName, [&](const auto &interface) {
-                interface->notifySyspropsChanged();
+                auto notifyRet = interface->notifySyspropsChanged();
+                if (!notifyRet.isOk()) {
+                    fprintf(stderr, "failed to notifySyspropsChanged on service %s: %s\n",
+                            fqInstanceName.c_str(),
+                            notifyRet.getStatus().toString8().string());
+                }
             });
             if (!getRet.isOk()) {
                 fprintf(stderr, "failed to get service %s: %s\n",
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 2b23a3d..17b411f 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -4,7 +4,7 @@
 # Common settings #
 # ================#
 # ZipArchive support, the order matters here to get all symbols.
-COMMON_ZIP_LIBRARIES := libziparchive libz libcrypto_static
+COMMON_ZIP_LIBRARIES := libziparchive libz libcrypto
 
 # TODO: ideally the tests should depend on a shared dumpstate library, but currently libdumpstate
 # is used to define the device-specific HAL library. Instead, both dumpstate and dumpstate_test
@@ -23,10 +23,10 @@
         libhardware_legacy \
         liblog \
         libselinux \
-        libutils
-COMMON_STATIC_LIBRARIES := \
-        libdumpstateutil \
+        libutils \
         $(COMMON_ZIP_LIBRARIES)
+COMMON_STATIC_LIBRARIES := \
+        libdumpstateutil
 
 # ====================#
 # libdumpstateutil #
@@ -152,19 +152,32 @@
 LOCAL_SRC_FILES := \
         tests/dumpstate_test_fixture.cpp
 
-dist_zip_root := $(TARGET_OUT_DATA)
+LOCAL_MODULE_CLASS := NATIVE_TESTS
+
+dumpstate_tests_intermediates := $(local-intermediates-dir)/DATA
 dumpstate_tests_subpath_from_data := nativetest/dumpstate_test_fixture
 dumpstate_tests_root_in_device := /data/$(dumpstate_tests_subpath_from_data)
-dumpstate_tests_root_for_test_zip := $(dist_zip_root)/$(dumpstate_tests_subpath_from_data)
+dumpstate_tests_root_for_test_zip := $(dumpstate_tests_intermediates)/$(dumpstate_tests_subpath_from_data)
 testdata_files := $(call find-subdir-files, testdata/*)
 
+# Copy test data files to intermediates/DATA for use with LOCAL_PICKUP_FILES
 GEN := $(addprefix $(dumpstate_tests_root_for_test_zip)/, $(testdata_files))
 $(GEN): PRIVATE_PATH := $(LOCAL_PATH)
 $(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@
 $(GEN): $(dumpstate_tests_root_for_test_zip)/testdata/% : $(LOCAL_PATH)/testdata/%
 	$(transform-generated-source)
 LOCAL_GENERATED_SOURCES += $(GEN)
-LOCAL_PICKUP_FILES := $(dist_zip_root)
+
+# Copy test data files again to $OUT/data so the tests can be run with adb sync
+# TODO: the build system should do this automatically
+GEN := $(addprefix $(TARGET_OUT_DATA)/$(dumpstate_tests_subpath_from_data)/, $(testdata_files))
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@
+$(GEN): $(TARGET_OUT_DATA)/$(dumpstate_tests_subpath_from_data)/testdata/% : $(LOCAL_PATH)/testdata/%
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+LOCAL_PICKUP_FILES := $(dumpstate_tests_intermediates)
 
 include $(BUILD_NATIVE_TEST)
 
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index e3048c7..4ed45ae 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -9,13 +9,16 @@
         "commands.cpp",
         "globals.cpp",
         "utils.cpp",
+        "binder/android/os/IInstalld.aidl",
     ],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libcutils",
         "liblog",
         "liblogwrap",
         "libselinux",
+        "libutils",
     ],
 
     clang: true,
@@ -30,6 +33,9 @@
     defaults: ["installd_defaults"],
 
     export_include_dirs: ["."],
+    aidl: {
+        export_aidl_headers: true,
+    },
 }
 
 //
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 54f6b5f..9406da1 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -23,13 +23,15 @@
 LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
 LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
 
-LOCAL_SRC_FILES := otapreopt.cpp commands.cpp globals.cpp utils.cpp
+LOCAL_SRC_FILES := otapreopt.cpp commands.cpp globals.cpp utils.cpp binder/android/os/IInstalld.aidl
 LOCAL_SHARED_LIBRARIES := \
     libbase \
+    libbinder \
     libcutils \
     liblog \
     liblogwrap \
     libselinux \
+    libutils \
 
 LOCAL_STATIC_LIBRARIES := libdiskusage
 LOCAL_CLANG := true
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
new file mode 100644
index 0000000..4f84319
--- /dev/null
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.os;
+
+interface IInstalld {
+    void createUserData(@nullable @utf8InCpp String uuid, int userId, int userSerial, int flags);
+    void destroyUserData(@nullable @utf8InCpp String uuid, int userId, int flags);
+
+    void createAppData(in @nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
+            int userId, int flags, int appId, in @utf8InCpp String seInfo, int targetSdkVersion);
+    void restoreconAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+            int userId, int flags, int appId, @utf8InCpp String seInfo);
+    void migrateAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+            int userId, int flags);
+    void clearAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+            int userId, int flags, long ceDataInode);
+    void destroyAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+            int userId, int flags, long ceDataInode);
+    long getAppDataInode(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
+            int userId, int flags);
+
+    void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
+            @utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
+            @utf8InCpp String seInfo, int targetSdkVersion);
+
+    void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet);
+
+    boolean mergeProfiles(int uid, @utf8InCpp String packageName);
+    boolean dumpProfiles(int uid, @utf8InCpp String packageName, @utf8InCpp String codePaths);
+    void clearAppProfiles(@utf8InCpp String packageName);
+    void destroyAppProfiles(@utf8InCpp String packageName);
+
+    void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
+    void rmPackageDir(@utf8InCpp String packageDir);
+    void markBootComplete(@utf8InCpp String instructionSet);
+    void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize);
+    void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
+            @utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId);
+    void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet);
+    void linkFile(@utf8InCpp String relativePath, @utf8InCpp String fromBase,
+            @utf8InCpp String toBase);
+    void moveAb(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
+            @utf8InCpp String outputPath);
+    void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
+            @utf8InCpp String outputPath);
+}
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 9f19597..cfe415d 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -86,6 +86,67 @@
 
 typedef int fd_t;
 
+namespace {
+
+constexpr const char* kDump = "android.permission.DUMP";
+
+binder::Status checkPermission(const char* permission) {
+    pid_t pid;
+    uid_t uid;
+
+    if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
+            reinterpret_cast<int32_t*>(&uid))) {
+        return binder::Status::ok();
+    } else {
+        auto err = StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission);
+        return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
+    }
+}
+
+binder::Status checkUid(uid_t expectedUid) {
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (uid == expectedUid || uid == AID_ROOT) {
+        return binder::Status::ok();
+    } else {
+        auto err = StringPrintf("UID %d is not expected UID %d", uid, expectedUid);
+        return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(err.c_str()));
+    }
+}
+
+#define ENFORCE_UID(uid) {                                  \
+    binder::Status status = checkUid((uid));                \
+    if (!status.isOk()) {                                   \
+        return status;                                      \
+    }                                                       \
+}
+
+}  // namespace
+
+status_t InstalldNativeService::start() {
+    IPCThreadState::self()->disableBackgroundScheduling(true);
+    status_t ret = BinderService<InstalldNativeService>::publish();
+    if (ret != android::OK) {
+        return ret;
+    }
+    sp<ProcessState> ps(ProcessState::self());
+    ps->startThreadPool();
+    ps->giveThreadPoolName();
+    return android::OK;
+}
+
+status_t InstalldNativeService::dump(int fd, const Vector<String16> & /* args */) {
+    const binder::Status dump_permission = checkPermission(kDump);
+    if (!dump_permission.isOk()) {
+        const String8 msg(dump_permission.toString8());
+        write(fd, msg.string(), msg.size());
+        return PERMISSION_DENIED;
+    }
+
+    std::string msg = "installd is happy\n";
+    write(fd, msg.c_str(), strlen(msg.c_str()));
+    return NO_ERROR;
+}
+
 static bool property_get_bool(const char* property_name, bool default_value = false) {
     char tmp_property_value[kPropertyValueMax];
     bool have_property = get_property(property_name, tmp_property_value, nullptr) > 0;
@@ -106,7 +167,7 @@
  * if the label of that top-level file actually changed.  This can save us
  * significant time by avoiding no-op traversals of large filesystem trees.
  */
-static int restorecon_app_data_lazy(const std::string& path, const char* seinfo, uid_t uid) {
+static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid) {
     int res = 0;
     char* before = nullptr;
     char* after = nullptr;
@@ -118,7 +179,7 @@
         PLOG(ERROR) << "Failed before getfilecon for " << path;
         goto fail;
     }
-    if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, 0) < 0) {
+    if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid, 0) < 0) {
         PLOG(ERROR) << "Failed top-level restorecon for " << path;
         goto fail;
     }
@@ -132,7 +193,7 @@
     if (strcmp(before, after)) {
         LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path
                 << "; running recursive restorecon";
-        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid,
+        if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
                 SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
             PLOG(ERROR) << "Failed recursive restorecon for " << path;
             goto fail;
@@ -148,9 +209,9 @@
     return res;
 }
 
-static int restorecon_app_data_lazy(const std::string& parent, const char* name, const char* seinfo,
-        uid_t uid) {
-    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seinfo, uid);
+static int restorecon_app_data_lazy(const std::string& parent, const char* name,
+        const std::string& seInfo, uid_t uid) {
+    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid);
 }
 
 static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
@@ -166,56 +227,62 @@
     return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid);
 }
 
-int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        appid_t appid, const char* seinfo, int target_sdk_version) {
-    uid_t uid = multiuser_get_uid(userid, appid);
-    mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
+        const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
+        const std::string& seInfo, int32_t targetSdkVersion) {
+    ENFORCE_UID(AID_SYSTEM);
+
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+
+    uid_t uid = multiuser_get_uid(userId, appId);
+    mode_t target_mode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
     if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
         if (prepare_app_dir(path, target_mode, uid) ||
                 prepare_app_dir(path, "cache", 0771, uid) ||
                 prepare_app_dir(path, "code_cache", 0771, uid)) {
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
 
         // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seinfo, uid) ||
-                restorecon_app_data_lazy(path, "cache", seinfo, uid) ||
-                restorecon_app_data_lazy(path, "code_cache", seinfo, uid)) {
-            return -1;
+        if (restorecon_app_data_lazy(path, seInfo, uid) ||
+                restorecon_app_data_lazy(path, "cache", seInfo, uid) ||
+                restorecon_app_data_lazy(path, "code_cache", seInfo, uid)) {
+            return binder::Status::fromServiceSpecificError(-1);
         }
 
         // Remember inode numbers of cache directories so that we can clear
         // contents while CE storage is locked
         if (write_path_inode(path, "cache", kXattrInodeCache) ||
                 write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
     }
     if (flags & FLAG_STORAGE_DE) {
-        auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+        auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
         if (prepare_app_dir(path, target_mode, uid)) {
             // TODO: include result once 25796509 is fixed
-            return 0;
+            return binder::Status::ok();
         }
 
         // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seinfo, uid)) {
-            return -1;
+        if (restorecon_app_data_lazy(path, seInfo, uid)) {
+            return binder::Status::fromServiceSpecificError(-1);
         }
 
         if (property_get_bool("dalvik.vm.usejitprofiles")) {
-            const std::string profile_path = create_data_user_profile_package_path(userid, pkgname);
+            const std::string profile_path = create_data_user_profile_package_path(userId, pkgname);
             // read-write-execute only for the app user.
             if (fs_prepare_dir_strict(profile_path.c_str(), 0700, uid, uid) != 0) {
                 PLOG(ERROR) << "Failed to prepare " << profile_path;
-                return -1;
+                return binder::Status::fromServiceSpecificError(-1);
             }
             std::string profile_file = create_primary_profile(profile_path);
             // read-write only for the app user.
             if (fs_prepare_file_strict(profile_file.c_str(), 0600, uid, uid) != 0) {
                 PLOG(ERROR) << "Failed to prepare " << profile_path;
-                return -1;
+                return binder::Status::fromServiceSpecificError(-1);
             }
             const std::string ref_profile_path = create_data_ref_profile_package_path(pkgname);
             // dex2oat/profman runs under the shared app gid and it needs to read/write reference
@@ -224,28 +291,33 @@
             if (fs_prepare_dir_strict(
                     ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
                 PLOG(ERROR) << "Failed to prepare " << ref_profile_path;
-                return -1;
+                return binder::Status::fromServiceSpecificError(-1);
             }
         }
     }
-    return 0;
+    return binder::Status::ok();
 }
 
-int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+binder::Status InstalldNativeService::migrateAppData(const std::unique_ptr<std::string>& uuid,
+        const std::string& packageName, int32_t userId, int32_t flags) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+
     // This method only exists to upgrade system apps that have requested
     // forceDeviceEncrypted, so their default storage always lives in a
     // consistent location.  This only works on non-FBE devices, since we
     // never want to risk exposing data on a device with real CE/DE storage.
 
-    auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
-    auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);
+    auto ce_path = create_data_user_ce_package_path(uuid_, userId, pkgname);
+    auto de_path = create_data_user_de_package_path(uuid_, userId, pkgname);
 
     // If neither directory is marked as default, assume CE is default
     if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1
             && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) {
         if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) {
             PLOG(ERROR) << "Failed to mark default storage " << ce_path;
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
     }
 
@@ -258,15 +330,15 @@
                 << " is not active; migrating from " << source;
         if (delete_dir_contents_and_dir(target) != 0) {
             PLOG(ERROR) << "Failed to delete";
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
         if (rename(source.c_str(), target.c_str()) != 0) {
             PLOG(ERROR) << "Failed to rename";
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
     }
 
-    return 0;
+    return binder::Status::ok();
 }
 
 static bool clear_profile(const std::string& profile) {
@@ -334,18 +406,24 @@
     return success;
 }
 
-int clear_app_profiles(const char* pkgname) {
+binder::Status InstalldNativeService::clearAppProfiles(const std::string& packageName) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* pkgname = packageName.c_str();
     bool success = true;
     success &= clear_reference_profile(pkgname);
     success &= clear_current_profiles(pkgname);
-    return success ? 0 : -1;
+    return success ? binder::Status::ok() : binder::Status::fromServiceSpecificError(-1);
 }
 
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        ino_t ce_data_inode) {
+binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid,
+        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+
     int res = 0;
     if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
         if (flags & FLAG_CLEAR_CACHE_ONLY) {
             path = read_path_inode(path, "cache", kXattrInodeCache);
         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
@@ -366,18 +444,18 @@
             only_cache = true;
         }
 
-        auto path = create_data_user_de_package_path(uuid, userid, pkgname) + suffix;
+        auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
         if (access(path.c_str(), F_OK) == 0) {
             // TODO: include result once 25796509 is fixed
             delete_dir_contents(path);
         }
         if (!only_cache) {
-            if (!clear_current_profile(pkgname, userid)) {
+            if (!clear_current_profile(pkgname, userId)) {
                 res |= -1;
             }
         }
     }
-    return res;
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
 static int destroy_app_reference_profile(const char *pkgname) {
@@ -392,37 +470,51 @@
         /*ignore_if_missing*/ true);
 }
 
-int destroy_app_profiles(const char *pkgname) {
+binder::Status InstalldNativeService::destroyAppProfiles(const std::string& packageName) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* pkgname = packageName.c_str();
     int result = 0;
     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
     for (auto user : users) {
         result |= destroy_app_current_profiles(pkgname, user);
     }
     result |= destroy_app_reference_profile(pkgname);
-    return result;
+    return result ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        ino_t ce_data_inode) {
+binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std::string>& uuid,
+        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+
     int res = 0;
     if (flags & FLAG_STORAGE_CE) {
         res |= delete_dir_contents_and_dir(
-                create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
+                create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode));
     }
     if (flags & FLAG_STORAGE_DE) {
         res |= delete_dir_contents_and_dir(
-                create_data_user_de_package_path(uuid, userid, pkgname));
-        destroy_app_current_profiles(pkgname, userid);
+                create_data_user_de_package_path(uuid_, userId, pkgname));
+        destroy_app_current_profiles(pkgname, userId);
         // TODO(calin): If the package is still installed by other users it's probably
         // beneficial to keep the reference profile around.
         // Verify if it's ok to do that.
         destroy_app_reference_profile(pkgname);
     }
-    return res;
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
-int move_complete_app(const char *from_uuid, const char *to_uuid, const char *package_name,
-        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version) {
+binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
+        const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
+        const std::string& dataAppName, int32_t appId, const std::string& seInfo,
+        int32_t targetSdkVersion) {
+
+    const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
+    const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
+    const char* package_name = packageName.c_str();
+    const char* data_app_name = dataAppName.c_str();
+
     std::vector<userid_t> users = get_known_users(from_uuid);
 
     // Copy app
@@ -467,8 +559,8 @@
             continue;
         }
 
-        if (create_app_data(to_uuid, package_name, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
-                appid, seinfo, target_sdk_version) != 0) {
+        if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId,
+                seInfo, targetSdkVersion).isOk()) {
             LOG(ERROR) << "Failed to create package target on " << to_uuid;
             goto fail;
         }
@@ -511,8 +603,8 @@
             }
         }
 
-        if (restorecon_app_data(to_uuid, package_name, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
-                appid, seinfo) != 0) {
+        if (!restoreconAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
+                appId, seInfo).isOk()) {
             LOG(ERROR) << "Failed to restorecon";
             goto fail;
         }
@@ -521,7 +613,7 @@
     // We let the framework scan the new location and persist that before
     // deleting the data in the old location; this ordering ensures that
     // we can recover from things like battery pulls.
-    return 0;
+    return binder::Status::ok();
 
 fail:
     // Nuke everything we might have already copied
@@ -545,33 +637,39 @@
             }
         }
     }
-    return -1;
+    return binder::Status::fromServiceSpecificError(-1);
 }
 
-int create_user_data(const char *uuid, userid_t userid, int user_serial ATTRIBUTE_UNUSED,
-        int flags) {
-    if (flags & FLAG_STORAGE_DE) {
-        if (uuid == nullptr) {
-            return ensure_config_user_dirs(userid);
-        }
-    }
-    return 0;
-}
-
-int destroy_user_data(const char *uuid, userid_t userid, int flags) {
+binder::Status InstalldNativeService::createUserData(const std::unique_ptr<std::string>& uuid,
+        int32_t userId, int32_t userSerial ATTRIBUTE_UNUSED, int32_t flags) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     int res = 0;
     if (flags & FLAG_STORAGE_DE) {
-        res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid, userid), true);
-        if (uuid == nullptr) {
-            res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userid), true);
-            res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userid), true);
+        if (uuid_ == nullptr) {
+            res = ensure_config_user_dirs(userId);
+        }
+    }
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
+}
+
+binder::Status InstalldNativeService::destroyUserData(const std::unique_ptr<std::string>& uuid,
+        int32_t userId, int32_t flags) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    int res = 0;
+    if (flags & FLAG_STORAGE_DE) {
+        res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid_, userId), true);
+        if (uuid_ == nullptr) {
+            res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userId), true);
+            res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userId), true);
         }
     }
     if (flags & FLAG_STORAGE_CE) {
-        res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid, userid), true);
-        res |= delete_dir_contents_and_dir(create_data_media_path(uuid, userid), true);
+        res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid_, userId), true);
+        res |= delete_dir_contents_and_dir(create_data_media_path(uuid_, userId), true);
     }
-    return res;
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
 /* Try to ensure free_size bytes of storage are available.
@@ -581,53 +679,70 @@
  * also require that apps constantly modify file metadata even
  * when just reading from the cache, which is pretty awful.
  */
-int free_cache(const char *uuid, int64_t free_size) {
+binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid,
+        int64_t freeStorageSize) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     cache_t* cache;
     int64_t avail;
 
-    auto data_path = create_data_path(uuid);
+    auto data_path = create_data_path(uuid_);
 
     avail = data_disk_free(data_path);
-    if (avail < 0) return -1;
+    if (avail < 0) {
+        return binder::Status::fromServiceSpecificError(-1);
+    }
 
-    ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
-    if (avail >= free_size) return 0;
+    ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", freeStorageSize, avail);
+    if (avail >= freeStorageSize) {
+        return binder::Status::ok();
+    }
 
     cache = start_cache_collection();
 
-    auto users = get_known_users(uuid);
+    auto users = get_known_users(uuid_);
     for (auto user : users) {
-        add_cache_files(cache, create_data_user_ce_path(uuid, user));
-        add_cache_files(cache, create_data_user_de_path(uuid, user));
+        add_cache_files(cache, create_data_user_ce_path(uuid_, user));
+        add_cache_files(cache, create_data_user_de_path(uuid_, user));
         add_cache_files(cache,
-                StringPrintf("%s/Android/data", create_data_media_path(uuid, user).c_str()));
+                StringPrintf("%s/Android/data", create_data_media_path(uuid_, user).c_str()));
     }
 
-    clear_cache_files(data_path, cache, free_size);
+    clear_cache_files(data_path, cache, freeStorageSize);
     finish_cache_collection(cache);
 
-    return data_disk_free(data_path) >= free_size ? 0 : -1;
+    if (data_disk_free(data_path) >= freeStorageSize) {
+        return binder::Status::ok();
+    } else {
+        return binder::Status::fromServiceSpecificError(-1);
+    }
 }
 
-int rm_dex(const char *path, const char *instruction_set)
-{
+binder::Status InstalldNativeService::rmdex(const std::string& codePath,
+        const std::string& instructionSet) {
+    ENFORCE_UID(AID_SYSTEM);
     char dex_path[PKG_PATH_MAX];
 
+    const char* path = codePath.c_str();
+    const char* instruction_set = instructionSet.c_str();
+
     if (validate_apk_path(path) && validate_system_app_path(path)) {
         ALOGE("invalid apk path '%s' (bad prefix)\n", path);
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
-    if (!create_cache_path(dex_path, path, instruction_set)) return -1;
+    if (!create_cache_path(dex_path, path, instruction_set)) {
+        return binder::Status::fromServiceSpecificError(-1);
+    }
 
     ALOGV("unlink %s\n", dex_path);
     if (unlink(dex_path) < 0) {
         if (errno != ENOENT) {
             ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
         }
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     } else {
-        return 0;
+        return binder::Status::ok();
     }
 }
 
@@ -708,12 +823,18 @@
     return 0;
 }
 
-int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
+binder::Status InstalldNativeService::getAppDataInode(const std::unique_ptr<std::string>& uuid,
+    const std::string& packageName, int32_t userId, int32_t flags, int64_t* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+
+    int res = 0;
     if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
-        return get_path_inode(path, inode);
+        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
+        res = get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return));
     }
-    return -1;
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
 static int split_count(const char *str)
@@ -1385,7 +1506,13 @@
 
 // Dumps the contents of a profile file, using pkgname's dex files for pretty
 // printing the result.
-bool dump_profile(uid_t uid, const char* pkgname, const char* code_path_string) {
+binder::Status InstalldNativeService::dumpProfiles(int32_t uid, const std::string& packageName,
+        const std::string& codePaths, bool* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+
+    const char* pkgname = packageName.c_str();
+    const char* code_path_string = codePaths.c_str();
+
     std::vector<fd_t> profile_fds;
     fd_t reference_profile_fd = -1;
     std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname);
@@ -1399,13 +1526,15 @@
 
     if (!has_reference_profile && !has_profiles) {
         ALOGE("profman dump: no profiles to dump for '%s'", pkgname);
-        return false;
+        *_aidl_return = false;
+        return binder::Status::ok();
     }
 
     fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW);
     if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
         ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
-        return false;
+        *_aidl_return = false;
+        return binder::Status::ok();
     }
     std::vector<std::string> code_full_paths = base::Split(code_path_string, ";");
     std::vector<std::string> dex_locations;
@@ -1415,7 +1544,8 @@
         fd_t apk_fd = open(full_path, O_RDONLY | O_NOFOLLOW);
         if (apk_fd == -1) {
             ALOGE("installd cannot open '%s'\n", full_path);
-            return false;
+            *_aidl_return = false;
+            return binder::Status::ok();
         }
         dex_locations.push_back(get_location_from_path(full_path));
         apk_fds.push_back(apk_fd);
@@ -1439,9 +1569,11 @@
     if (!WIFEXITED(return_code)) {
         LOG(WARNING) << "profman failed for package " << pkgname << ": "
                 << return_code;
-        return false;
+        *_aidl_return = false;
+        return binder::Status::ok();
     }
-    return true;
+    *_aidl_return = true;
+    return binder::Status::ok();
 }
 
 static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
@@ -1548,8 +1680,12 @@
 }
 
 // TODO: Consider returning error codes.
-bool merge_profiles(uid_t uid, const char *pkgname) {
-    return analyse_profiles(uid, pkgname);
+binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::string& packageName,
+    bool* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* pkgname = packageName.c_str();
+    *_aidl_return = analyse_profiles(uid, pkgname);
+    return binder::Status::ok();
 }
 
 static const char* parse_null(const char* arg) {
@@ -1924,23 +2060,23 @@
     return 0;
 }
 
-int mark_boot_complete(const char* instruction_set)
-{
-  char boot_marker_path[PKG_PATH_MAX];
-  sprintf(boot_marker_path,
+binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* instruction_set = instructionSet.c_str();
+
+    char boot_marker_path[PKG_PATH_MAX];
+    sprintf(boot_marker_path,
           "%s/%s/%s/.booting",
           android_data_dir.path,
           DALVIK_CACHE,
           instruction_set);
 
-  ALOGV("mark_boot_complete : %s", boot_marker_path);
-  if (unlink(boot_marker_path) != 0) {
-      ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path,
-            strerror(errno));
-      return -1;
-  }
-
-  return 0;
+    ALOGV("mark_boot_complete : %s", boot_marker_path);
+    if (unlink(boot_marker_path) != 0) {
+        ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path, strerror(errno));
+        return binder::Status::fromServiceSpecificError(-1);
+    }
+    return binder::Status::ok();
 }
 
 void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
@@ -1964,22 +2100,29 @@
     }
 }
 
-int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId)
-{
+binder::Status InstalldNativeService::linkNativeLibraryDirectory(
+        const std::unique_ptr<std::string>& uuid, const std::string& packageName,
+        const std::string& nativeLibPath32, int32_t userId) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgname = packageName.c_str();
+    const char* asecLibDir = nativeLibPath32.c_str();
     struct stat s, libStat;
     int rc = 0;
 
-    std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
+    std::string _pkgdir(create_data_user_ce_package_path(uuid_, userId, pkgname));
     std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
 
     const char* pkgdir = _pkgdir.c_str();
     const char* libsymlink = _libsymlink.c_str();
 
-    if (stat(pkgdir, &s) < 0) return -1;
+    if (stat(pkgdir, &s) < 0) {
+        return binder::Status::fromServiceSpecificError(-1);
+    }
 
     if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
         ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
     if (chmod(pkgdir, 0700) < 0) {
@@ -2024,10 +2167,10 @@
 
     if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
         ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
-        return -errno;
+        rc = -errno;
     }
 
-    return rc;
+    return rc ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
 static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
@@ -2077,8 +2220,11 @@
     return 0;
 }
 
-int idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
-{
+binder::Status InstalldNativeService::idmap(const std::string& targetApkPath,
+        const std::string& overlayApkPath, int32_t uid) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* target_apk = targetApkPath.c_str();
+    const char* overlay_apk = overlayApkPath.c_str();
     ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
 
     int idmap_fd = -1;
@@ -2133,78 +2279,93 @@
     }
 
     close(idmap_fd);
-    return 0;
+    return binder::Status::ok();
 fail:
     if (idmap_fd >= 0) {
         close(idmap_fd);
         unlink(idmap_path);
     }
-    return -1;
+    return binder::Status::fromServiceSpecificError(-1);
 }
 
-int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
-        appid_t appid, const char* seinfo) {
+binder::Status InstalldNativeService::restoreconAppData(const std::unique_ptr<std::string>& uuid,
+        const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
+        const std::string& seInfo) {
+    ENFORCE_UID(AID_SYSTEM);
     int res = 0;
 
     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
     unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+    const char* pkgName = packageName.c_str();
+    const char* seinfo = seInfo.c_str();
 
     if (!pkgName || !seinfo) {
         ALOGE("Package name or seinfo tag is null when trying to restorecon.");
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
-    uid_t uid = multiuser_get_uid(userid, appid);
+    uid_t uid = multiuser_get_uid(userId, appId);
     if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
+        auto path = create_data_user_ce_package_path(uuid_, userId, pkgName);
         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
             PLOG(ERROR) << "restorecon failed for " << path;
             res = -1;
         }
     }
     if (flags & FLAG_STORAGE_DE) {
-        auto path = create_data_user_de_package_path(uuid, userid, pkgName);
+        auto path = create_data_user_de_package_path(uuid_, userId, pkgName);
         if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
             PLOG(ERROR) << "restorecon failed for " << path;
             // TODO: include result once 25796509 is fixed
         }
     }
-
-    return res;
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
-int create_oat_dir(const char* oat_dir, const char* instruction_set)
-{
+binder::Status InstalldNativeService::createOatDir(const std::string& oatDir,
+        const std::string& instructionSet) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* oat_dir = oatDir.c_str();
+    const char* instruction_set = instructionSet.c_str();
     char oat_instr_dir[PKG_PATH_MAX];
 
     if (validate_apk_path(oat_dir)) {
         ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
     if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
     if (selinux_android_restorecon(oat_dir, 0)) {
         ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
     snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
     if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
-    return 0;
+    return binder::Status::ok();
 }
 
-int rm_package_dir(const char* apk_path)
-{
+binder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* apk_path = packageDir.c_str();
     if (validate_apk_path(apk_path)) {
         ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
-    return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
+    int res = delete_dir_contents(apk_path, 1 /* also_delete_dir */,
+            NULL /* exclusion_predicate */);
+    return res ? binder::Status::fromServiceSpecificError(-1) : binder::Status::ok();
 }
 
-int link_file(const char* relative_path, const char* from_base, const char* to_base) {
+binder::Status InstalldNativeService::linkFile(const std::string& relativePath,
+        const std::string& fromBase, const std::string& toBase) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* relative_path = relativePath.c_str();
+    const char* from_base = fromBase.c_str();
+    const char* to_base = toBase.c_str();
     char from_path[PKG_PATH_MAX];
     char to_path[PKG_PATH_MAX];
     snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path);
@@ -2212,21 +2373,21 @@
 
     if (validate_apk_path_subdirs(from_path)) {
         ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path);
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
     if (validate_apk_path_subdirs(to_path)) {
         ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path);
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
     const int ret = link(from_path, to_path);
     if (ret < 0) {
         ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno));
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
-    return 0;
+    return binder::Status::ok();
 }
 
 // Helper for move_ab, so that we can have common failure-case cleanup.
@@ -2287,40 +2448,42 @@
     return true;
 }
 
-int move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
-    if (apk_path == nullptr || instruction_set == nullptr || oat_dir == nullptr) {
-        LOG(ERROR) << "Cannot move_ab with null input";
-        return -1;
-    }
+//int move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
+binder::Status InstalldNativeService::moveAb(const std::string& apkPath,
+        const std::string& instructionSet, const std::string& outputPath) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* apk_path = apkPath.c_str();
+    const char* instruction_set = instructionSet.c_str();
+    const char* oat_dir = outputPath.c_str();
 
     // Get the current slot suffix. No suffix, no A/B.
     std::string slot_suffix;
     {
         char buf[kPropertyValueMax];
         if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
         slot_suffix = buf;
 
         if (!ValidateTargetSlotSuffix(slot_suffix)) {
             LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
-            return -1;
+            return binder::Status::fromServiceSpecificError(-1);
         }
     }
 
     // Validate other inputs.
     if (validate_apk_path(apk_path) != 0) {
         LOG(ERROR) << "invalid apk_path " << apk_path;
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
     if (validate_apk_path(oat_dir) != 0) {
         LOG(ERROR) << "invalid oat_dir " << oat_dir;
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
     char a_path[PKG_PATH_MAX];
     if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
-        return -1;
+        return binder::Status::fromServiceSpecificError(-1);
     }
     const std::string a_vdex_path = create_vdex_filename(a_path);
     const std::string a_image_path = create_image_filename(a_path);
@@ -2360,14 +2523,20 @@
         success = false;
     }
 
-    return success ? 0 : -1;
+    return success ? binder::Status::ok() : binder::Status::fromServiceSpecificError(-1);
 }
 
-bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir) {
+binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
+        const std::string& instructionSet, const std::string& outputPath) {
+    ENFORCE_UID(AID_SYSTEM);
+    const char* apk_path = apkPath.c_str();
+    const char* instruction_set = instructionSet.c_str();
+    const char* oat_dir = outputPath.c_str();
+
     // Delete the oat/odex file.
     char out_path[PKG_PATH_MAX];
     if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) {
-        return false;
+        return binder::Status::fromServiceSpecificError(-1);
     }
 
     // In case of a permission failure report the issue. Otherwise just print a warning.
@@ -2390,7 +2559,8 @@
     bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
 
     // Report success.
-    return return_value_oat && return_value_art;
+    bool success = return_value_oat && return_value_art;
+    return success ? binder::Status::ok() : binder::Status::fromServiceSpecificError(-1);
 }
 
 }  // namespace installd
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index ba27517..a54d980 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -21,42 +21,70 @@
 #include <inttypes.h>
 #include <unistd.h>
 
+#include <vector>
+
+#include <binder/BinderService.h>
 #include <cutils/multiuser.h>
 
-#include <installd_constants.h>
+#include "android/os/BnInstalld.h"
+#include "installd_constants.h"
 
 namespace android {
 namespace installd {
 
-static constexpr size_t DEXOPT_PARAM_COUNT = 10U;
+class InstalldNativeService : public BinderService<InstalldNativeService>, public os::BnInstalld {
+public:
+    static status_t start();
+    static char const* getServiceName() { return "installd"; }
+    virtual status_t dump(int fd, const Vector<String16> &args) override;
 
-int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        appid_t appid, const char* seinfo, int target_sdk_version);
-int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
-        appid_t appid, const char* seinfo);
-int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
-int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        ino_t ce_data_inode);
-int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        ino_t ce_data_inode);
+    binder::Status createUserData(const std::unique_ptr<std::string>& uuid, int32_t userId,
+            int32_t userSerial, int32_t flags);
+    binder::Status destroyUserData(const std::unique_ptr<std::string>& uuid, int32_t userId,
+            int32_t flags);
 
-int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
-        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
+    binder::Status createAppData(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
+            const std::string& seInfo, int32_t targetSdkVersion);
+    binder::Status restoreconAppData(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
+            const std::string& seInfo);
+    binder::Status migrateAppData(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags);
+    binder::Status clearAppData(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
+    binder::Status destroyAppData(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
+    binder::Status getAppDataInode(const std::unique_ptr<std::string>& uuid,
+            const std::string& packageName, int32_t userId, int32_t flags, int64_t* _aidl_return);
+
+    binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
+            const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
+            const std::string& dataAppName, int32_t appId, const std::string& seInfo,
+            int32_t targetSdkVersion);
+
+    binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
+
+    binder::Status mergeProfiles(int32_t uid, const std::string& packageName, bool* _aidl_return);
+    binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
+            const std::string& codePaths, bool* _aidl_return);
+    binder::Status clearAppProfiles(const std::string& packageName);
+    binder::Status destroyAppProfiles(const std::string& packageName);
+
+    binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath, int32_t uid);
+    binder::Status rmPackageDir(const std::string& packageDir);
+    binder::Status markBootComplete(const std::string& instructionSet);
+    binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize);
+    binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid, const std::string& packageName, const std::string& nativeLibPath32, int32_t userId);
+    binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet);
+    binder::Status linkFile(const std::string& relativePath, const std::string& fromBase, const std::string& toBase);
+    binder::Status moveAb(const std::string& apkPath, const std::string& instructionSet, const std::string& outputPath);
+    binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet, const std::string& outputPath);
+};
 
 int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
         const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
         int64_t *asecsize);
-int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
-
-int create_user_data(const char *uuid, userid_t userid, int user_serial, int flags);
-int destroy_user_data(const char *uuid, userid_t userid, int flags);
-
-int rm_dex(const char *path, const char *instruction_set);
-int free_cache(const char *uuid, int64_t free_size);
-
-bool merge_profiles(uid_t uid, const char *pkgname);
-
-bool dump_profile(uid_t uid, const char *pkgname, const char *dex_files);
 
 int dexopt(const char *apk_path,
            uid_t uid,
@@ -73,21 +101,6 @@
 // Helper for the above, converting arguments.
 int dexopt(const char* const params[DEXOPT_PARAM_COUNT]);
 
-int mark_boot_complete(const char *instruction_set);
-int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
-int idmap(const char *target_path, const char *overlay_path, uid_t uid);
-int create_oat_dir(const char* oat_dir, const char *instruction_set);
-int rm_package_dir(const char* apk_path);
-int clear_app_profiles(const char* pkgname);
-int destroy_app_profiles(const char* pkgname);
-int link_file(const char *relative_path, const char *from_base, const char *to_base);
-
-// Move a B version over to the A location. Only works for oat_dir != nullptr.
-int move_ab(const char *apk_path, const char *instruction_set, const char* oat_dir);
-
-// Delete odex files generated by dexopt.
-bool delete_odex(const char *apk_path, const char *instruction_set, const char *oat_dir);
-
 }  // namespace installd
 }  // namespace android
 
diff --git a/cmds/installd/globals.h b/cmds/installd/globals.h
index c90beec..fc502c0 100644
--- a/cmds/installd/globals.h
+++ b/cmds/installd/globals.h
@@ -18,6 +18,7 @@
 #ifndef GLOBALS_H_
 #define GLOBALS_H_
 
+#include <commands.h>
 #include <inttypes.h>
 
 namespace android {
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index c81a339..ef92a69 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -188,34 +188,6 @@
     return 0;
 }
 
-static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char *uuid, const char *pkgname, userid_t userid, int flags,
-            appid_t appid, const char* seinfo, int target_sdk_version */
-    return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]),
-                           atoi(arg[4]), arg[5], atoi(arg[6]));
-}
-
-static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char* uuid, const char* pkgName, userid_t userid, int flags,
-            appid_t appid, const char* seinfo */
-    return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]);
-}
-
-static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char *uuid, const char *pkgname, userid_t userid, int flags */
-    return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
-}
-
-static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
-    return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
-}
-
-static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
-    return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
-}
-
 // We use otapreopt_chroot to get into the chroot.
 static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot";
 
@@ -281,46 +253,6 @@
     return dexopt_fn(args, reply);
 }
 
-static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
-{
-    uid_t uid = static_cast<uid_t>(atoi(arg[0]));
-    const char* pkgname = arg[1];
-    if (merge_profiles(uid, pkgname)) {
-        strncpy(reply, "true", REPLY_MAX);
-    } else {
-        strncpy(reply, "false", REPLY_MAX);
-    }
-    return 0;
-}
-
-static int do_dump_profiles(char **arg, char reply[REPLY_MAX])
-{
-    uid_t uid = static_cast<uid_t>(atoi(arg[0]));
-    const char* pkgname = arg[1];
-    const char* dex_files = arg[2];
-    if (dump_profile(uid, pkgname, dex_files)) {
-        strncpy(reply, "true", REPLY_MAX);
-    } else {
-        strncpy(reply, "false", REPLY_MAX);
-    }
-    return 0;
-}
-
-static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    return mark_boot_complete(arg[0] /* instruction set */);
-}
-
-static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
-}
-
-static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
-{
-    return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
-}
-
 static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
     int64_t codesize = 0;
     int64_t datasize = 0;
@@ -342,87 +274,6 @@
     return res;
 }
 
-static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
-    ino_t inode = 0;
-    int res = 0;
-
-    /* const char *uuid, const char *pkgname, int userid, int flags */
-    res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
-
-    snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
-    return res;
-}
-
-static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    /* const char* from_uuid, const char *to_uuid, const char *package_name,
-            const char *data_app_name, appid_t appid, const char* seinfo,
-            int target_sdk_version */
-    return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
-                             atoi(arg[4]), arg[5], atoi(arg[6]));
-}
-
-static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* const char *uuid, userid_t userid, int user_serial, int flags */
-    return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
-}
-
-static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* const char *uuid, userid_t userid, int flags */
-    return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
-}
-
-static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
-}
-
-static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    return idmap(arg[0], arg[1], atoi(arg[2]));
-}
-
-static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* oat_dir, instruction_set */
-    return create_oat_dir(arg[0], arg[1]);
-}
-
-static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* oat_dir */
-    return rm_package_dir(arg[0]);
-}
-
-static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* package_name */
-    return clear_app_profiles(arg[0]);
-}
-
-static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* package_name */
-    return destroy_app_profiles(arg[0]);
-}
-
-static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
-{
-    /* relative_path, from_base, to_base */
-    return link_file(arg[0], arg[1], arg[2]);
-}
-
-static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    // apk_path, instruction_set, oat_dir
-    return move_ab(arg[0], arg[1], arg[2]);
-}
-
-static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
-    // apk_path, instruction_set, oat_dir
-    return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1;
-}
-
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -431,34 +282,8 @@
 
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
-
-    { "create_app_data",      7, do_create_app_data },
-    { "restorecon_app_data",  6, do_restorecon_app_data },
-    { "migrate_app_data",     4, do_migrate_app_data },
-    { "clear_app_data",       5, do_clear_app_data },
-    { "destroy_app_data",     5, do_destroy_app_data },
-    { "move_complete_app",    7, do_move_complete_app },
     { "get_app_size",         6, do_get_app_size },
-    { "get_app_data_inode",   4, do_get_app_data_inode },
-
-    { "create_user_data",     4, do_create_user_data },
-    { "destroy_user_data",    3, do_destroy_user_data },
-
     { "dexopt",              10, do_dexopt },
-    { "markbootcomplete",     1, do_mark_boot_complete },
-    { "rmdex",                2, do_rm_dex },
-    { "freecache",            2, do_free_cache },
-    { "linklib",              4, do_linklib },
-    { "idmap",                3, do_idmap },
-    { "createoatdir",         2, do_create_oat_dir },
-    { "rmpackagedir",         1, do_rm_package_dir },
-    { "clear_app_profiles",   1, do_clear_app_profiles },
-    { "destroy_app_profiles", 1, do_destroy_app_profiles },
-    { "linkfile",             3, do_link_file },
-    { "move_ab",              3, do_move_ab },
-    { "merge_profiles",       2, do_merge_profiles },
-    { "dump_profiles",        3, do_dump_profiles },
-    { "delete_odex",          3, do_delete_odex },
 };
 
 static int readx(int s, void *_buf, int count)
@@ -705,7 +530,7 @@
     char buf[BUFFER_MAX];
     struct sockaddr addr;
     socklen_t alen;
-    int lsocket, s;
+    int lsocket, s, ret;
     int selinux_enabled = (is_selinux_enabled() > 0);
 
     setenv("ANDROID_LOG_TAGS", "*:v", 1);
@@ -732,6 +557,11 @@
         exit(1);
     }
 
+    if ((ret = InstalldNativeService::start()) != android::OK) {
+        ALOGE("Unable to start InstalldNativeService: %d", ret);
+        exit(1);
+    }
+
     lsocket = android_get_control_socket(SOCKET_PATH);
     if (lsocket < 0) {
         ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index b0bcce9..4a6143f 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -30,6 +30,8 @@
 #define DALVIK_CACHE "dalvik-cache"
 constexpr const char* DALVIK_CACHE_POSTFIX = "@classes.dex";
 
+static constexpr size_t DEXOPT_PARAM_COUNT = 10U;
+
 constexpr size_t PKG_NAME_MAX = 128u;   /* largest allowed package name */
 constexpr size_t PKG_PATH_MAX = 256u;   /* max size of any path we use */
 
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 5ea89e6..924600a 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -25,8 +25,8 @@
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 
-#include <commands.h>
-#include <otapreopt_utils.h>
+#include "installd_constants.h"
+#include "otapreopt_utils.h"
 
 #ifndef LOG_TAG
 #define LOG_TAG "otapreopt"
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 447c8bd..a32df22 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -5,8 +5,8 @@
     srcs: ["installd_utils_test.cpp"],
     shared_libs: [
         "libbase",
-        "libutils",
         "liblog",
+        "libutils",
         "libcutils",
     ],
     static_libs: [
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 8123e9b..ead73fe 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -73,7 +73,6 @@
 std::string create_data_path(const char* volume_uuid);
 
 std::string create_data_app_path(const char* volume_uuid);
-
 std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
 
 std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h
index be72d44..0f1fe5b 100644
--- a/include/binder/IInterface.h
+++ b/include/binder/IInterface.h
@@ -72,24 +72,24 @@
 // ----------------------------------------------------------------------
 
 #define DECLARE_META_INTERFACE(INTERFACE)                               \
-    static const android::String16 descriptor;                          \
-    static android::sp<I##INTERFACE> asInterface(                       \
-            const android::sp<android::IBinder>& obj);                  \
-    virtual const android::String16& getInterfaceDescriptor() const;    \
+    static const ::android::String16 descriptor;                        \
+    static ::android::sp<I##INTERFACE> asInterface(                     \
+            const ::android::sp<::android::IBinder>& obj);              \
+    virtual const ::android::String16& getInterfaceDescriptor() const;  \
     I##INTERFACE();                                                     \
     virtual ~I##INTERFACE();                                            \
 
 
 #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
-    const android::String16 I##INTERFACE::descriptor(NAME);             \
-    const android::String16&                                            \
+    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
+    const ::android::String16&                                          \
             I##INTERFACE::getInterfaceDescriptor() const {              \
         return I##INTERFACE::descriptor;                                \
     }                                                                   \
-    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
-            const android::sp<android::IBinder>& obj)                   \
+    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
+            const ::android::sp<::android::IBinder>& obj)               \
     {                                                                   \
-        android::sp<I##INTERFACE> intr;                                 \
+        ::android::sp<I##INTERFACE> intr;                               \
         if (obj != NULL) {                                              \
             intr = static_cast<I##INTERFACE*>(                          \
                 obj->queryLocalInterface(                               \
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 2062b3b..3aeff2e 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -135,10 +135,12 @@
     {
         unsigned n;
         for (n = 0; n < 5; n++){
+            if (n > 0) {
+                ALOGI("Waiting for service %s...", String8(name).string());
+                sleep(1);
+            }
             sp<IBinder> svc = checkService(name);
             if (svc != NULL) return svc;
-            ALOGI("Waiting for service %s...\n", String8(name).string());
-            sleep(1);
         }
         return NULL;
     }
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 6caf076..e8691bb 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -985,6 +985,7 @@
         boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
                                              && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
                                                  || (cfunc.hasPointerArg() && numArrays > 0))
+                                         || (numBufferArgs > 0)
                                          || hasCheckTest(cfunc)
                                          || hasIfTest(cfunc))
                                          || (stringArgs.size() > 0);
@@ -1308,6 +1309,8 @@
 
                     out.println();
                 } else if (jfunc.getArgType(idx).isBuffer()) {
+                    needsExit = needsExit || (!nullAllowed && !isPointerFunc);
+
                     String array = numBufferArgs <= 1 ? "_array" :
                         "_" + cfunc.getArgName(cIndex) + "Array";
                     String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
@@ -1318,6 +1321,17 @@
                         out.println(indent + "if (" + cname + "_buf) {");
                         out.print(indent);
                     }
+                    else
+                    {
+                        out.println(indent + "if (!" + cname + "_buf) {");
+                        out.println(indent + indent + "_exception = 1;");
+                        out.println(indent + indent + "_exceptionType = " +
+                                "\"java/lang/IllegalArgumentException\";");
+                        out.println(indent + indent + "_exceptionMessage = \"" +
+                                cname +" == null\";");
+                        out.println(indent + indent + "goto exit;");
+                        out.println(indent + "}");
+                    }
 
                     if (isPointerFunc) {
                         out.println(indent +
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp
new file mode 100644
index 0000000..3eacf3c
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.cpp
@@ -0,0 +1,9 @@
+/* EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list ) */
+static jobject
+android_eglCreatePixmapSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jint pixmap, jintArray attrib_list_ref, jint offset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
+        "eglCreatePixmapSurface");
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, (EGLSurface) 0);
+}
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.java b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.java
index bc6740e..1750b32 100644
--- a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.java
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.java
@@ -7,4 +7,5 @@
         int pixmap,
         int[] attrib_list,
         int offset
-    );
\ No newline at end of file
+    );
+
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.nativeReg
new file mode 100644
index 0000000..fa260d8
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePixmapSurface.nativeReg
@@ -0,0 +1 @@
+{"eglCreatePixmapSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;I[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePixmapSurface },
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 18c7945..61c231d 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -205,7 +205,7 @@
 void FramebufferSurface::onFrameCommitted() {
 #ifdef USE_HWC2
     if (mHasPendingRelease) {
-        sp<Fence> fence = mHwc.getRetireFence(mDisplayType);
+        sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
         if (fence->isValid()) {
             status_t result = addReleaseFence(mPreviousBufferSlot,
                     mPreviousBuffer, fence);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 31af8a1..dd909aa 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -924,21 +924,21 @@
     return Error::None;
 }
 
-Error Display::present(sp<Fence>* outRetireFence)
+Error Display::present(sp<Fence>* outPresentFence)
 {
-    int32_t retireFenceFd = 0;
+    int32_t presentFenceFd = 0;
 #ifdef BYPASS_IHWC
     int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
-            &retireFenceFd);
+            &presentFenceFd);
 #else
-    auto intError = mDevice.mComposer->presentDisplay(mId, retireFenceFd);
+    auto intError = mDevice.mComposer->presentDisplay(mId, presentFenceFd);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
     }
 
-    *outRetireFence = new Fence(retireFenceFd);
+    *outPresentFence = new Fence(presentFenceFd);
     return Error::None;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 1c709b2..33fb8cb 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -313,7 +313,7 @@
             std::unordered_map<std::shared_ptr<Layer>,
                     android::sp<android::Fence>>* outFences) const;
     [[clang::warn_unused_result]] Error present(
-            android::sp<android::Fence>* outRetireFence);
+            android::sp<android::Fence>* outPresentFence);
     [[clang::warn_unused_result]] Error setActiveConfig(
             const std::shared_ptr<const Config>& config);
     [[clang::warn_unused_result]] Error setClientTarget(
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d590649..c82b0c4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -594,12 +594,12 @@
     return mDisplayData[displayId].hasClientComposition;
 }
 
-sp<Fence> HWComposer::getRetireFence(int32_t displayId) const {
+sp<Fence> HWComposer::getPresentFence(int32_t displayId) const {
     if (!isValidDisplay(displayId)) {
-        ALOGE("getRetireFence failed for invalid display %d", displayId);
+        ALOGE("getPresentFence failed for invalid display %d", displayId);
         return Fence::NO_FENCE;
     }
-    return mDisplayData[displayId].lastRetireFence;
+    return mDisplayData[displayId].lastPresentFence;
 }
 
 bool HWComposer::retireFenceRepresentsStartOfScanout() const {
@@ -629,7 +629,7 @@
 
     auto& displayData = mDisplayData[displayId];
     auto& hwcDisplay = displayData.hwcDisplay;
-    auto error = hwcDisplay->present(&displayData.lastRetireFence);
+    auto error = hwcDisplay->present(&displayData.lastPresentFence);
     if (error != HWC2::Error::None) {
         ALOGE("presentAndGetReleaseFences: failed for display %d: %s (%d)",
               displayId, to_string(error).c_str(), static_cast<int32_t>(error));
@@ -879,7 +879,7 @@
   : hasClientComposition(false),
     hasDeviceComposition(false),
     hwcDisplay(),
-    lastRetireFence(Fence::NO_FENCE),
+    lastPresentFence(Fence::NO_FENCE),
     outbufHandle(nullptr),
     outbufAcquireFence(Fence::NO_FENCE),
     vsyncEnabled(HWC2::Vsync::Disable) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index e6f1b25..e63bdd4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -118,9 +118,8 @@
     // does this display have layers handled by GLES
     bool hasClientComposition(int32_t displayId) const;
 
-    // get the retire fence for the previous frame (i.e., corresponding to the
-    // last call to presentDisplay
-    sp<Fence> getRetireFence(int32_t displayId) const;
+    // get the present fence received from the last call to present.
+    sp<Fence> getPresentFence(int32_t displayId) const;
 
     // Returns true if the retire fence represents the start of the display
     // controller's scan out. This should be true for all HWC2 implementations,
@@ -191,7 +190,7 @@
         bool hasDeviceComposition;
         std::shared_ptr<HWC2::Display> hwcDisplay;
         HWC2::DisplayRequest displayRequests;
-        sp<Fence> lastRetireFence;  // signals when the last set op retires
+        sp<Fence> lastPresentFence;  // signals when the last set op retires
         std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
                 releaseFences;
         buffer_handle_t outbufHandle;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 9de74d6..0511df2 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -241,7 +241,7 @@
     mDbgState = DBG_STATE_IDLE;
 
 #ifdef USE_HWC2
-    sp<Fence> retireFence = mHwc.getRetireFence(mDisplayId);
+    sp<Fence> retireFence = mHwc.getPresentFence(mDisplayId);
 #else
     sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
 #endif
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2334e47..a42dd54 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -906,7 +906,7 @@
         // if not everything below us is covered, we plug the holes!
         Region holes(clip.subtract(under));
         if (!holes.isEmpty()) {
-            clearWithOpenGL(hw, holes, 0, 0, 0, 1);
+            clearWithOpenGL(hw, 0, 0, 0, 1);
         }
         return;
     }
@@ -978,7 +978,7 @@
 
 
 void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw,
-        const Region& /* clip */, float red, float green, float blue,
+        float red, float green, float blue,
         float alpha) const
 {
     RenderEngine& engine(mFlinger->getRenderEngine());
@@ -988,8 +988,8 @@
 }
 
 void Layer::clearWithOpenGL(
-        const sp<const DisplayDevice>& hw, const Region& clip) const {
-    clearWithOpenGL(hw, clip, 0,0,0,0);
+        const sp<const DisplayDevice>& hw) const {
+    clearWithOpenGL(hw, 0,0,0,0);
 }
 
 void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
@@ -1751,10 +1751,10 @@
         sp<Fence> presentFence = Fence::NO_FENCE;
         sp<Fence> presentOrRetireFence = Fence::NO_FENCE;
         if (hwc.retireFenceRepresentsStartOfScanout()) {
-            presentFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY);
+            presentFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
             presentOrRetireFence = presentFence;
         } else {
-            retireFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY);
+            retireFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
             presentOrRetireFence = retireFence;
         }
         bool wasGpuComposited = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index b4d8685..a051292 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -383,7 +383,7 @@
 #endif
     // -----------------------------------------------------------------------
 
-    void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
+    void clearWithOpenGL(const sp<const DisplayDevice>& hw) const;
     void setFiltering(bool filtering);
     bool getFiltering() const;
 
@@ -459,7 +459,7 @@
     static bool getOpacityForFormat(uint32_t format);
 
     // drawing
-    void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
+    void clearWithOpenGL(const sp<const DisplayDevice>& hw,
             float r, float g, float b, float alpha) const;
     void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
             bool useIdentityTransform) const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 91dd8a6..879959e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1117,7 +1117,7 @@
 }
 
 bool SurfaceFlinger::handleMessageTransaction() {
-    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
+    uint32_t transactionFlags = peekTransactionFlags();
     if (transactionFlags) {
         handleTransaction(transactionFlags);
         return true;
@@ -1142,7 +1142,7 @@
     doComposition();
     postComposition();
 
-    mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
+    mPreviousPresentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
 
     mHadClientComposition = false;
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
@@ -1242,7 +1242,7 @@
         }
     }
 
-    sp<Fence> presentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
+    sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
 
     if (presentFence->isValid()) {
         if (mPrimaryDispSync.addPresentFence(presentFence)) {
@@ -2069,14 +2069,15 @@
 }
 
 
-void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
+void SurfaceFlinger::doDisplayComposition(
+        const sp<const DisplayDevice>& displayDevice,
         const Region& inDirtyRegion)
 {
     // We only need to actually compose the display if:
     // 1) It is being handled by hardware composer, which may need this to
     //    keep its virtual display state machine in sync, or
     // 2) There is work to be done (the dirty region isn't empty)
-    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
+    bool isHwcDisplay = displayDevice->getHwcDisplayId() >= 0;
     if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
         ALOGV("Skipping display composition");
         return;
@@ -2087,35 +2088,35 @@
     Region dirtyRegion(inDirtyRegion);
 
     // compute the invalid region
-    hw->swapRegion.orSelf(dirtyRegion);
+    displayDevice->swapRegion.orSelf(dirtyRegion);
 
-    uint32_t flags = hw->getFlags();
+    uint32_t flags = displayDevice->getFlags();
     if (flags & DisplayDevice::SWAP_RECTANGLE) {
         // we can redraw only what's dirty, but since SWAP_RECTANGLE only
         // takes a rectangle, we must make sure to update that whole
         // rectangle in that case
-        dirtyRegion.set(hw->swapRegion.bounds());
+        dirtyRegion.set(displayDevice->swapRegion.bounds());
     } else {
         if (flags & DisplayDevice::PARTIAL_UPDATES) {
             // We need to redraw the rectangle that will be updated
             // (pushed to the framebuffer).
             // This is needed because PARTIAL_UPDATES only takes one
             // rectangle instead of a region (see DisplayDevice::flip())
-            dirtyRegion.set(hw->swapRegion.bounds());
+            dirtyRegion.set(displayDevice->swapRegion.bounds());
         } else {
             // we need to redraw everything (the whole screen)
-            dirtyRegion.set(hw->bounds());
-            hw->swapRegion = dirtyRegion;
+            dirtyRegion.set(displayDevice->bounds());
+            displayDevice->swapRegion = dirtyRegion;
         }
     }
 
-    if (!doComposeSurfaces(hw, dirtyRegion)) return;
+    if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
 
     // update the swap region and clear the dirty region
-    hw->swapRegion.orSelf(dirtyRegion);
+    displayDevice->swapRegion.orSelf(dirtyRegion);
 
     // swap buffers (presentation)
-    hw->swapBuffers(getHwComposer());
+    displayDevice->swapBuffers(getHwComposer());
 }
 
 bool SurfaceFlinger::doComposeSurfaces(
@@ -2223,7 +2224,7 @@
                                 && hasClientComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
-                            layer->clearWithOpenGL(displayDevice, clip);
+                            layer->clearWithOpenGL(displayDevice);
                         }
                         break;
                     }
@@ -2259,8 +2260,8 @@
     return true;
 }
 
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const {
-    const int32_t height = hw->getHeight();
+void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const {
+    const int32_t height = displayDevice->getHeight();
     RenderEngine& engine(getRenderEngine());
     engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
 }
@@ -2304,7 +2305,7 @@
     return status_t(index);
 }
 
-uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t /* flags */) {
+uint32_t SurfaceFlinger::peekTransactionFlags() {
     return android_atomic_release_load(&mTransactionFlags);
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5bf989b..4ec1a72 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -283,7 +283,7 @@
      * Transactions
      */
     uint32_t getTransactionFlags(uint32_t flags);
-    uint32_t peekTransactionFlags(uint32_t flags);
+    uint32_t peekTransactionFlags();
     uint32_t setTransactionFlags(uint32_t flags);
     void commitTransaction();
     uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
@@ -406,14 +406,14 @@
     void setUpHWComposer();
     void doComposition();
     void doDebugFlashRegions();
-    void doDisplayComposition(const sp<const DisplayDevice>& hw, const Region& dirtyRegion);
+    void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion);
 
     // compose surfaces for display hw. this fails if using GL and the surface
     // has been destroyed and is no longer valid.
-    bool doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty);
+    bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice, const Region& dirty);
 
     void postFramebuffer();
-    void drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const;
+    void drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const;
 
     /* ------------------------------------------------------------------------
      * Display management
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 66a3c42..55edc15 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1050,7 +1050,7 @@
 }
 
 bool SurfaceFlinger::handleMessageTransaction() {
-    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
+    uint32_t transactionFlags = peekTransactionFlags();
     if (transactionFlags) {
         handleTransaction(transactionFlags);
         return true;
@@ -2143,7 +2143,7 @@
                                 && hasGlesComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
-                            layer->clearWithOpenGL(hw, clip);
+                            layer->clearWithOpenGL(hw);
                         }
                         break;
                     }
@@ -2223,7 +2223,7 @@
     return status_t(index);
 }
 
-uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t /* flags */) {
+uint32_t SurfaceFlinger::peekTransactionFlags() {
     return android_atomic_release_load(&mTransactionFlags);
 }
 
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index d97cf5e..ba3cf79 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -20,6 +20,13 @@
     license: "include/vulkan/NOTICE",
 }
 
+cc_library_static {
+    name: "vulkan_headers",
+    export_include_dirs: ["include"],
+}
+
 subdirs = [
+    "nulldrv",
     "libvulkan",
+    "tools",
 ]
diff --git a/vulkan/Android.mk b/vulkan/Android.mk
deleted file mode 100644
index d125673..0000000
--- a/vulkan/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-named-subdir-makefiles, libvulkan nulldrv tools)
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5e3f4dd..5a0a93b 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -18,3 +18,62 @@
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
 }
+
+cc_library_shared {
+    name: "libvulkan",
+    clang: true,
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+
+    cflags: [
+        "-DLOG_TAG=\"vulkan\"",
+        "-DVK_USE_PLATFORM_ANDROID_KHR",
+        "-DVK_NO_PROTOTYPES",
+        "-fvisibility=hidden",
+        "-fstrict-aliasing",
+        "-Weverything",
+        "-Werror",
+        "-Wno-padded",
+        "-Wno-switch-enum",
+        "-Wno-undef",
+
+        //"-DLOG_NDEBUG=0",
+    ],
+
+    cppflags: [
+        "-std=c++14",
+        "-Wno-c99-extensions",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+        "-Wno-zero-length-array",
+    ],
+
+    srcs: [
+        "api.cpp",
+        "api_gen.cpp",
+        "debug_report.cpp",
+        "driver.cpp",
+        "driver_gen.cpp",
+        "layers_extensions.cpp",
+        "stubhal.cpp",
+        "swapchain.cpp",
+        "vulkan_loader_data.cpp",
+    ],
+
+    export_static_lib_headers: ["vulkan_headers"],
+    static_libs: [
+        "vulkan_headers",
+    ],
+    shared_libs: [
+        "libziparchive",
+        "libhardware",
+        "libsync",
+        "libbase",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libz",
+    ],
+}
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
deleted file mode 100644
index f1155ca..0000000
--- a/vulkan/libvulkan/Android.mk
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-
-LOCAL_CFLAGS := -DLOG_TAG=\"vulkan\" \
-	-DVK_USE_PLATFORM_ANDROID_KHR \
-	-DVK_NO_PROTOTYPES \
-	-std=c99 -fvisibility=hidden -fstrict-aliasing \
-	-Weverything -Werror \
-	-Wno-padded \
-	-Wno-switch-enum \
-	-Wno-undef
-
-#LOCAL_CFLAGS += -DLOG_NDEBUG=0
-LOCAL_CPPFLAGS := -std=c++14 \
-	-Wno-c99-extensions \
-	-Wno-c++98-compat-pedantic \
-	-Wno-exit-time-destructors \
-	-Wno-global-constructors \
-	-Wno-zero-length-array
-
-LOCAL_C_INCLUDES := \
-	frameworks/native/vulkan/include \
-	system/core/libsync/include
-
-LOCAL_SRC_FILES := \
-	api.cpp \
-	api_gen.cpp \
-	debug_report.cpp \
-	driver.cpp \
-	driver_gen.cpp \
-	layers_extensions.cpp \
-	stubhal.cpp \
-	swapchain.cpp \
-	vulkan_loader_data.cpp
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_STATIC_LIBRARIES := libziparchive
-LOCAL_SHARED_LIBRARIES := libhardware libsync libbase liblog libutils libcutils libz
-
-LOCAL_MODULE := libvulkan
-include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
new file mode 100644
index 0000000..ea3b781
--- /dev/null
+++ b/vulkan/nulldrv/Android.bp
@@ -0,0 +1,47 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    // Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
+    name: "vulkan.default",
+    proprietary: true,
+    relative_install_path: "hw",
+
+    clang: true,
+    cflags: [
+        "-fvisibility=hidden",
+        "-fstrict-aliasing",
+        "-DLOG_TAG=\"vknulldrv\"",
+        "-Weverything",
+        "-Werror",
+        "-Wno-padded",
+        "-Wno-undef",
+        "-Wno-zero-length-array",
+
+        "-DLOG_NDEBUG=0",
+    ],
+    cppflags: [
+        "-std=c++1y",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-c99-extensions",
+    ],
+
+    srcs: [
+        "null_driver.cpp",
+        "null_driver_gen.cpp",
+    ],
+
+    static_libs: ["vulkan_headers"],
+    shared_libs: ["liblog"],
+}
diff --git a/vulkan/nulldrv/Android.mk b/vulkan/nulldrv/Android.mk
deleted file mode 100644
index 77d4746..0000000
--- a/vulkan/nulldrv/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing \
-	-DLOG_TAG=\"vknulldrv\" \
-	-Weverything -Werror \
-	-Wno-padded \
-	-Wno-undef \
-	-Wno-zero-length-array
-#LOCAL_CFLAGS += -DLOG_NDEBUG=0
-LOCAL_CPPFLAGS := -std=c++1y \
-	-Wno-c++98-compat-pedantic \
-	-Wno-c99-extensions
-
-LOCAL_C_INCLUDES := \
-	frameworks/native/vulkan/include
-
-LOCAL_SRC_FILES := \
-	null_driver.cpp \
-	null_driver_gen.cpp
-
-LOCAL_SHARED_LIBRARIES := liblog
-
-# Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE := vulkan.default
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/tools/Android.bp b/vulkan/tools/Android.bp
new file mode 100644
index 0000000..d81d9ec
--- /dev/null
+++ b/vulkan/tools/Android.bp
@@ -0,0 +1,44 @@
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+    name: "vkinfo",
+
+    clang: true,
+    cflags: [
+        "-fvisibility=hidden",
+        "-fstrict-aliasing",
+
+        "-DLOG_TAG=\"vkinfo\"",
+
+        "-Weverything",
+        "-Werror",
+        "-Wno-padded",
+        "-Wno-undef",
+        "-Wno-switch-enum",
+    ],
+    cppflags: [
+        "-std=c++1y",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-c99-extensions",
+        "-Wno-old-style-cast",
+    ],
+
+    srcs: ["vkinfo.cpp"],
+
+    shared_libs: [
+        "libvulkan",
+        "liblog",
+    ],
+}
diff --git a/vulkan/tools/Android.mk b/vulkan/tools/Android.mk
deleted file mode 100644
index 337e683..0000000
--- a/vulkan/tools/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
-LOCAL_CFLAGS += -DLOG_TAG=\"vkinfo\"
-LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef -Wno-switch-enum
-LOCAL_CPPFLAGS := -std=c++1y \
-	-Wno-c++98-compat-pedantic \
-	-Wno-c99-extensions \
-	-Wno-old-style-cast
-
-LOCAL_C_INCLUDES := \
-	frameworks/native/vulkan/include
-
-LOCAL_SRC_FILES := vkinfo.cpp
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_SHARED_LIBRARIES := libvulkan liblog
-
-LOCAL_MODULE := vkinfo
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)