Merge "Bugreport: Adding eBPF maps content to bugreport"
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
new file mode 100644
index 0000000..3de5c79
--- /dev/null
+++ b/cmds/installd/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+  "presubmit": [
+    {
+      "name": "installd_cache_test"
+    },
+    {
+      "name": "installd_dexopt_test"
+    },
+    {
+      "name": "installd_otapreopt_test"
+    },
+    {
+      "name": "installd_service_test"
+    },
+    {
+      "name": "installd_utils_test"
+    }
+  ]
+}
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 279bce8..f216c53 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -84,10 +84,16 @@
     system(cmd.c_str());
 }
 
-static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
-    ::mkdir(path.c_str(), mode);
-    ::chown(path.c_str(), owner, group);
-    ::chmod(path.c_str(), mode);
+static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
+    int ret = ::mkdir(path.c_str(), mode);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = ::chown(path.c_str(), owner, group);
+    if (ret != 0) {
+        return ret;
+    }
+    return ::chmod(path.c_str(), mode);
 }
 
 static int log_callback(int type, const char *fmt, ...) { // NOLINT
@@ -184,7 +190,7 @@
         se_info_ = "default";
         app_apk_dir_ = android_app_dir + package_name_;
 
-        create_mock_app();
+        ASSERT_TRUE(create_mock_app());
     }
 
     virtual void TearDown() {
@@ -198,33 +204,56 @@
         delete service_;
     }
 
-    void create_mock_app() {
+    ::testing::AssertionResult create_mock_app() {
         // Create the oat dir.
         app_oat_dir_ = app_apk_dir_ + "/oat";
-        mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
-        service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+        if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0) {
+            return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
+                                                 << " : " << strerror(errno);
+        }
+        binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not create oat dir: "
+                                                 << status.toString8().c_str();
+        }
 
         // Copy the primary apk.
         apk_path_ = app_apk_dir_ + "/base.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644));
+        std::string error_msg;
+        if (!WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644, &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to " << apk_path_
+                                                 << " : " << error_msg;
+        }
 
         // Create the app user data.
-        ASSERT_TRUE(service_->createAppData(
-            volume_uuid_,
-            package_name_,
-            kTestUserId,
-            kAppDataFlags,
-            kTestAppUid,
-            se_info_,
-            kOSdkVersion,
-            &ce_data_inode_).isOk());
+        status = service_->createAppData(
+                volume_uuid_,
+                package_name_,
+                kTestUserId,
+                kAppDataFlags,
+                kTestAppUid,
+                se_info_,
+                kOSdkVersion,
+                &ce_data_inode_);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not create app data: "
+                                                 << status.toString8().c_str();
+        }
 
         // Create a secondary dex file on CE storage
         const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
         app_private_dir_ce_ = create_data_user_ce_package_path(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
+        if (!WriteBase64ToFile(kDexFile,
+                               secondary_dex_ce_,
+                               kTestAppUid,
+                               kTestAppGid,
+                               0600,
+                               &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to "
+                                                 << secondary_dex_ce_ << " : " << error_msg;
+        }
         std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
@@ -233,10 +262,24 @@
         app_private_dir_de_ = create_data_user_de_package_path(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
+        if (!WriteBase64ToFile(kDexFile,
+                               secondary_dex_de_,
+                               kTestAppUid,
+                               kTestAppGid,
+                               0600,
+                               &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to "
+                                                 << secondary_dex_de_ << " : " << error_msg;
+        }
 
         // Fix app data uid.
-        ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
+        status = service_->fixupAppData(volume_uuid_, kTestUserId);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not fixup app data: "
+                                                 << status.toString8().c_str();
+        }
+
+        return ::testing::AssertionSuccess();
     }
 
 
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
index b8785c6..a7ef674 100644
--- a/cmds/installd/tests/test_utils.h
+++ b/cmds/installd/tests/test_utils.h
@@ -3,6 +3,7 @@
 #include <sys/capability.h>
 
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 #include <selinux/android.h>
 
 uint8_t kBase64Map[256] = {
@@ -74,7 +75,7 @@
 }
 
 bool WriteBase64ToFile(const char* base64, const std::string& file,
-        uid_t uid, gid_t gid, int mode) {
+        uid_t uid, gid_t gid, int mode, std::string* error_msg) {
     CHECK(base64 != nullptr);
     size_t length;
     std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
@@ -83,8 +84,10 @@
 
     int fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
 
+    using android::base::StringPrintf;
+
     if (fd < 0) {
-        PLOG(ERROR) << "Could not open file " << file;
+        *error_msg = StringPrintf("Could not open file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
 
@@ -92,18 +95,18 @@
     while (wrote < length) {
         ssize_t cur = write(fd, bytes.get() + wrote, length - wrote);
         if (cur == -1) {
-            PLOG(ERROR) << "Could not write file " << file;
+            *error_msg = StringPrintf("Could not write file %s: %s", file.c_str(), strerror(errno));
             return false;
         }
         wrote += cur;
     }
 
     if (::chown(file.c_str(), uid, gid) != 0) {
-        PLOG(ERROR) << "Could not chown file " << file;
+        *error_msg = StringPrintf("Could not chown file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
     if (::chmod(file.c_str(), mode) != 0) {
-        PLOG(ERROR) << "Could not chmod file " << file;
+        *error_msg = StringPrintf("Could not chmod file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
     return true;
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 43346fe..d75de1e 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -30,8 +30,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 24
-
 struct AChoreographer;
 typedef struct AChoreographer AChoreographer;
 
@@ -45,25 +43,29 @@
  */
 typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data);
 
+#if __ANDROID_API__ >= 24
+
 /**
  * Get the AChoreographer instance for the current thread. This must be called
  * on an ALooper thread.
  */
-AChoreographer* AChoreographer_getInstance();
+AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
 
 /**
  * Post a callback to be run on the next frame. The data pointer provided will
  * be passed to the callback function when it's called.
  */
 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
-                AChoreographer_frameCallback callback, void* data);
+                AChoreographer_frameCallback callback, void* data) __INTRODUCED_IN(24);
+
 /**
  * Post a callback to be run on the frame following the specified delay. The
  * data pointer provided will be passed to the callback function when it's
  * called.
  */
 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
-                AChoreographer_frameCallback callback, void* data, long delayMillis);
+                AChoreographer_frameCallback callback, void* data,
+                long delayMillis) __INTRODUCED_IN(24);
 
 #endif /* __ANDROID_API__ >= 24 */
 
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 6287332..ef6c5a2 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -30,6 +30,10 @@
 
 #include <android/asset_manager.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -676,34 +680,34 @@
  * Return the current configuration screen width in dp units, or
  * ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
 
 /**
  * Return the current configuration screen height in dp units, or
  * ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
  */
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's current screen width in dp units.
  */
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
 
 /**
  * Return the configuration's smallest screen width in dp units, or
  * ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
  */
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
 
 /**
  * Set the configuration's smallest screen width in dp units.
  */
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
 #endif /* __ANDROID_API__ >= 13 */
 
 #if __ANDROID_API__ >= 17
@@ -711,12 +715,12 @@
  * Return the configuration's layout direction, or
  * ACONFIGURATION_LAYOUTDIR_ANY if not set.
  */
-int32_t AConfiguration_getLayoutDirection(AConfiguration* config);
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
 
 /**
  * Set the configuration's layout direction.
  */
-void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value);
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
 #endif /* __ANDROID_API__ >= 17 */
 
 /**
diff --git a/include/android/input.h b/include/android/input.h
index 0829989..6810901 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -56,6 +56,10 @@
 #include <android/keycodes.h>
 #include <android/looper.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -984,7 +988,7 @@
 
 #if __ANDROID_API__ >= 14
 /** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
 #endif
 
 /**
@@ -1056,7 +1060,7 @@
  * The tool type indicates the type of tool used to make contact such as a
  * finger or stylus, if known.
  */
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
 #endif
 
 /**
@@ -1150,7 +1154,7 @@
 #if __ANDROID_API__ >= 13
 /** Get the value of the request axis for the given pointer index. */
 float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index);
+        int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
 #endif
 
 /**
@@ -1288,7 +1292,7 @@
  * that occurred between this event and the previous motion event.
  */
 float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
-        int32_t axis, size_t pointer_index, size_t history_index);
+        int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
 #endif
 
 
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 5f2a57f..4d24680 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,7 +60,7 @@
  * on failure with an appropriate errno value set.
  */
 
-#if __ANDROID_API__ >= 24
+#if __ANDROID_API__ >= 23
 
 /**
  * Set the network to be used by the given socket file descriptor.
@@ -70,7 +70,7 @@
  * This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
  *
  */
-int android_setsocknetwork(net_handle_t network, int fd);
+int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
 
 
 /**
@@ -87,7 +87,7 @@
  * This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
  *
  */
-int android_setprocnetwork(net_handle_t network);
+int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
 
 
 /**
@@ -106,9 +106,9 @@
  */
 int android_getaddrinfofornetwork(net_handle_t network,
         const char *node, const char *service,
-        const struct addrinfo *hints, struct addrinfo **res);
+        const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
 
-#endif /* __ANDROID_API__ >= 24 */
+#endif /* __ANDROID_API__ >= 23 */
 
 __END_DECLS
 
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 082fab2..0c196b9 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -52,7 +52,7 @@
  * and will automatically release the reference when the Java object gets garbage
  * collected.
  */
-jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window);
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
 #endif
 
 #ifdef __cplusplus
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 191777c..005564d 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -472,13 +472,13 @@
  *     ASensorManager* sensorManager = ASensorManager_getInstance();
  *
  */
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
 __attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
 #else
 ASensorManager* ASensorManager_getInstance();
 #endif
 
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
 /**
  * Get a reference to the sensor manager. ASensorManager is a singleton
  * per package as different packages may have access to different sensors.
@@ -488,7 +488,7 @@
  *     ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
  *
  */
-ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
 #endif
 
 /**
@@ -507,7 +507,7 @@
  * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
  * of this type and wakeUp properties exists.
  */
-ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp);
+ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
 #endif
 
 /**
@@ -525,7 +525,7 @@
  */
 int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
 
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
 /**
  * Create direct channel based on shared memory
  *
@@ -542,7 +542,7 @@
  *         {@link ASensorManager_destroyDirectChannel} and
  *         {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
  */
-int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size);
+int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size) __INTRODUCED_IN(26);
 
 /**
  * Create direct channel based on AHardwareBuffer
@@ -560,7 +560,7 @@
  *         {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
  */
 int ASensorManager_createHardwareBufferDirectChannel(
-        ASensorManager* manager, AHardwareBuffer const * buffer, size_t size);
+        ASensorManager* manager, AHardwareBuffer const * buffer, size_t size) __INTRODUCED_IN(26);
 
 /**
  * Destroy a direct channel
@@ -575,7 +575,7 @@
  *                  {@link ASensorManager_createSharedMemoryDirectChannel} or
  *                  {@link ASensorManager_createHardwareBufferDirectChannel}.
  */
-void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId);
+void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId) __INTRODUCED_IN(26);
 
 /**
  * Configure direct report on channel
@@ -612,9 +612,9 @@
  *
  * \return positive token for success or negative error code.
  */
-int ASensorManager_configureDirectReport(
-        ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
-#endif
+int ASensorManager_configureDirectReport(ASensorManager* manager,
+        ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
+#endif /* __ANDROID_API__ >= 26 */
 
 /*****************************************************************************/
 
@@ -738,30 +738,30 @@
  * Returns the maximum size of batches for this sensor. Batches will often be
  * smaller, as the hardware fifo might be used for other sensors.
  */
-int ASensor_getFifoMaxEventCount(ASensor const* sensor);
+int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the hardware batch fifo size reserved to this sensor.
  */
-int ASensor_getFifoReservedEventCount(ASensor const* sensor);
+int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns this sensor's string type.
  */
-const char* ASensor_getStringType(ASensor const* sensor);
+const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
  */
-int ASensor_getReportingMode(ASensor const* sensor);
+int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
 
 /**
  * Returns true if this is a wake up sensor, false otherwise.
  */
-bool ASensor_isWakeUpSensor(ASensor const* sensor);
+bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
 #endif /* __ANDROID_API__ >= 21 */
 
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
 /**
  * Test if sensor supports a certain type of direct channel.
  *
@@ -771,7 +771,8 @@
  *                     or {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER}.
  * \returns true if sensor supports the specified direct channel type.
  */
-bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType);
+bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
+
 /**
  * Get the highest direct rate level that a sensor support.
  *
@@ -781,8 +782,8 @@
  *         If return value is {@link ASENSOR_DIRECT_RATE_STOP}, it means the sensor
  *         does not support direct report.
  */
-int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor);
-#endif
+int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
+#endif /* __ANDROID_API__ >= 26 */
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 107de64..8c3ff74 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -28,6 +28,7 @@
 #define ANDROID_SHARED_MEMORY_H
 
 #include <stddef.h>
+#include <sys/cdefs.h>
 
 /******************************************************************
  *
@@ -49,7 +50,7 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= __ANDROID_API_O__
+#if __ANDROID_API__ >= 26
 
 /**
  * Create a shared memory region.
@@ -66,7 +67,7 @@
  * \param size size of the shared memory region
  * \return file descriptor that denotes the shared memory; error code on failure.
  */
-int ASharedMemory_create(const char *name, size_t size);
+int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
 
 /**
  * Get the size of the shared memory region.
@@ -76,7 +77,7 @@
  * \param fd file descriptor of the shared memory region
  * \return size in bytes; 0 if fd is not a valid shared memory file descriptor.
  */
-size_t ASharedMemory_getSize(int fd);
+size_t ASharedMemory_getSize(int fd) __INTRODUCED_IN(26);
 
 /**
  * Restrict access of shared memory region.
@@ -109,9 +110,9 @@
  *             updated access. Note access can only be removed, but not added back.
  * \return 0 for success, error code on failure.
  */
-int ASharedMemory_setProt(int fd, int prot);
+int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
 
-#endif
+#endif // __ANDROID_API__ >= 26
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 2af3955..13e56e6 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -30,6 +30,7 @@
 #include <jni.h>
 #include <android/sharedmem.h>
 #include <stddef.h>
+#include <sys/cdefs.h>
 
 /******************************************************************
  *
@@ -51,7 +52,7 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= __ANDROID_API_O_MR1__
+#if __ANDROID_API__ >= 27
 
 /**
  * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
@@ -69,9 +70,9 @@
  *      already closed, if the JNIEnv or jobject is NULL, or if there are too many open file
  *      descriptors (errno=EMFILE)
  */
-int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory);
+int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
 
-#endif
+#endif // __ANDROID_API__ >= 27
 
 #ifdef __cplusplus
 };
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index 56b3342..540d23a 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -43,6 +43,7 @@
  */
 
 #include <stdint.h>
+#include <sys/cdefs.h>
 
 #include <android/native_window.h>
 
@@ -58,13 +59,15 @@
  */
 typedef struct ASurfaceTexture ASurfaceTexture;
 
+#if __ANDROID_API__ >= 28
+
 /**
  * Release the reference to the native ASurfaceTexture acquired with
  * ASurfaceTexture_fromSurfaceTexture().
  * Failing to do so will result in leaked memory and graphic resources.
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
-void ASurfaceTexture_release(ASurfaceTexture* st);
+void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
 /**
  * Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
@@ -73,9 +76,9 @@
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * @return A reference to an ANativeWindow. This reference MUST BE released when no longer needed
  * using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
- * returned if \st is null or if it's not an instance of android.graphics.SurfaceTexture
+ * returned if \p st is null or if it's not an instance of android.graphics.SurfaceTexture
  */
-ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st);
+ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
 /**
  * Attach the SurfaceTexture to the OpenGL ES context that is current on the calling thread.  A
@@ -92,7 +95,7 @@
  * must be unusued in the OpenGL ES context that is current on the calling thread.
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
-int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName);
+int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) __INTRODUCED_IN(28);
 
 /**
  * Detach the SurfaceTexture from the OpenGL ES context that owns the OpenGL ES texture object.
@@ -108,7 +111,7 @@
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
-int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st);
+int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
 /**
  * Update the texture image to the most recent frame from the image stream.  This may only be
@@ -118,7 +121,7 @@
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  * \return 0 on success, negative posix error code otherwise (see <errno.h>)
  */
-int ASurfaceTexture_updateTexImage(ASurfaceTexture* st);
+int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
 /**
  * Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set by
@@ -136,7 +139,7 @@
  * \param mtx the array into which the 4x4 matrix will be stored.  The array must have exactly
  *     16 elements.
  */
-void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]);
+void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) __INTRODUCED_IN(28);
 
 /**
  * Retrieve the timestamp associated with the texture image set by the most recent call to
@@ -155,7 +158,9 @@
  *
  * \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
  */
-int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st);
+int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
+
+#endif /* __ANDROID_API__ >= 28 */
 
 __END_DECLS
 
diff --git a/include/android/trace.h b/include/android/trace.h
index 99b3f82..aa24995 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -47,7 +47,7 @@
  *
  * Available since API level 23.
  */
-bool ATrace_isEnabled();
+bool ATrace_isEnabled() __INTRODUCED_IN(23);
 
 /**
  * Writes a tracing message to indicate that the given section of code has begun. This call must be
@@ -59,7 +59,7 @@
  *
  * Available since API level 23.
  */
-void ATrace_beginSection(const char* sectionName);
+void ATrace_beginSection(const char* sectionName) __INTRODUCED_IN(23);
 
 /**
  * Writes a tracing message to indicate that a given section of code has ended. This call must be
@@ -69,7 +69,7 @@
  *
  * Available since API level 23.
  */
-void ATrace_endSection();
+void ATrace_endSection() __INTRODUCED_IN(23);
 
 #endif /* __ANDROID_API__ >= 23 */
 
