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;
}