diff --git a/libs/binder/ndk/ABinderProcess.cpp b/libs/binder/ndk/ABinderProcess.cpp
new file mode 100644
index 0000000..c89caaf
--- /dev/null
+++ b/libs/binder/ndk/ABinderProcess.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_process.h>
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+
+using ::android::IPCThreadState;
+using ::android::ProcessState;
+
+void ABinderProcess_startThreadPool() {
+    ProcessState::self()->startThreadPool();
+    ProcessState::self()->giveThreadPoolName();
+}
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) {
+    return ProcessState::self()->setThreadPoolMaxThreadCount(numThreads) == 0;
+}
+void ABinderProcess_joinThreadPool() {
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/AIBinder.cpp
new file mode 100644
index 0000000..d0ce98d
--- /dev/null
+++ b/libs/binder/ndk/AIBinder.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_ibinder.h>
+#include "AIBinder_internal.h"
+
+#include <android/binder_status.h>
+#include "AParcel_internal.h"
+
+#include <android-base/logging.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+using ::android::String16;
+using ::android::wp;
+
+AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
+AIBinder::~AIBinder() {}
+
+sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
+    using ::android::String8;
+
+    if (clazz == nullptr) return nullptr;
+    if (mClazz == clazz) return this;
+
+    String8 newDescriptor(clazz->getInterfaceDescriptor());
+
+    if (mClazz != nullptr) {
+        String8 currentDescriptor(mClazz->getInterfaceDescriptor());
+        if (newDescriptor == currentDescriptor) {
+            LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
+                       << "' match during associateClass, but they are different class objects. "
+                          "Class descriptor collision?";
+            return nullptr;
+        }
+
+        LOG(ERROR) << __func__
+                   << ": Class cannot be associated on object which already has a class. Trying to "
+                      "associate to '"
+                   << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
+                   << "'.";
+        return nullptr;
+    }
+
+    String8 descriptor(getBinder()->getInterfaceDescriptor());
+    if (descriptor != newDescriptor) {
+        LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
+                   << "' but descriptor is actually '" << descriptor.c_str() << "'.";
+        return nullptr;
+    }
+
+    // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
+    // An error here can occur if there is a conflict between descriptors (two unrelated classes
+    // define the same descriptor), but this should never happen.
+
+    // if this is a local ABBinder, mClazz should be non-null
+    CHECK(asABBinder() == nullptr);
+    CHECK(asABpBinder() != nullptr);
+
+    if (!isRemote()) {
+        // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
+        ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
+        return binder;
+    }
+
+    // This is a remote object
+    mClazz = clazz;
+
+    return this;
+}
+
+ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
+      : AIBinder(clazz), BBinder(), mUserData(userData) {
+    CHECK(clazz != nullptr);
+}
+ABBinder::~ABBinder() {
+    getClass()->onDestroy(mUserData);
+}
+
+const String16& ABBinder::getInterfaceDescriptor() const {
+    return getClass()->getInterfaceDescriptor();
+}
+
+binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
+                                     binder_flags_t flags) {
+    if (isUserCommand(code)) {
+        if (!data.checkInterface(this)) {
+            return EX_ILLEGAL_STATE;
+        }
+
+        const AParcel in = AParcel::readOnly(this, &data);
+        AParcel out = AParcel(this, reply, false /*owns*/);
+
+        return getClass()->onTransact(this, code, &in, &out);
+    } else {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
+      : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
+    CHECK(binder != nullptr);
+}
+ABpBinder::~ABpBinder() {}
+
+struct AIBinder_Weak {
+    wp<AIBinder> binder;
+};
+AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
+    if (binder == nullptr) return nullptr;
+    return new AIBinder_Weak{wp<AIBinder>(binder)};
+}
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
+    delete weakBinder;
+}
+AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
+    if (weakBinder == nullptr) return nullptr;
+    sp<AIBinder> binder = weakBinder->binder.promote();
+    AIBinder_incStrong(binder.get());
+    return binder.get();
+}
+
+AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+                               AIBinder_Class_onDestroy onDestroy,
+                               AIBinder_Class_onTransact onTransact)
+      : onCreate(onCreate),
+        onDestroy(onDestroy),
+        onTransact(onTransact),
+        mInterfaceDescriptor(interfaceDescriptor) {}
+
+AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
+                                      AIBinder_Class_onCreate onCreate,
+                                      AIBinder_Class_onDestroy onDestroy,
+                                      AIBinder_Class_onTransact onTransact) {
+    if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
+        onTransact == nullptr) {
+        return nullptr;
+    }
+
+    return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
+}
+
+AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
+    if (clazz == nullptr) {
+        LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
+        return nullptr;
+    }
+
+    void* userData = clazz->onCreate(args);
+
+    AIBinder* ret = new ABBinder(clazz, userData);
+    AIBinder_incStrong(ret);
+    return ret;
+}
+
+bool AIBinder_isRemote(AIBinder* binder) {
+    if (binder == nullptr) {
+        return true;
+    }
+
+    return binder->isRemote();
+}
+
+void AIBinder_incStrong(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return;
+    }
+
+    binder->incStrong(nullptr);
+}
+void AIBinder_decStrong(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return;
+    }
+
+    binder->decStrong(nullptr);
+}
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return -1;
+    }
+
+    return binder->getStrongCount();
+}
+
+void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
+    if (binder == nullptr || *binder == nullptr) {
+        return;
+    }
+
+    sp<AIBinder> result = (*binder)->associateClass(clazz);
+
+    // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
+    // callee. First we give the callee their refcount and then take it away from binder. This is
+    // done in this order in order to handle the case that the result and the binder are the same
+    // object.
+    if (result != nullptr) {
+        AIBinder_incStrong(result.get());
+    }
+    AIBinder_decStrong(*binder);
+
+    *binder = result.get(); // Maybe no-op
+}
+
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    return binder->getClass();
+}
+
+void* AIBinder_getUserData(AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    ABBinder* bBinder = binder->asABBinder();
+    if (bBinder == nullptr) {
+        return nullptr;
+    }
+
+    return bBinder->getUserData();
+}
+
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
+    if (binder == nullptr || in == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null parameters.";
+        return EX_NULL_POINTER;
+    }
+    const AIBinder_Class* clazz = binder->getClass();
+    if (clazz == nullptr) {
+        LOG(ERROR) << __func__
+                   << ": Class must be defined for a remote binder transaction. See "
+                      "AIBinder_associateClass.";
+        return EX_ILLEGAL_STATE;
+    }
+
+    *in = new AParcel(binder);
+    binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
+    if (status != EX_NONE) {
+        delete *in;
+        *in = nullptr;
+    }
+
+    return status;
+}
+
+using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
+static void destroy_parcel(AParcel** parcel) {
+    delete *parcel;
+    *parcel = nullptr;
+}
+
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+                                  AParcel** out, binder_flags_t flags) {
+    if (in == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null in parameter";
+        return EX_NULL_POINTER;
+    }
+
+    // This object is the input to the transaction. This function takes ownership of it and deletes
+    // it.
+    AutoParcelDestroyer forIn(in, destroy_parcel);
+
+    if (!isUserCommand(code)) {
+        LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
+        return EX_UNSUPPORTED_OPERATION;
+    }
+
+    if ((flags & ~FLAG_ONEWAY) != 0) {
+        LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
+        return EX_ILLEGAL_ARGUMENT;
+    }
+
+    if (binder == nullptr || *in == nullptr || out == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null parameters.";
+        return EX_NULL_POINTER;
+    }
+
+    if ((*in)->getBinder() != binder) {
+        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+                   << " but called with " << (*in)->getBinder();
+        return EX_ILLEGAL_STATE;
+    }
+
+    *out = new AParcel(binder);
+
+    binder_status_t parcelStatus =
+            binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);
+
+    if (parcelStatus != EX_NONE) {
+        delete *out;
+        *out = nullptr;
+    }
+
+    return parcelStatus;
+}
+
+binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out) {
+    if (out == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null out parameter";
+        return EX_NULL_POINTER;
+    }
+
+    // This object is the input to the transaction. This function takes ownership of it and deletes
+    // it.
+    AutoParcelDestroyer forOut(out, destroy_parcel);
+
+    if (binder == nullptr || *out == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null parameters.";
+        return EX_NULL_POINTER;
+    }
+
+    if ((*out)->getBinder() != binder) {
+        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+                   << " but called with " << (*out)->getBinder();
+        return EX_ILLEGAL_STATE;
+    }
+
+    if ((**out)->dataAvail() != 0) {
+        LOG(ERROR) << __func__
+                   << ": Only part of this transaction was read. There is remaining data left.";
+        return EX_ILLEGAL_STATE;
+    }
+
+    return EX_NONE;
+}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/AIBinder_internal.h
new file mode 100644
index 0000000..d44b937
--- /dev/null
+++ b/libs/binder/ndk/AIBinder_internal.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include "AIBinder_internal.h"
+
+#include <atomic>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+
+inline bool isUserCommand(transaction_code_t code) {
+    return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION;
+}
+
+struct ABBinder;
+struct ABpBinder;
+
+struct AIBinder : public virtual ::android::RefBase {
+    AIBinder(const AIBinder_Class* clazz);
+    virtual ~AIBinder();
+
+    // This returns an AIBinder object with this class associated. If the class is already
+    // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
+    // be returned. If this is a remote object, the class will be associated and this will be ready
+    // to be used for transactions.
+    ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
+    const AIBinder_Class* getClass() const { return mClazz; }
+
+    // This does not create the binder if it does not exist in the process.
+    virtual ::android::sp<::android::IBinder> getBinder() = 0;
+    virtual ABBinder* asABBinder() { return nullptr; }
+    virtual ABpBinder* asABpBinder() { return nullptr; }
+
+    bool isRemote() {
+        auto binder = getBinder();
+        // if the binder is nullptr, then it is a local object which hasn't been sent out of process
+        // yet.
+        return binder != nullptr && binder->remoteBinder() != nullptr;
+    }
+
+private:
+    // AIBinder instance is instance of this class for a local object. In order to transact on a
+    // remote object, this also must be set for simplicity (although right now, only the
+    // interfaceDescriptor from it is used).
+    const AIBinder_Class* mClazz;
+};
+
+// This is a local AIBinder object with a known class.
+struct ABBinder : public AIBinder, public ::android::BBinder {
+    ABBinder(const AIBinder_Class* clazz, void* userData);
+    virtual ~ABBinder();
+
+    void* getUserData() { return mUserData; }
+
+    ::android::sp<::android::IBinder> getBinder() override { return this; }
+    ABBinder* asABBinder() override { return this; }
+
+    const ::android::String16& getInterfaceDescriptor() const override;
+    binder_status_t onTransact(uint32_t code, const ::android::Parcel& data,
+                               ::android::Parcel* reply, binder_flags_t flags) override;
+
+private:
+    // Can contain implementation if this is a local binder. This can still be nullptr for a local
+    // binder. If it is nullptr, the implication is the implementation state is entirely external to
+    // this object and the functionality provided in the AIBinder_Class is sufficient.
+    void* mUserData;
+};
+
+// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
+// a class.
+struct ABpBinder : public AIBinder, public ::android::BpRefBase {
+    ABpBinder(::android::sp<::android::IBinder> binder);
+    virtual ~ABpBinder();
+
+    ::android::sp<::android::IBinder> getBinder() override { return remote(); }
+    ABpBinder* asABpBinder() override { return this; }
+};
+
+struct AIBinder_Class {
+    AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+                   AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+    const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
+
+    const AIBinder_Class_onCreate onCreate;
+    const AIBinder_Class_onDestroy onDestroy;
+    const AIBinder_Class_onTransact onTransact;
+
+private:
+    // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
+    // one.
+    const ::android::String16 mInterfaceDescriptor;
+};
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/AParcel.cpp
new file mode 100644
index 0000000..b63b138
--- /dev/null
+++ b/libs/binder/ndk/AParcel.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_parcel.h>
+#include "AParcel_internal.h"
+
+#include "AIBinder_internal.h"
+
+#include <binder/Parcel.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
+    return (*parcel)->writeStrongBinder(binder->getBinder());
+}
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
+    sp<IBinder> readBinder = nullptr;
+    binder_status_t status = (*parcel)->readStrongBinder(&readBinder);
+    if (status != EX_NONE) {
+        return status;
+    }
+    *binder = new ABpBinder(readBinder);
+    AIBinder_incStrong(*binder);
+    return status;
+}
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
+    sp<IBinder> readBinder = nullptr;
+    binder_status_t status = (*parcel)->readNullableStrongBinder(&readBinder);
+    if (status != EX_NONE) {
+        return status;
+    }
+    *binder = new ABpBinder(readBinder);
+    AIBinder_incStrong(*binder);
+    return status;
+}
+
+// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
+// libbinder and this library.
+// @START
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
+    return (*parcel)->writeInt32(value);
+}
+
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
+    return (*parcel)->writeUint32(value);
+}
+
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
+    return (*parcel)->writeInt64(value);
+}
+
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
+    return (*parcel)->writeUint64(value);
+}
+
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
+    return (*parcel)->writeFloat(value);
+}
+
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
+    return (*parcel)->writeDouble(value);
+}
+
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
+    return (*parcel)->writeBool(value);
+}
+
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
+    return (*parcel)->writeChar(value);
+}
+
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
+    return (*parcel)->writeByte(value);
+}
+
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
+    return (*parcel)->readInt32(value);
+}
+
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
+    return (*parcel)->readUint32(value);
+}
+
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
+    return (*parcel)->readInt64(value);
+}
+
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
+    return (*parcel)->readUint64(value);
+}
+
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
+    return (*parcel)->readFloat(value);
+}
+
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
+    return (*parcel)->readDouble(value);
+}
+
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
+    return (*parcel)->readBool(value);
+}
+
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
+    return (*parcel)->readChar(value);
+}
+
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
+    return (*parcel)->readByte(value);
+}
+
+// @END
diff --git a/libs/binder/ndk/AParcel_internal.h b/libs/binder/ndk/AParcel_internal.h
new file mode 100644
index 0000000..9f30a2f
--- /dev/null
+++ b/libs/binder/ndk/AParcel_internal.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+
+#include <sys/cdefs.h>
+
+#include <binder/Parcel.h>
+#include "AIBinder_internal.h"
+
+struct AParcel {
+    const ::android::Parcel* operator->() const { return mParcel; }
+    ::android::Parcel* operator->() { return mParcel; }
+
+    AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+    AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
+          : mBinder(binder), mParcel(parcel), mOwns(owns) {}
+
+    ~AParcel() {
+        if (mOwns) {
+            delete mParcel;
+        }
+    }
+
+    static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+        return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
+    }
+
+    const AIBinder* getBinder() { return mBinder; }
+
+private:
+    // This object is associated with a calls to a specific AIBinder object. This is used for sanity
+    // checking to make sure that a parcel is one that is expected.
+    const AIBinder* mBinder;
+
+    ::android::Parcel* mParcel;
+    bool mOwns;
+};
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/AServiceManager.cpp
new file mode 100644
index 0000000..f61b914
--- /dev/null
+++ b/libs/binder/ndk/AServiceManager.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_manager.h>
+#include "AIBinder_internal.h"
+
+#include <binder/IServiceManager.h>
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::String16;
+
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance) {
+    if (binder == nullptr || instance == nullptr) {
+        return EX_NULL_POINTER;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    return sm->addService(String16(instance), binder->getBinder());
+}
+AIBinder* AServiceManager_getService(const char* instance) {
+    if (instance == nullptr) {
+        return nullptr;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16(instance));
+
+    AIBinder* ret = new ABpBinder(binder);
+    AIBinder_incStrong(ret);
+    return ret;
+}
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
new file mode 100644
index 0000000..76d5a73
--- /dev/null
+++ b/libs/binder/ndk/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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 {
+    name: "libbinder_ndk",
+    vendor_available: false,
+
+    export_include_dirs: [
+        "include_ndk",
+        "include_apex",
+    ],
+
+    srcs: [
+        "ABinderProcess.cpp",
+        "AIBinder.cpp",
+        "AParcel.cpp",
+        "AServiceManager.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
new file mode 100644
index 0000000..b8f38ba
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+/**
+ * This registers the service with the default service manager under this instance name.
+ */
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
+
+/**
+ * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
+ * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
+ * for calling AIBinder_decStrong).
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
new file mode 100644
index 0000000..69e6387
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * This creates a threadpool for incoming binder transactions if it has not already been created.
+ */
+void ABinderProcess_startThreadPool();
+/**
+ * This sets the maximum number of threads that can be started in the threadpool. By default, after
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
+ * the kernel from starting new threads and will not delete already existing threads.
+ */
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
+/**
+ * This adds the current thread to the threadpool. This may cause the threadpool to exceed the
+ * maximum size.
+ */
+void ABinderProcess_joinThreadPool();
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
new file mode 100644
index 0000000..23136a2
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+__BEGIN_DECLS
+
+// Also see TF_* in kernel's binder.h
+typedef uint32_t binder_flags_t;
+enum {
+    /**
+     * The transaction will be dispatched and then returned to the caller. The outgoing process
+     * cannot block a call made by this, and execution of the call will not be waited on. An error
+     * can still be returned if the call is unable to be processed by the binder driver. All oneway
+     * calls are guaranteed to be ordered if they are sent on the same AIBinder object.
+     */
+    FLAG_ONEWAY = 0x01,
+};
+
+// Also see IBinder.h in libbinder
+typedef uint32_t transaction_code_t;
+enum {
+    /**
+     * The first transaction code available for user commands (inclusive).
+     */
+    FIRST_CALL_TRANSACTION = 0x00000001,
+    /**
+     * The last transaction code available for user commands (inclusive).
+     */
+    LAST_CALL_TRANSACTION = 0x00ffffff,
+};
+
+/**
+ * Represents a type of AIBinder object which can be sent out.
+ */
+struct AIBinder_Class;
+typedef struct AIBinder_Class AIBinder_Class;
+
+/**
+ * Represents a local or remote object which can be used for IPC or which can itself be sent.
+ *
+ * This object has a refcount associated with it and will be deleted when its refcount reaches zero.
+ * How methods interactive with this refcount is described below. When using this API, it is
+ * intended for a client of a service to hold a strong reference to that service. This also means
+ * that user data typically should hold a strong reference to a local AIBinder object. A remote
+ * AIBinder object automatically holds a strong reference to the AIBinder object in the server's
+ * process. A typically memory layout looks like this:
+ *
+ * Key:
+ *   --->         Ownership/a strong reference
+ *   ...>         A weak reference
+ *
+ *                         (process boundary)
+ *                                 |
+ * MyInterface ---> AIBinder_Weak  |  ProxyForMyInterface
+ *      ^                .         |          |
+ *      |                .         |          |
+ *      |                v         |          v
+ *   UserData  <---   AIBinder   <-|-      AIBinder
+ *                                 |
+ *
+ * In this way, you'll notice that a proxy for the interface holds a strong reference to the
+ * implementation and that in the server process, the AIBinder object which was sent can be resent
+ * so that the same AIBinder object always represents the same object. This allows, for instance, an
+ * implementation (usually a callback) to transfer all ownership to a remote process and
+ * automatically be deleted when the remote process is done with it or dies. Other memory models are
+ * possible, but this is the standard one.
+ */
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+/**
+ * The AIBinder object associated with this can be retrieved if it is still alive so that it can be
+ * re-used. The intention of this is to enable the same AIBinder object to always represent the same
+ * object.
+ */
+struct AIBinder_Weak;
+typedef struct AIBinder_Weak AIBinder_Weak;
+
+/**
+ * This is called whenever a new AIBinder object is needed of a specific class.
+ *
+ * These arguments are passed from AIBinder_new. The return value is stored and can be retrieved
+ * using AIBinder_getUserData.
+ */
+typedef void* (*AIBinder_Class_onCreate)(void* args);
+
+/**
+ * This is called whenever an AIBinder object is no longer referenced and needs destroyed.
+ *
+ * Typically, this just deletes whatever the implementation is.
+ */
+typedef void (*AIBinder_Class_onDestroy)(void* userData);
+
+/**
+ * This is called whenever a transaction needs to be processed by a local implementation.
+ */
+typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transaction_code_t code,
+                                                     const AParcel* in, AParcel* out);
+
+/**
+ * An interfaceDescriptor uniquely identifies the type of object that is being created. This is used
+ * internally for sanity checks on transactions.
+ *
+ * None of these parameters can be nullptr.
+ *
+ * This is created one time during library initialization and cleaned up when the process exits or
+ * execs.
+ */
+__attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
+        const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+        AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+/**
+ * Creates a new binder object of the appropriate class.
+ *
+ * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
+ * and AIBinder_decStrong. When the reference count reaches zero, onDestroy is called.
+ *
+ * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
+ * required to delete this object.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
+
+/**
+ * If this is hosted in a process other than the current one.
+ */
+bool AIBinder_isRemote(AIBinder* binder);
+
+/**
+ * This can only be called if a strong reference to this object already exists in process.
+ */
+void AIBinder_incStrong(AIBinder* binder);
+
+/**
+ * This will delete the object and call onDestroy once the refcount reaches zero.
+ */
+void AIBinder_decStrong(AIBinder* binder);
+
+/**
+ * For debugging only!
+ */
+int32_t AIBinder_debugGetRefCount(AIBinder* binder);
+
+/**
+ * This sets the class of an AIBinder object. This checks to make sure the remote object is of
+ * the expected class. A class must be set in order to use transactions on an AIBinder object.
+ * However, if an object is just intended to be passed through to another process or used as a
+ * handle this need not be called.
+ *
+ * The binder parameter may or may not be updated. If it is updated, the ownership of the original
+ * object is transferred to the new object. If the class association fails, ownership of the binder
+ * is lost, and it is set to nullptr.
+ */
+void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz);
+
+/*
+ * Returns the class that this binder was constructed with or associated with.
+ */
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
+
+/**
+ * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
+ * nullptr), this also returns nullptr. For a remote binder, this will always return nullptr.
+ */
+void* AIBinder_getUserData(AIBinder* binder);
+
+/**
+ * A transaction is a series of calls to these functions which looks this
+ * - call AIBinder_prepareTransaction
+ * - fill out parcel with in parameters (lifetime of the 'in' variable)
+ * - call AIBinder_transact
+ * - fill out parcel with out parameters (lifetime of the 'out' variable)
+ * - call AIBinder_finalizeTransaction
+ */
+
+/**
+ * Creates a parcel to start filling out for a transaction. This may add data to the parcel for
+ * security, debugging, or other purposes. This parcel is to be sent via AIBinder_transact and it
+ * represents the input data to the transaction. It is recommended to check if the object is local
+ * and call directly into its user data before calling this as the parceling and unparceling cost
+ * can be avoided. This AIBinder must be either built with a class or associated with a class before
+ * using this API.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
+
+/**
+ * Transact using a parcel created from AIBinder_prepareTransaction. This actually communicates with
+ * the object representing this binder object. This also passes out a parcel to be used for the
+ * return transaction. This takes ownership of the in parcel and automatically deletes it after it
+ * is sent to the remote process. The output parcel is the result of the transaction. If the
+ * transaction has FLAG_ONEWAY, the out parcel will be empty. Otherwise, this will block until the
+ * remote process has processed the transaction, and the out parcel will contain the output data
+ * from transaction.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+                                  AParcel** out, binder_flags_t flags);
+
+/**
+ * This takes ownership of the out parcel and automatically deletes it. Additional checks for
+ * security or debugging maybe performed internally.
+ *
+ * This does not affect the ownership of binder.
+ */
+binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out);
+
+/*
+ * This does not take any ownership of the input binder, but it can be used to retrieve it if
+ * something else in some process still holds a reference to it.
+ */
+__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
+
+/*
+ * Deletes the weak reference. This will have no impact on the lifetime of the binder.
+ */
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder);
+
+/**
+ * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
+ * nullptr.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
new file mode 100644
index 0000000..091ae8e
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#include <android/binder_status.h>
+
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+__BEGIN_DECLS
+
+/**
+ * This object represents a package of data that can be sent between processes. When transacting, an
+ * instance of it is automatically created to be used for the transaction. When two processes use
+ * binder to communicate, they must agree on a format of this parcel to be used in order to transfer
+ * data. This is usually done in an IDL (see AIDL, specificially).
+ */
+struct AParcel;
+typedef struct AParcel AParcel;
+
+/**
+ * Writes an AIBinder to the next location in a non-null parcel. Can be null.
+ */
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
+ * non-null. One strong ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
+ * ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+// @START
+/**
+ * Writes int32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value);
+
+/**
+ * Writes uint32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value);
+
+/**
+ * Writes int64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value);
+
+/**
+ * Writes uint64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value);
+
+/**
+ * Writes float value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value);
+
+/**
+ * Writes double value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value);
+
+/**
+ * Writes bool value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value);
+
+/**
+ * Writes char16_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value);
+
+/**
+ * Writes int8_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value);
+
+/**
+ * Reads into int32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value);
+
+/**
+ * Reads into uint32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value);
+
+/**
+ * Reads into int64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value);
+
+/**
+ * Reads into uint64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value);
+
+/**
+ * Reads into float value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value);
+
+/**
+ * Reads into double value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value);
+
+/**
+ * Reads into bool value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value);
+
+/**
+ * Reads into char16_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value);
+
+/**
+ * Reads into int8_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value);
+
+// @END
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
new file mode 100644
index 0000000..d414c99
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Keep the exception codes in sync with android/os/Parcel.java.
+enum {
+    EX_NONE = 0,
+    EX_SECURITY = -1,
+    EX_BAD_PARCELABLE = -2,
+    EX_ILLEGAL_ARGUMENT = -3,
+    EX_NULL_POINTER = -4,
+    EX_ILLEGAL_STATE = -5,
+    EX_NETWORK_MAIN_THREAD = -6,
+    EX_UNSUPPORTED_OPERATION = -7,
+    EX_SERVICE_SPECIFIC = -8,
+    EX_PARCELABLE = -9,
+
+    /**
+     * This is special and Java specific; see Parcel.java.
+     * This should be considered a success, and the next readInt32 bytes can be ignored.
+     */
+    EX_HAS_REPLY_HEADER = -128,
+
+    /**
+     * This is special, and indicates to native binder proxies that the
+     * transaction has failed at a low level.
+     */
+    EX_TRANSACTION_FAILED = -129,
+};
+
+/**
+ * One of the above values or -errno.
+ * By convention, positive values are considered to mean service-specific exceptions.
+ */
+typedef int32_t binder_status_t;
+
+__END_DECLS
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
new file mode 100755
index 0000000..6c8527d
--- /dev/null
+++ b/libs/binder/ndk/runtests.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2018 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+  echo "You need to source and lunch before you can use this script"
+  exit 1
+fi
+
+set -ex
+
+function run_libbinder_ndk_test() {
+	adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
+	local pid=$!
+	trap "kill $pid" ERR
+	adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client
+	trap '' ERR
+	kill $pid
+}
+
+[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+    MODULES-IN-frameworks-native-libs-binder-ndk
+
+adb root
+adb wait-for-device
+adb sync data
+
+run_libbinder_ndk_test
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000..698d291
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2018 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.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
new file mode 100755
index 0000000..5c0b936
--- /dev/null
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 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.
+
+import os
+import sys
+
+# list (pretty, cpp)
+data_types = [
+    ("Int32", "int32_t"),
+    ("Uint32", "uint32_t"),
+    ("Int64", "int64_t"),
+    ("Uint64", "uint64_t"),
+    ("Float", "float"),
+    ("Double", "double"),
+    ("Bool", "bool"),
+    ("Char", "char16_t"),
+    ("Byte", "int8_t"),
+]
+
+def replaceFileTags(path, content):
+    print("Updating", path)
+    with open(path, "r+") as f:
+        lines = f.readlines()
+
+        start = lines.index("// @START\n")
+        end = lines.index("// @END\n")
+
+        if end <= start or start < 0 or end < 0:
+            print("Failed to find tags in", path)
+            exit(1)
+
+        f.seek(0)
+        f.write("".join(lines[:start+1]) + content + "".join(lines[end:]))
+        f.truncate()
+
+def main():
+    if len(sys.argv) != 1:
+        print("No arguments.")
+        exit(1)
+
+    ABT = os.environ.get('ANDROID_BUILD_TOP', None)
+    if ABT is None:
+        print("Can't get ANDROID_BUILD_TOP. Lunch?")
+        exit(1)
+    ROOT = ABT + "/frameworks/native/libs/binder/ndk/"
+
+    print("Updating auto-generated code")
+
+    header = ""
+    source = ""
+
+    for pretty, cpp in data_types:
+        header += "/**\n"
+        header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
+        header += " */\n"
+        header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value);\n\n"
+        source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
+        source += "    return (*parcel)->write" + pretty + "(value);\n"
+        source += "}\n\n"
+
+    for pretty, cpp in data_types:
+        header += "/**\n"
+        header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
+        header += " */\n"
+        header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value);\n\n"
+        source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
+        source += "    return (*parcel)->read" + pretty + "(value);\n"
+        source += "}\n\n"
+
+    replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header)
+    replaceFileTags(ROOT + "AParcel.cpp", source)
+
+    print("Updating DONE.")
+
+if __name__ == "__main__":
+    main()
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
new file mode 100644
index 0000000..d242138
--- /dev/null
+++ b/libs/binder/ndk/test/Android.bp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This test is a unit test of the low-level API that is presented here.
+// Actual users should use AIDL to generate these complicated stubs.
+
+cc_defaults {
+    name: "test_libbinder_ndk_defaults",
+    shared_libs: [
+        "libbase",
+    ],
+    strip: {
+        none: true,
+    },
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
+
+cc_library_static {
+    name: "test_libbinder_ndk_library",
+    defaults: ["test_libbinder_ndk_defaults"],
+    export_include_dirs: ["include"],
+    shared_libs: ["libbinder_ndk"],
+    export_shared_lib_headers: ["libbinder_ndk"],
+    srcs: ["iface.cpp"],
+}
+
+cc_defaults {
+    name: "test_libbinder_ndk_test_defaults",
+    defaults: ["test_libbinder_ndk_defaults"],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libutils",
+    ],
+    static_libs: [
+        "libbinder_ndk",
+        "test_libbinder_ndk_library",
+    ],
+}
+
+cc_test {
+    name: "libbinder_ndk_test_client",
+    defaults: ["test_libbinder_ndk_test_defaults"],
+    srcs: ["main_client.cpp"],
+}
+
+cc_test {
+    name: "libbinder_ndk_test_server",
+    defaults: ["test_libbinder_ndk_test_defaults"],
+    srcs: ["main_server.cpp"],
+    gtest: false,
+}
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
new file mode 100644
index 0000000..eed09f0
--- /dev/null
+++ b/libs/binder/ndk/test/iface.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+using ::android::wp;
+
+const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
+const char* kIFooDescriptor = "my-special-IFoo-class";
+
+struct IFoo_Class_Data {
+    sp<IFoo> foo;
+};
+
+void* IFoo_Class_onCreate(void* args) {
+    IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
+    // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
+    // coupled with this.
+    return static_cast<void*>(foo);
+}
+
+void IFoo_Class_onDestroy(void* userData) {
+    delete static_cast<IFoo_Class_Data*>(userData);
+}
+
+binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
+                                      AParcel* out) {
+    binder_status_t stat = EX_UNSUPPORTED_OPERATION;
+
+    sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
+    CHECK(foo != nullptr) << "Transaction made on already deleted object";
+
+    switch (code) {
+        case IFoo::DOFOO: {
+            int32_t valueIn;
+            stat = AParcel_readInt32(in, &valueIn);
+            if (stat != EX_NONE) break;
+            int32_t valueOut = foo->doubleNumber(valueIn);
+            stat = AParcel_writeInt32(out, valueOut);
+            break;
+        }
+    }
+
+    return stat;
+}
+
+AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
+                                                     IFoo_Class_onDestroy, IFoo_Class_onTransact);
+
+class BpFoo : public IFoo {
+public:
+    BpFoo(AIBinder* binder) : mBinder(binder) {}
+    virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
+
+    virtual int32_t doubleNumber(int32_t in) {
+        AParcel* parcelIn;
+        CHECK(EX_NONE == AIBinder_prepareTransaction(mBinder, &parcelIn));
+
+        CHECK(EX_NONE == AParcel_writeInt32(parcelIn, in));
+
+        AParcel* parcelOut;
+        CHECK(EX_NONE ==
+              AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/));
+
+        int32_t out;
+        CHECK(EX_NONE == AParcel_readInt32(parcelOut, &out));
+
+        CHECK(EX_NONE == AIBinder_finalizeTransaction(mBinder, &parcelOut));
+        return out;
+    }
+
+private:
+    // Always assumes one refcount
+    AIBinder* mBinder;
+};
+
+IFoo::~IFoo() {
+    AIBinder_Weak_delete(mWeakBinder);
+}
+
+binder_status_t IFoo::addService(const char* instance) {
+    AIBinder* binder = nullptr;
+
+    if (mWeakBinder != nullptr) {
+        // one strong ref count of binder
+        binder = AIBinder_Weak_promote(mWeakBinder);
+    }
+    if (binder == nullptr) {
+        // or one strong refcount here
+        binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
+        if (mWeakBinder != nullptr) {
+            AIBinder_Weak_delete(mWeakBinder);
+        }
+        mWeakBinder = AIBinder_Weak_new(binder);
+    }
+
+    binder_status_t status = AServiceManager_addService(binder, instance);
+    // Strong references we care about kept by remote process
+    AIBinder_decStrong(binder);
+    return status;
+}
+
+sp<IFoo> IFoo::getService(const char* instance) {
+    AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+    AIBinder_associateClass(&binder, IFoo::kClass);
+
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    if (AIBinder_isRemote(binder)) {
+        sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
+        return ret;
+    }
+
+    IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
+
+    CHECK(data != nullptr); // always created with non-null data
+
+    sp<IFoo> ret = data->foo;
+
+    AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
+    CHECK(held == binder);
+    AIBinder_decStrong(held);
+
+    // IFoo only keeps a weak reference to AIBinder, so we can drop this
+    AIBinder_decStrong(binder);
+    return ret;
+}
diff --git a/libs/binder/ndk/test/include/iface/iface.h b/libs/binder/ndk/test/include/iface/iface.h
new file mode 100644
index 0000000..4c61e9d
--- /dev/null
+++ b/libs/binder/ndk/test/include/iface/iface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include <utils/RefBase.h>
+
+class IFoo : public virtual ::android::RefBase {
+public:
+    static const char* kSomeInstanceName;
+    static AIBinder_Class* kClass;
+
+    // Takes ownership of IFoo
+    binder_status_t addService(const char* instance);
+    static ::android::sp<IFoo> getService(const char* instance);
+
+    enum Call {
+        DOFOO = FIRST_CALL_TRANSACTION + 0,
+    };
+
+    virtual ~IFoo();
+    virtual int32_t doubleNumber(int32_t in) = 0;
+
+private:
+    AIBinder_Weak* mWeakBinder = nullptr; // maybe owns AIBinder
+};
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
new file mode 100644
index 0000000..7c53e51
--- /dev/null
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
+
+// This is too slow
+// TEST(NdkBinder, GetServiceThatDoesntExist) {
+//     sp<IFoo> foo = IFoo::getService("asdfghkl;");
+//     EXPECT_EQ(nullptr, foo.get());
+// }
+
+TEST(NdkBinder, DoubleNumber) {
+    sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
+    ASSERT_NE(foo, nullptr);
+    EXPECT_EQ(2, foo->doubleNumber(1));
+}
+
+TEST(NdkBinder, RetrieveNonNdkService) {
+    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(nullptr, binder);
+    AIBinder_decStrong(binder);
+}
+
+class MyTestFoo : public IFoo {
+    int32_t doubleNumber(int32_t in) override {
+        LOG(INFO) << "doubleNumber " << in;
+        return 2 * in;
+    }
+};
+
+TEST(NdkBinder, GetServiceInProcess) {
+    static const char* kInstanceName = "test-get-service-in-process";
+
+    sp<IFoo> foo = new MyTestFoo;
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
+
+    sp<IFoo> getFoo = IFoo::getService(kInstanceName);
+    EXPECT_EQ(foo.get(), getFoo.get());
+
+    EXPECT_EQ(2, getFoo->doubleNumber(1));
+}
+
+TEST(NdkBinder, AddServiceMultipleTimes) {
+    static const char* kInstanceName1 = "test-multi-1";
+    static const char* kInstanceName2 = "test-multi-2";
+    sp<IFoo> foo = new MyTestFoo;
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
+    EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
+}
diff --git a/libs/binder/ndk/test/main_server.cpp b/libs/binder/ndk/test/main_server.cpp
new file mode 100644
index 0000000..f3da7da
--- /dev/null
+++ b/libs/binder/ndk/test/main_server.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_process.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+class MyFoo : public IFoo {
+    int32_t doubleNumber(int32_t in) override {
+        LOG(INFO) << "doubling " << in;
+        return 2 * in;
+    }
+};
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // Strong reference to MyFoo kept by service manager.
+    binder_status_t status = (new MyFoo)->addService(IFoo::kSomeInstanceName);
+
+    if (status != EX_NONE) {
+        LOG(FATAL) << "Could not register: " << status;
+    }
+
+    ABinderProcess_joinThreadPool();
+
+    return 1;
+}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000..1eba892
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2018 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.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 961f101..a8ef7a0 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -56,7 +56,7 @@
     mDriverPath = path;
 }
 
-void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths) {
+void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
     if (mLayerPaths.empty()) {
         mLayerPaths = layerPaths;
         mAppNamespace = appNamespace;
@@ -66,7 +66,7 @@
     }
 }
 
-android_namespace_t* GraphicsEnv::getAppNamespace() {
+NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
     return mAppNamespace;
 }
 
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 213580c..17e8f6b 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -23,6 +23,8 @@
 
 namespace android {
 
+class NativeLoaderNamespace;
+
 class GraphicsEnv {
 public:
     static GraphicsEnv& getInstance();
@@ -35,8 +37,8 @@
     void setDriverPath(const std::string path);
     android_namespace_t* getDriverNamespace();
 
-    void setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths);
-    android_namespace_t* getAppNamespace();
+    void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths);
+    NativeLoaderNamespace* getAppNamespace();
     const std::string getLayerPaths();
 
     void setDebugLayers(const std::string layers);
@@ -48,7 +50,7 @@
     std::string mDebugLayers;
     std::string mLayerPaths;
     android_namespace_t* mDriverNamespace = nullptr;
-    android_namespace_t* mAppNamespace = nullptr;
+    NativeLoaderNamespace* mAppNamespace = nullptr;
 };
 
 } // namespace android
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 74cee3f..571558a 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -171,12 +171,12 @@
 int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
                                     const DvrNativeBufferMetadata* meta,
                                     int ready_fence_fd) {
+  // Some basic sanity checks before we put the buffer back into a slot.
+  size_t slot = static_cast<size_t>(write_buffer->slot);
   LOG_FATAL_IF(
       (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
       "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
 
-  // Some basic sanity checks before we put the buffer back into a slot.
-  size_t slot = static_cast<size_t>(write_buffer->slot);
   if (write_buffers_[slot] != nullptr) {
     ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
     return -EINVAL;
@@ -374,12 +374,12 @@
 int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
                                       const DvrNativeBufferMetadata* meta,
                                       int release_fence_fd) {
+  // Some basic sanity checks before we put the buffer back into a slot.
+  size_t slot = static_cast<size_t>(read_buffer->slot);
   LOG_FATAL_IF(
       (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
       "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
 
-  // Some basic sanity checks before we put the buffer back into a slot.
-  size_t slot = static_cast<size_t>(read_buffer->slot);
   if (read_buffers_[slot] != nullptr) {
     ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
     return -EINVAL;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 3312b03..42049a4 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -456,7 +456,7 @@
 // Translates EGL color spaces to Android data spaces.
 static android_dataspace dataSpaceFromEGLColorSpace(EGLint colorspace) {
     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
-        return HAL_DATASPACE_SRGB_LINEAR;
+        return HAL_DATASPACE_UNKNOWN;
     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
         return HAL_DATASPACE_SRGB;
     } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index cbba5f4..7eaf7b2 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -81,6 +81,8 @@
         "libutils",
         "libcutils",
         "libz",
+        "libnativebridge",
+        "libnativeloader",
         "libnativewindow",
         "android.hardware.graphics.common@1.0",
     ],
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 3a59208..96c5563 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -31,6 +31,8 @@
 #include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
+#include <nativebridge/native_bridge.h>
+#include <nativeloader/native_loader.h>
 #include <ziparchive/zip_archive.h>
 
 // TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
@@ -73,12 +75,14 @@
         : path_(path),
           filename_(filename),
           dlhandle_(nullptr),
+          native_bridge_(false),
           refcount_(0) {}
 
     LayerLibrary(LayerLibrary&& other)
         : path_(std::move(other.path_)),
           filename_(std::move(other.filename_)),
           dlhandle_(other.dlhandle_),
+          native_bridge_(other.native_bridge_),
           refcount_(other.refcount_) {
         other.dlhandle_ = nullptr;
         other.refcount_ = 0;
@@ -101,6 +105,17 @@
     const std::string GetFilename() { return filename_; }
 
    private:
+    // TODO(b/79940628): remove that adapter when we could use NativeBridgeGetTrampoline
+    // for native libraries.
+    template<typename Func = void*>
+    Func GetTrampoline(const char* name) const {
+        if (native_bridge_) {
+            return reinterpret_cast<Func>(android::NativeBridgeGetTrampoline(
+                dlhandle_, name, nullptr, 0));
+        }
+        return reinterpret_cast<Func>(dlsym(dlhandle_, name));
+    }
+
     const std::string path_;
 
     // Track the filename alone so we can detect duplicates
@@ -108,6 +123,7 @@
 
     std::mutex mutex_;
     void* dlhandle_;
+    bool native_bridge_;
     size_t refcount_;
 };
 
@@ -123,19 +139,23 @@
         auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
         if (app_namespace &&
             !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
-            android_dlextinfo dlextinfo = {};
-            dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
-            dlextinfo.library_namespace = app_namespace;
-            dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL,
-                                           &dlextinfo);
+            std::string error_msg;
+            dlhandle_ = OpenNativeLibrary(
+                app_namespace, path_.c_str(), &native_bridge_, &error_msg);
+            if (!dlhandle_) {
+                ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+                      error_msg.c_str());
+                refcount_ = 0;
+                return false;
+            }
         } else {
-            dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
-        }
-        if (!dlhandle_) {
-            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
-                  dlerror());
-            refcount_ = 0;
-            return false;
+          dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+            if (!dlhandle_) {
+                ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+                      dlerror());
+                refcount_ = 0;
+                return false;
+            }
         }
     }
     return true;
@@ -153,11 +173,11 @@
 bool LayerLibrary::EnumerateLayers(size_t library_idx,
                                    std::vector<Layer>& instance_layers) const {
     PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
-        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
-            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
+        GetTrampoline<PFN_vkEnumerateInstanceLayerProperties>(
+            "vkEnumerateInstanceLayerProperties");
     PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
-        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
-            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+        GetTrampoline<PFN_vkEnumerateInstanceExtensionProperties>(
+            "vkEnumerateInstanceExtensionProperties");
     if (!enumerate_instance_layers || !enumerate_instance_extensions) {
         ALOGE("layer library '%s' missing some instance enumeration functions",
               path_.c_str());
@@ -166,11 +186,11 @@
 
     // device functions are optional
     PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
-        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
-            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+        GetTrampoline<PFN_vkEnumerateDeviceLayerProperties>(
+            "vkEnumerateDeviceLayerProperties");
     PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
-        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
-            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+        GetTrampoline<PFN_vkEnumerateDeviceExtensionProperties>(
+            "vkEnumerateDeviceExtensionProperties");
 
     // get layer counts
     uint32_t num_instance_layers = 0;
@@ -301,10 +321,10 @@
     char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
     strcpy(name, layer.properties.layerName);
     strcpy(name + layer_name_len, gpa_name);
-    if (!(gpa = dlsym(dlhandle_, name))) {
+    if (!(gpa = GetTrampoline(name))) {
         strcpy(name, "vk");
         strcpy(name + 2, gpa_name);
-        gpa = dlsym(dlhandle_, name);
+        gpa = GetTrampoline(name);
     }
     return gpa;
 }