diff --git a/defconfig b/defconfig
index ff0704f..d7f0ea5 100644
--- a/defconfig
+++ b/defconfig
@@ -59,3 +59,6 @@ CONFIG_OVERLAY_FS=m
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_DEVICES="binder"
 CONFIG_ANDROID_BINDER_IPC=y
+# This will configure the Dynamically Allocated Binder Devices added
+# to 5.0+ kernels:
+CONFIG_ANDROID_BINDERFS=y
diff --git a/policy/test_binder.te b/policy/test_binder.te
index 47992b2..c160ec0 100644
--- a/policy/test_binder.te
+++ b/policy/test_binder.te
@@ -1,126 +1,118 @@
-
 attribute binderdomain;
 
 #
-################################## Manager ###################################
+################################## Manager ##################################
 #
 type test_binder_mgr_t;
 domain_type(test_binder_mgr_t)
 unconfined_runs_test(test_binder_mgr_t)
 typeattribute test_binder_mgr_t testdomain;
 typeattribute test_binder_mgr_t binderdomain;
-allow test_binder_mgr_t self:binder { set_context_mgr call };
-allow test_binder_mgr_t test_binder_provider_t:binder call;
+allow test_binder_mgr_t test_binder_client_t:binder { transfer };
 allow test_binder_mgr_t device_t:chr_file { ioctl open read write };
 allow_map(test_binder_mgr_t, device_t, chr_file)
-allow test_binder_mgr_t self:capability { sys_nice };
-allow test_binder_provider_t test_binder_mgr_t:fd use;
-fs_getattr_tmpfs(test_binder_mgr_t)
-allow test_binder_mgr_t tmpfs_t:file { read write open };
-allow_map(test_binder_mgr_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_mgr_t)
-fs_manage_tmpfs_files(test_binder_mgr_t)
-
+allow test_binder_mgr_t self:binder { set_context_mgr };
 # For writing to flag file:
 allow test_binder_mgr_t test_file_t:fifo_file rw_file_perms;
 
 #
-########################## Manager no fd {use} ###############################
-#
-type test_binder_mgr_no_fd_t;
-domain_type(test_binder_mgr_no_fd_t)
-unconfined_runs_test(test_binder_mgr_no_fd_t)
-typeattribute test_binder_mgr_no_fd_t testdomain;
-typeattribute test_binder_mgr_no_fd_t binderdomain;
-allow test_binder_mgr_no_fd_t self:binder { set_context_mgr call };
-allow test_binder_mgr_no_fd_t test_binder_provider_t:binder { call };
-allow test_binder_mgr_no_fd_t device_t:chr_file { ioctl open read write };
-allow_map(test_binder_mgr_no_fd_t, device_t, chr_file)
-allow test_binder_provider_t test_binder_mgr_no_fd_t:binder { call transfer impersonate };
-fs_getattr_tmpfs(test_binder_mgr_no_fd_t)
-allow test_binder_mgr_no_fd_t tmpfs_t:file { read write open };
-allow_map(test_binder_mgr_no_fd_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_mgr_no_fd_t)
-fs_manage_tmpfs_files(test_binder_mgr_no_fd_t)
-
-# For writing to flag file:
-allow test_binder_mgr_no_fd_t test_file_t:fifo_file rw_file_perms;
-
-#
-########################## Service Provider ################################
+########################### Service Provider ################################
 #
 type test_binder_provider_t;
 domain_type(test_binder_provider_t)
 unconfined_runs_test(test_binder_provider_t)
 typeattribute test_binder_provider_t testdomain;
 typeattribute test_binder_provider_t binderdomain;
-allow test_binder_provider_t self:binder { call };
-allow test_binder_provider_t test_binder_mgr_t:binder { call transfer impersonate };
+allow test_binder_provider_t test_binder_mgr_t:binder { call transfer };
 allow test_binder_provider_t device_t:chr_file { ioctl open read write };
 allow_map(test_binder_provider_t, device_t, chr_file)
-# For fstat:
-allow test_binder_provider_t device_t:chr_file getattr;
-fs_getattr_tmpfs(test_binder_provider_t)
-allow test_binder_provider_t tmpfs_t:file { read write open };
-allow_map(test_binder_provider_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_provider_t)
-fs_manage_tmpfs_files(test_binder_provider_t)
+# For writing to flag file:
+allow test_binder_provider_t test_file_t:fifo_file rw_file_perms;
 
 #
-#################### Service Provider no call ################################
-#
-type test_binder_provider_no_call_t;
-domain_type(test_binder_provider_no_call_t)
-unconfined_runs_test(test_binder_provider_no_call_t)
-typeattribute test_binder_provider_no_call_t testdomain;
-typeattribute test_binder_provider_no_call_t binderdomain;
-allow test_binder_provider_no_call_t device_t:chr_file { ioctl open read write };
-allow_map(test_binder_provider_no_call_t, device_t, chr_file)
-fs_getattr_tmpfs(test_binder_provider_no_call_t)
-allow test_binder_provider_no_call_t tmpfs_t:file { read write open };
-allow_map(test_binder_provider_no_call_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_provider_no_call_t)
-fs_manage_tmpfs_files(test_binder_provider_no_call_t)
+#################### Service Provider no fd {use} ###########################
+# test 7
+type test_binder_provider_no_fd_t;
+domain_type(test_binder_provider_no_fd_t)
+unconfined_runs_test(test_binder_provider_no_fd_t)
+typeattribute test_binder_provider_no_fd_t testdomain;
+typeattribute test_binder_provider_no_fd_t binderdomain;
+allow test_binder_provider_no_fd_t test_binder_mgr_t:binder { call transfer };
+allow test_binder_client_t test_binder_provider_no_fd_t:binder { call impersonate };
+allow test_binder_provider_no_fd_t device_t:chr_file { ioctl open read write };
+allow_map(test_binder_provider_no_fd_t, device_t, chr_file)
+# For writing to flag file:
+allow test_binder_provider_no_fd_t test_file_t:fifo_file rw_file_perms;
 
 #
-#################### Service Provider no transfer #############################
-#
-type test_binder_provider_no_transfer_t;
-domain_type(test_binder_provider_no_transfer_t)
-unconfined_runs_test(test_binder_provider_no_transfer_t)
-typeattribute test_binder_provider_no_transfer_t testdomain;
-typeattribute test_binder_provider_no_transfer_t binderdomain;
-allow test_binder_provider_no_transfer_t test_binder_mgr_t:binder { call };
-allow test_binder_provider_no_transfer_t device_t:chr_file { ioctl open read write };
-allow_map(test_binder_provider_no_transfer_t, device_t, chr_file)
-fs_getattr_tmpfs(test_binder_provider_no_transfer_t)
-allow test_binder_provider_no_transfer_t tmpfs_t:file { read write open };
-allow_map(test_binder_provider_no_transfer_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_provider_no_transfer_t)
-fs_manage_tmpfs_files(test_binder_provider_no_transfer_t)
+################################# Client ####################################
+#
+type test_binder_client_t;
+domain_type(test_binder_client_t)
+unconfined_runs_test(test_binder_client_t)
+typeattribute test_binder_client_t testdomain;
+typeattribute test_binder_client_t binderdomain;
+allow test_binder_client_t test_binder_provider_t:binder { call impersonate };
+allow test_binder_client_t test_binder_mgr_t:binder { call };
+allow test_binder_client_t test_binder_provider_t:fd { use };
+allow test_binder_client_t device_t:chr_file { getattr ioctl open read write };
+allow_map(test_binder_client_t, device_t, chr_file)
 
 #
-#################### Service Provider no impersonate ##########################
-#
-type test_binder_provider_no_im_t;
-domain_type(test_binder_provider_no_im_t)
-unconfined_runs_test(test_binder_provider_no_im_t)
-typeattribute test_binder_provider_no_im_t testdomain;
-typeattribute test_binder_provider_no_im_t binderdomain;
-allow test_binder_provider_no_im_t self:binder { call };
-allow test_binder_provider_no_im_t test_binder_mgr_t:binder { call transfer };
-allow test_binder_provider_no_im_t device_t:chr_file { ioctl open read write };
-allow_map(test_binder_provider_no_im_t, device_t, chr_file)
-allow test_binder_provider_no_im_t test_binder_mgr_t:fd use;
-allow test_binder_provider_no_im_t device_t:chr_file getattr;
-fs_getattr_tmpfs(test_binder_provider_no_im_t)
-allow test_binder_provider_no_im_t tmpfs_t:file { read write open };
-allow_map(test_binder_provider_no_im_t, tmpfs_t, file)
-fs_manage_tmpfs_dirs(test_binder_provider_no_im_t)
-fs_manage_tmpfs_files(test_binder_provider_no_im_t)
+######################## Client No call Manager #############################
+#
+type test_binder_client_no_call_mgr_t;
+domain_type(test_binder_client_no_call_mgr_t)
+unconfined_runs_test(test_binder_client_no_call_mgr_t)
+typeattribute test_binder_client_no_call_mgr_t testdomain;
+typeattribute test_binder_client_no_call_mgr_t binderdomain;
+allow test_binder_client_no_call_mgr_t test_binder_provider_t:binder { call impersonate };
+allow test_binder_client_no_call_mgr_t device_t:chr_file { getattr ioctl open read write };
+allow_map(test_binder_client_no_call_mgr_t, device_t, chr_file)
+
+#
+################## Client No call Service Provider ##########################
+#
+type test_binder_client_no_call_sp_t;
+domain_type(test_binder_client_no_call_sp_t)
+unconfined_runs_test(test_binder_client_no_call_sp_t)
+typeattribute test_binder_client_no_call_sp_t testdomain;
+typeattribute test_binder_client_no_call_sp_t binderdomain;
+allow test_binder_mgr_t test_binder_client_no_call_sp_t:binder { transfer };
+allow test_binder_client_no_call_sp_t test_binder_mgr_t:binder { call };
+allow test_binder_client_no_call_sp_t device_t:chr_file { getattr ioctl open read write };
+allow_map(test_binder_client_no_call_sp_t, device_t, chr_file)
+
+#
+######################## Client No impersonate ##############################
+#
+type test_binder_client_no_im_t;
+domain_type(test_binder_client_no_im_t)
+unconfined_runs_test(test_binder_client_no_im_t)
+typeattribute test_binder_client_no_im_t testdomain;
+typeattribute test_binder_client_no_im_t binderdomain;
+allow test_binder_mgr_t test_binder_client_no_im_t:binder { transfer };
+allow test_binder_client_no_im_t test_binder_provider_t:binder { call };
+allow test_binder_client_no_im_t test_binder_mgr_t:binder { call };
+allow test_binder_client_no_im_t test_binder_provider_t:fd { use };
+allow test_binder_client_no_im_t device_t:chr_file { getattr ioctl open read write };
+allow_map(test_binder_client_no_im_t, device_t, chr_file)
+
+#
+########################## Client No transfer ###############################
+#
+type test_binder_client_no_transfer_t;
+domain_type(test_binder_client_no_transfer_t)
+unconfined_runs_test(test_binder_client_no_transfer_t)
+typeattribute test_binder_client_no_transfer_t testdomain;
+typeattribute test_binder_client_no_transfer_t binderdomain;
+allow test_binder_client_no_transfer_t test_binder_mgr_t:binder { call };
+allow test_binder_client_no_transfer_t test_binder_provider_t:binder { call impersonate };
+allow test_binder_client_no_transfer_t device_t:chr_file { getattr ioctl open read write };
+allow_map(test_binder_client_no_transfer_t, device_t, chr_file)
 
 #
-############ Allow these domains to be entered from sysadm domain ############
+########### Allow these domains to be entered from sysadm domain ############
 #
 miscfiles_domain_entry_test_files(binderdomain)
 userdom_sysadm_entry_spec_domtrans_to(binderdomain)
diff --git a/tests/binder/.gitignore b/tests/binder/.gitignore
index 37a2dd7..dc6ce20 100644
--- a/tests/binder/.gitignore
+++ b/tests/binder/.gitignore
@@ -1,3 +1,5 @@
 check_binder
-test_binder
-thread
+check_binderfs
+manager
+service_provider
+client
diff --git a/tests/binder/Makefile b/tests/binder/Makefile
index 0d76723..32f9a83 100644
--- a/tests/binder/Makefile
+++ b/tests/binder/Makefile
@@ -1,7 +1,18 @@
-TARGETS = check_binder test_binder
+# Required for local building
+INCLUDEDIR ?= /usr/include
 
+TARGETS = check_binder client manager service_provider
 LDLIBS += -lselinux -lrt
+DEPS = binder_common.c binder_common.h
+
+ifeq ($(shell test -e $(INCLUDEDIR)/linux/android/binderfs.h && echo true),true)
+CFLAGS += -DHAVE_BINDERFS
+TARGETS += check_binderfs
+endif
 
 all: $(TARGETS)
+
 clean:
 	rm -f $(TARGETS)
+
+$(TARGETS): $(DEPS)
diff --git a/tests/binder/binder_common.c b/tests/binder/binder_common.c
new file mode 100644
index 0000000..a240453
--- /dev/null
+++ b/tests/binder/binder_common.c
@@ -0,0 +1,155 @@
+/*
+ * This is a simple binder Service Manager/Service Provider that only uses
+ * the raw ioctl commands to test the SELinux binder permissions:
+ *     set_context_mgr, call, transfer, impersonate.
+ *
+ * Using binder test policy the following will be validated:
+ *    security_binder_set_context_mgr() binder { set_context_mgr }
+ *    security_binder_transaction()     binder { call impersonate }
+ *    security_binder_transfer_binder() binder { transfer }
+ *    security_binder_transfer_file()   fd { use }
+ *
+ * TODO security_binder_transfer_file() uses BPF if configured in kernel.
+ */
+
+#include "binder_common.h"
+
+const char *cmd_name(uint32_t cmd)
+{
+	switch (cmd) {
+	case BR_NOOP:
+		return "BR_NOOP";
+	case BR_TRANSACTION_COMPLETE:
+		return "BR_TRANSACTION_COMPLETE";
+	case BR_INCREFS:
+		return "BR_INCREFS";
+	case BR_ACQUIRE:
+		return "BR_ACQUIRE";
+	case BR_RELEASE:
+		return "BR_RELEASE";
+	case BR_DECREFS:
+		return "BR_DECREFS";
+	case BR_TRANSACTION:
+		return "BR_TRANSACTION";
+#if HAVE_BINDERFS
+	case BR_TRANSACTION_SEC_CTX:
+		return "BR_TRANSACTION_SEC_CTX";
+#endif
+	case BR_REPLY:
+		return "BR_REPLY";
+	case BR_FAILED_REPLY:
+		return "BR_FAILED_REPLY";
+	case BR_DEAD_REPLY:
+		return "BR_DEAD_REPLY";
+	case BR_DEAD_BINDER:
+		return "BR_DEAD_BINDER";
+	case BR_ERROR:
+		return "BR_ERROR";
+	/* fallthrough */
+	default:
+		return "Unknown Binder return code";
+	}
+}
+
+void print_trans_data(const struct binder_transaction_data *txn_in)
+{
+	const struct flat_binder_object *obj;
+	binder_size_t *offs = (binder_size_t *)
+			      (binder_uintptr_t)txn_in->data.ptr.offsets;
+	size_t count = txn_in->offsets_size / sizeof(binder_size_t);
+
+	printf("\thandle: %d\n", (uint32_t)txn_in->target.handle);
+	printf("\tcookie: %lld\n", txn_in->cookie);
+	switch (txn_in->code) {
+	case TEST_SERVICE_ADD:
+		printf("\tcode: TEST_SERVICE_ADD\n");
+		break;
+	case TEST_SERVICE_GET:
+		printf("\tcode: TEST_SERVICE_GET\n");
+		break;
+	case TEST_SERVICE_SEND_CLIENT_SP_FD:
+		printf("\tcode: TEST_SERVICE_SEND_CLIENT_SP_FD\n");
+		break;
+	default:
+		printf("Unknown binder_transaction_data->code: %x\n",
+		       txn_in->code);
+		return;
+	}
+
+	switch (txn_in->flags) {
+	case TF_ONE_WAY:
+		printf("\tflag: TF_ONE_WAY\n");
+		break;
+	case TF_ROOT_OBJECT:
+		printf("\tflag: TF_ROOT_OBJECT\n");
+		break;
+	case TF_STATUS_CODE:
+		printf("\tflag: TF_STATUS_CODE\n");
+		break;
+	case TF_ACCEPT_FDS:
+		printf("\tflag: TF_ACCEPT_FDS\n");
+		break;
+	default:
+		printf("Unknown flag: %x\n", txn_in->flags);
+		return;
+	}
+	printf("\tsender pid: %u\n", txn_in->sender_pid);
+	printf("\tsender euid: %u\n", txn_in->sender_euid);
+	printf("\tdata_size: %llu\n", txn_in->data_size);
+	printf("\toffsets_size: %llu\n", txn_in->offsets_size);
+
+	while (count--) {
+		obj = (const struct flat_binder_object *)
+		      (((char *)(binder_uintptr_t)txn_in->data.ptr.buffer) + *offs++);
+
+		switch (obj->hdr.type) {
+		case BINDER_TYPE_BINDER:
+			printf("\thdr: BINDER_TYPE_BINDER\n");
+			printf("\tbinder: %llx\n", obj->binder);
+			break;
+		case BINDER_TYPE_HANDLE:
+			printf("\thdr: BINDER_TYPE_HANDLE\n");
+			printf("\thandle: %x\n", obj->handle);
+			break;
+		case BINDER_TYPE_FD:
+			printf("\thdr: BINDER_TYPE_FD\n");
+			printf("\tfd: %x\n", obj->handle);
+			break;
+		default:
+			printf("Unknown header: %u\n", obj->hdr.type);
+			return;
+		}
+#if HAVE_BINDERFS
+		printf("\tflags: priority: 0x%x accept FDS: %s request security CTX: %s\n",
+		       obj->flags & FLAT_BINDER_FLAG_PRIORITY_MASK,
+		       obj->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS ? "YES" : "NO",
+		       obj->flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX ? "YES" : "NO");
+#else
+		printf("\tflags: priority: 0x%x accept FDS: %s\n",
+		       obj->flags & FLAT_BINDER_FLAG_PRIORITY_MASK,
+		       obj->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS ? "YES" : "NO");
+#endif
+		printf("\tcookie: %llx\n", obj->cookie);
+	}
+	fflush(stdout);
+}
+
+int binder_write(int fd, void *data, size_t len)
+{
+	struct binder_write_read bwr;
+	int result;
+
+	bwr.write_size = len;
+	bwr.write_consumed = 0;
+	bwr.write_buffer = (binder_uintptr_t)data;
+	bwr.read_size = 0;
+	bwr.read_consumed = 0;
+	bwr.read_buffer = 0;
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr, "binder_write ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+	}
+	return result;
+}
diff --git a/tests/binder/binder_common.h b/tests/binder/binder_common.h
new file mode 100644
index 0000000..bcf9e0c
--- /dev/null
+++ b/tests/binder/binder_common.h
@@ -0,0 +1,37 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <selinux/selinux.h>
+#include <linux/android/binder.h>
+#if HAVE_BINDERFS
+#include <linux/android/binderfs.h>
+#endif
+
+#define BINDER_DEV "/dev/binder"
+#define BINDERFS_DEV "/dev/binderfs"
+#define BINDERFS_NAME "binder-test"
+#define BINDERFS_CONTROL "/dev/binderfs/binder-control"
+#define BINDER_MMAP_SIZE 1024
+
+#define TEST_SERVICE_MANAGER_HANDLE 0
+/* These are the Binder txn->code values used by the Service Provider, Client
+ * and Manager to request/retrieve a binder handle or file descriptor.
+ */
+#define TEST_SERVICE_ADD		240616 /* Sent by Service Provider */
+#define TEST_SERVICE_GET		290317 /* Sent by Client */
+#define TEST_SERVICE_SEND_CLIENT_SP_FD	120419 /* Sent by Client */
+
+bool verbose;
+
+const char *cmd_name(uint32_t cmd);
+void print_trans_data(const struct binder_transaction_data *txn_in);
+int binder_write(int fd, void *data, size_t len);
diff --git a/tests/binder/check_binder.c b/tests/binder/check_binder.c
index 7b81a3d..2fc8d77 100644
--- a/tests/binder/check_binder.c
+++ b/tests/binder/check_binder.c
@@ -1,13 +1,4 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <linux/android/binder.h>
+#include "binder_common.h"
 
 static void usage(char *progname)
 {
@@ -21,10 +12,8 @@ static void usage(char *progname)
 int main(int argc, char **argv)
 {
 	int opt, result, fd;
-	char *driver = "/dev/binder";
-	bool verbose;
 	void *mapped;
-	size_t mapsize = 1024;
+	size_t mapsize = BINDER_MMAP_SIZE;
 	struct binder_version vers;
 
 	while ((opt = getopt(argc, argv, "v")) != -1) {
@@ -37,14 +26,15 @@ int main(int argc, char **argv)
 		}
 	}
 
-	fd = open(driver, O_RDWR | O_CLOEXEC);
+	fd = open(BINDER_DEV, O_RDWR | O_CLOEXEC);
 	if (fd < 0) {
 		fprintf(stderr, "Cannot open: %s error: %s\n",
-			driver, strerror(errno));
-		exit(1);
+			BINDER_DEV, strerror(errno));
+		result = 1;
+		return result;
 	}
 
-	/* Need this or no VMA error from kernel */
+	/* Need this or 'no VMA error' from kernel */
 	mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
 	if (mapped == MAP_FAILED) {
 		fprintf(stderr, "mmap error: %s\n", strerror(errno));
@@ -69,8 +59,7 @@ int main(int argc, char **argv)
 	}
 
 	if (verbose)
-		fprintf(stderr, "Binder kernel version: %d\n",
-			vers.protocol_version);
+		printf("Binder kernel version: %d\n", vers.protocol_version);
 
 brexit:
 	munmap(mapped, mapsize);
diff --git a/tests/binder/check_binderfs.c b/tests/binder/check_binderfs.c
new file mode 100644
index 0000000..b016755
--- /dev/null
+++ b/tests/binder/check_binderfs.c
@@ -0,0 +1,53 @@
+#include "binder_common.h"
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-v]\n"
+		"Where:\n\t"
+		"-v Print new device information.\n", progname);
+	exit(-1);
+}
+
+int main(int argc, char *argv[])
+{
+	int opt, fd, result;
+	size_t len;
+	struct binderfs_device device = { 0 };
+
+	while ((opt = getopt(argc, argv, "v")) != -1) {
+		switch (opt) {
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	len = strlen(BINDERFS_NAME);
+	memcpy(device.name, BINDERFS_NAME, len);
+
+	fd = open(BINDERFS_CONTROL, O_RDONLY | O_CLOEXEC);
+	if (fd < 0) {
+		fprintf(stderr, "Failed to open binder-control device: %s\n",
+			strerror(errno));
+		return 1;
+	}
+
+	result = ioctl(fd, BINDER_CTL_ADD, &device);
+	if (result < 0) {
+		fprintf(stderr, "Failed to allocate new binder device: %s\n",
+			strerror(errno));
+		result = 2;
+		goto brexit;
+	}
+
+	if (verbose)
+		printf("Allocated new binder device: major %d minor %d"
+		       " with name \"%s\"\n", device.major, device.minor,
+		       device.name);
+brexit:
+	close(fd);
+	return result;
+}
diff --git a/tests/binder/client.c b/tests/binder/client.c
new file mode 100644
index 0000000..e4e2a61
--- /dev/null
+++ b/tests/binder/client.c
@@ -0,0 +1,450 @@
+#include "binder_common.h"
+
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size);
+static int transactions_complete;
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-c] [-n] [-r replies] [-v]\n"
+		"Where:\n\t"
+		"-c  Use the number of replies for the BR_TRANSACTION_COMPLETE"
+		" count.\n\t"
+		"-n  Use the /dev/binderfs name service.\n\t"
+		"-r  Number of replies expected that depends on the test.\n\t"
+		"    It can be the number of BR_TRANSACTION_COMPLETE if\n\t"
+		"    the -c option is set or number of times to issue the\n\t"
+		"    ioctl - BINDER_WRITE_READ command if -c not set.\n\t"
+		"-v  Print context and command information.\n\t"
+		"\nNote: Ensure this boolean command is run when "
+		"testing after a reboot:\n\t"
+		"setsebool allow_domain_fd_use=0\n", progname);
+	exit(-1);
+}
+
+static void client_alarm(int sig)
+{
+	fprintf(stderr, "Client timer expired waiting for Binder reply\n");
+	exit(-1);
+}
+
+/* This retrieves the Service Providers file descriptor, then using this
+ * sends a simple transaction to trigger the impersonate permission.
+ */
+static void extract_fd_and_respond(const struct binder_transaction_data *txn_in)
+{
+	int result;
+	uint32_t cmd;
+	struct stat sb;
+	struct binder_write_read bwr;
+	const struct binder_fd_object *obj;
+	struct {
+		uint32_t cmd;
+		struct binder_transaction_data txn;
+	} __attribute__((packed)) writebuf;
+	unsigned int readbuf[32];
+
+	binder_size_t *offs = (binder_size_t *)
+			      (binder_uintptr_t)txn_in->data.ptr.offsets;
+
+	/* Get the binder_fd_object that contains the Service Providers
+	 * binder file descriptor.
+	 */
+	obj = (const struct binder_fd_object *)
+	      (((char *)(binder_uintptr_t)txn_in->data.ptr.buffer) + *offs);
+
+	if (obj->hdr.type != BINDER_TYPE_FD) {
+		fprintf(stderr, "Header not BINDER_TYPE_FD: %d\n",
+			obj->hdr.type);
+		exit(130);
+	}
+
+	/* fstat this just to see if a valid fd */
+	result = fstat(obj->fd, &sb);
+	if (result < 0) {
+		fprintf(stderr, "Not a valid fd: %s\n", strerror(errno));
+		exit(131);
+	}
+
+	if (verbose)
+		printf("Client retrieved Service Providers fd: %d st_dev: %ld\n",
+		       obj->fd, sb.st_dev);
+
+	memset(&writebuf, 0, sizeof(writebuf));
+	memset(readbuf, 0, sizeof(readbuf));
+	memset(&bwr, 0, sizeof(bwr));
+
+	/* Send response using Service Providers fd to trigger
+	 * impersonate check.
+	 */
+	writebuf.cmd = BC_TRANSACTION;
+	writebuf.txn.target.handle = txn_in->target.handle;
+	writebuf.txn.cookie = txn_in->cookie;
+	writebuf.txn.code = txn_in->code;
+	writebuf.txn.flags = TF_ONE_WAY;
+
+	writebuf.txn.data_size = 0;
+	writebuf.txn.data.ptr.buffer = (binder_uintptr_t)NULL;
+	writebuf.txn.data.ptr.offsets = (binder_uintptr_t)NULL;
+	writebuf.txn.offsets_size = 0;
+
+	bwr.write_size = sizeof(writebuf);
+	bwr.write_consumed = 0;
+	bwr.write_buffer = (binder_uintptr_t)&writebuf;
+	bwr.read_size = sizeof(readbuf);
+	bwr.read_consumed = 0;
+	bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+	result = ioctl(obj->fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Client ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		exit(132);
+	}
+
+	if (verbose)
+		printf("Client read_consumed: %lld\n",
+		       bwr.read_consumed);
+
+	cmd = binder_parse(obj->fd, (binder_uintptr_t)readbuf,
+			   bwr.read_consumed);
+
+	if (cmd == BR_FAILED_REPLY ||
+	    cmd == BR_DEAD_REPLY ||
+	    cmd == BR_DEAD_BINDER) {
+		fprintf(stderr, "Client %s() failing command %s, exiting.\n",
+			__func__, cmd_name(cmd));
+		exit(133);
+	}
+
+	if (verbose)
+		printf("Client sent transaction using Service Providers FD: %d\n",
+		       obj->fd);
+}
+
+static void request_service_provider_fd(int fd, uint32_t handle)
+{
+	int result;
+	uint32_t cmd;
+	struct binder_write_read bwr;
+	struct {
+		uint32_t cmd;
+		struct binder_transaction_data txn;
+	} __attribute__((packed)) writebuf;
+	unsigned int readbuf[32];
+
+	memset(&writebuf, 0, sizeof(writebuf));
+	memset(readbuf, 0, sizeof(readbuf));
+	memset(&bwr, 0, sizeof(bwr));
+
+	writebuf.cmd = BC_TRANSACTION;
+	writebuf.txn.target.handle = handle;
+	writebuf.txn.cookie = 0;
+	writebuf.txn.code = TEST_SERVICE_SEND_CLIENT_SP_FD;
+	writebuf.txn.flags = TF_ACCEPT_FDS;
+
+	writebuf.txn.data_size = 0;
+	writebuf.txn.data.ptr.buffer = (binder_uintptr_t)NULL;
+	writebuf.txn.data.ptr.offsets = (binder_uintptr_t)NULL;
+	writebuf.txn.offsets_size = 0;
+
+	bwr.write_size = sizeof(writebuf);
+	bwr.write_consumed = 0;
+	bwr.write_buffer = (binder_uintptr_t)&writebuf;
+	bwr.read_size = sizeof(readbuf);
+	bwr.read_consumed = 0;
+	bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+	if (verbose)
+		printf("Client sending transaction SEND_CLIENT_YOUR_BINDER_FD to handle: %d\n",
+		       handle);
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr, "Client ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		exit(140);
+	}
+
+	cmd = binder_parse(fd, (binder_uintptr_t)readbuf, bwr.read_consumed);
+	if (cmd == BR_FAILED_REPLY ||
+	    cmd == BR_DEAD_REPLY ||
+	    cmd == BR_DEAD_BINDER) {
+		fprintf(stderr, "Client %s() failing command %s, exiting.\n",
+			__func__, cmd_name(cmd));
+		exit(141);
+	}
+}
+
+static void extract_handle_and_acquire(int fd,
+				       struct binder_transaction_data *txn_in)
+{
+	int result;
+	uint32_t acmd[2];
+	struct binder_write_read bwr;
+	const struct flat_binder_object *obj;
+	binder_size_t *offs = (binder_size_t *)
+			      (binder_uintptr_t)txn_in->data.ptr.offsets;
+
+	/* Get the fbo that contains the Service Provider's Handle. */
+	obj = (const struct flat_binder_object *)
+	      (((char *)(binder_uintptr_t)txn_in->data.ptr.buffer) + *offs);
+
+	if (obj->hdr.type != BINDER_TYPE_HANDLE) {
+		fprintf(stderr, "Client - Header not BINDER_TYPE_HANDLE: %d\n",
+			obj->hdr.type);
+		exit(150);
+	}
+
+	acmd[0] = BC_ACQUIRE;
+	acmd[1] = obj->handle;
+
+	memset(&bwr, 0, sizeof(bwr));
+	bwr.write_buffer = (binder_uintptr_t)&acmd;
+	bwr.write_size = sizeof(acmd);
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Client ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		exit(151);
+	}
+
+	if (verbose)
+		printf("Client acquired binder handle: %d for Service Provider\n",
+		       obj->handle);
+
+	/* Now get their fd */
+	request_service_provider_fd(fd, obj->handle);
+
+}
+
+/* Parse response, reply as required and then return last CMD */
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
+{
+	binder_uintptr_t end = ptr + size;
+	uint32_t cmd;
+
+	while (ptr < end) {
+		cmd = *(uint32_t *)ptr;
+		ptr += sizeof(uint32_t);
+
+		if (verbose)
+			printf("Client command: %s\n", cmd_name(cmd));
+
+		switch (cmd) {
+		case BR_NOOP:
+			break;
+		case BR_TRANSACTION_COMPLETE:
+			transactions_complete++;
+			break;
+		case BR_INCREFS:
+		case BR_ACQUIRE:
+		case BR_RELEASE:
+		case BR_DECREFS:
+			ptr += sizeof(const struct binder_ptr_cookie);
+			break;
+		case BR_TRANSACTION: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Client BR_TRANSACTION data:\n");
+				print_trans_data(txn);
+			}
+
+			ptr += sizeof(*txn);
+			break;
+		}
+		case BR_REPLY: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Client BR_REPLY data:\n");
+				print_trans_data(txn);
+			}
+
+			if (txn->code == TEST_SERVICE_GET)
+				extract_handle_and_acquire(fd, txn);
+
+			if (txn->code == TEST_SERVICE_SEND_CLIENT_SP_FD)
+				extract_fd_and_respond(txn);
+
+			ptr += sizeof(*txn);
+			break;
+		}
+		case BR_DEAD_BINDER:
+		case BR_FAILED_REPLY:
+		case BR_DEAD_REPLY:
+			break;
+		case BR_ERROR:
+			ptr += sizeof(uint32_t);
+			break;
+		default:
+			if (verbose)
+				printf("Client parsed unknown command: %d\n",
+				       cmd);
+			exit(160);
+		}
+	}
+	fflush(stdout);
+	return cmd;
+}
+
+int main(int argc, char **argv)
+{
+	int opt, result, fd, client_replies = 0, ioctl_wr = 0;
+	bool name = false;
+	bool use_transactions_complete = false;
+	uint32_t cmd;
+	pid_t pid;
+	char *context;
+	char dev_str[128];
+	void *map_base;
+	size_t map_size = BINDER_MMAP_SIZE;
+	struct binder_write_read bwr;
+	struct {
+		uint32_t cmd;
+		struct binder_transaction_data txn;
+	} __attribute__((packed)) writebuf;
+	unsigned int readbuf[32];
+
+	transactions_complete = 0;
+
+	while ((opt = getopt(argc, argv, "cnr:v")) != -1) {
+		switch (opt) {
+		case 'c':
+			use_transactions_complete = true;
+			break;
+		case 'n':
+			name = true;
+			break;
+		case 'r':
+			client_replies = atoi(optarg);
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	/* Get our context and pid */
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Client failed to obtain SELinux context\n");
+		exit(120);
+	}
+	pid = getpid();
+
+	if (verbose) {
+		printf("Client PID: %d Process context:\n\t%s\n",
+		       pid, context);
+	}
+	free(context);
+
+	if (name)
+		result = sprintf(dev_str, "%s/%s", BINDERFS_DEV, BINDERFS_NAME);
+	else
+		result = sprintf(dev_str, "%s", BINDER_DEV);
+
+	if (result < 0) {
+		fprintf(stderr, "Manager failed to obtain Binder dev name\n");
+		exit(121);
+	}
+
+	fd = open(dev_str, O_RDWR | O_CLOEXEC);
+	if (fd < 0) {
+		fprintf(stderr, "Cannot open %s error: %s\n", dev_str,
+			strerror(errno));
+		exit(122);
+	}
+
+	map_base = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (map_base == MAP_FAILED) {
+		fprintf(stderr, "mmap error: %s\n", strerror(errno));
+		close(fd);
+		exit(123);
+	}
+
+	memset(&bwr, 0, sizeof(bwr));
+	memset(&writebuf, 0, sizeof(writebuf));
+	memset(readbuf, 0, sizeof(readbuf));
+
+	writebuf.cmd = BC_TRANSACTION;
+	writebuf.txn.target.handle = TEST_SERVICE_MANAGER_HANDLE;
+	writebuf.txn.cookie = 0;
+	writebuf.txn.code = TEST_SERVICE_GET;
+	writebuf.txn.flags = TF_ACCEPT_FDS;
+
+	writebuf.txn.data_size = 0;
+	writebuf.txn.offsets_size = 0;
+
+	writebuf.txn.data.ptr.buffer = (binder_uintptr_t)NULL;
+	writebuf.txn.data.ptr.offsets = (binder_uintptr_t)NULL;
+
+	bwr.write_buffer = (binder_uintptr_t)&writebuf;
+	bwr.write_size = sizeof(writebuf);
+	bwr.write_consumed = 0;
+
+	if (verbose)
+		printf("Client sending transaction to Manager - TEST_SERVICE_GET\n");
+
+	/* Set an alarm just in case Binder does not reply when sitting
+	 * on the ioctl BINDER_WRITE_READ
+	 */
+	signal(SIGALRM, client_alarm);
+	alarm(10);
+
+	/* Each Client test expects a different number of replies */
+	while (true) {
+		memset(readbuf, 0, sizeof(readbuf));
+		bwr.read_size = sizeof(readbuf);
+		bwr.read_consumed = 0;
+		bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+		result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+		if (result < 0) {
+			fprintf(stderr,
+				"Client ioctl BINDER_WRITE_READ error: %s\n",
+				strerror(errno));
+			result = 124;
+			goto brexit;
+		}
+		ioctl_wr++;
+
+		if (verbose)
+			printf("Client read_consumed: %lld\n",
+			       bwr.read_consumed);
+
+		cmd = binder_parse(fd, (binder_uintptr_t)readbuf,
+				   bwr.read_consumed);
+
+		if (cmd == BR_FAILED_REPLY ||
+		    cmd == BR_DEAD_REPLY ||
+		    cmd == BR_DEAD_BINDER) {
+			fprintf(stderr, "Client %s() failing command %s, exiting.\n",
+				__func__, cmd_name(cmd));
+			result = 125;
+			goto brexit;
+		}
+
+		result = 0;
+		if (use_transactions_complete &&
+		    transactions_complete == client_replies)
+			break;
+		else if (!use_transactions_complete &&
+			 ioctl_wr == client_replies)
+			break;
+	}
+
+brexit:
+	munmap(map_base, map_size);
+	close(fd);
+
+	return result;
+}
diff --git a/tests/binder/manager.c b/tests/binder/manager.c
new file mode 100644
index 0000000..9922183
--- /dev/null
+++ b/tests/binder/manager.c
@@ -0,0 +1,362 @@
+#include "binder_common.h"
+
+/* Store the only service provider handle here. */
+uint32_t sp_handle;
+
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size);
+static void reply_with_handle(int fd, struct binder_transaction_data *txn_in);
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-f file] [-n] [-v]\n"
+		"Where:\n\t"
+		"-f  Write a line to the file when listening starts.\n\t"
+		"-n  Use the /dev/binderfs name service.\n\t"
+		"-v  Print context and command information.\n\t"
+		"\nNote: Ensure this boolean command is run when "
+		"testing after a reboot:\n\t"
+		"setsebool allow_domain_fd_use=0\n", progname);
+	exit(-1);
+}
+
+static void do_service_manager(int fd, struct binder_transaction_data *txn_in)
+{
+	int result;
+	const struct flat_binder_object *obj;
+	struct binder_write_read bwr;
+	uint32_t acmd[2];
+	binder_size_t *offs;
+
+	struct {
+		uint32_t cmd_reply;
+		struct binder_transaction_data txn;
+	} __attribute__((packed)) reply;
+
+	switch (txn_in->code) {
+	case TEST_SERVICE_ADD:
+		offs = (binder_size_t *)(binder_uintptr_t)txn_in->data.ptr.offsets;
+
+		/* Get fbo that contains the Service Providers handle. */
+		obj = (const struct flat_binder_object *)
+		      (((char *)(binder_uintptr_t)txn_in->data.ptr.buffer) + *offs);
+
+		if (obj->hdr.type == BINDER_TYPE_HANDLE) {
+			sp_handle = obj->handle;
+
+			if (verbose)
+				printf("Manager has TEST_SERVICE_ADD obj->handle: %d\n",
+				       sp_handle);
+		} else {
+			fprintf(stderr, "Manager failed to obtain a handle\n");
+			exit(20);
+		}
+
+		acmd[0] = BC_ACQUIRE;
+		acmd[1] = obj->handle;
+
+		memset(&bwr, 0, sizeof(bwr));
+		bwr.write_buffer = (binder_uintptr_t)&acmd;
+		bwr.write_size = sizeof(acmd);
+
+		result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+		if (result < 0) {
+			fprintf(stderr,
+				"Manager ioctl BINDER_WRITE_READ error: %s\n",
+				strerror(errno));
+			exit(21);
+		}
+
+		if (verbose)
+			printf("Manager acquired binder handle: %d for Service Provider\n",
+			       sp_handle);
+
+		/* Inform the Service Provider of outcome. */
+		reply.cmd_reply = BC_REPLY;
+		reply.txn.target.ptr = 0;
+		reply.txn.cookie = txn_in->cookie;
+		reply.txn.code = txn_in->code;
+		reply.txn.flags = TF_STATUS_CODE;
+		reply.txn.data_size = sizeof(int);
+		reply.txn.offsets_size = 0;
+		reply.txn.data.ptr.buffer = (binder_uintptr_t)&result;
+		reply.txn.data.ptr.offsets = 0;
+		binder_write(fd, &reply, sizeof(reply));
+		break;
+	case TEST_SERVICE_GET:
+		if (verbose)
+			printf("Manager has TEST_SERVICE_GET handle: %d\n",
+			       sp_handle);
+
+		reply_with_handle(fd, txn_in);
+
+		break;
+	case TEST_SERVICE_SEND_CLIENT_SP_FD:
+		if (verbose)
+			printf("Manager Rx'ed SEND_CLIENT_YOUR_BINDER_FD for handle: %d\n",
+			       txn_in->target.handle);
+		break;
+	default:
+		fprintf(stderr, "Manager unknown txn->code: %d for handle: %d\n",
+			txn_in->code, txn_in->target.handle);
+		exit(22);
+	}
+}
+
+static void reply_with_handle(int fd, struct binder_transaction_data *txn_in)
+{
+	int result;
+	unsigned int writebuf[1024];
+	binder_size_t offset = 0;
+	struct flat_binder_object obj;
+	struct binder_write_read bwr;
+	struct binder_transaction_data *txn;
+
+	if (verbose)
+		printf("Manager sending BC_REPLY to Client with handle\n");
+
+	memset(&writebuf, 0, sizeof(writebuf));
+	memset(&obj, 0, sizeof(obj));
+	memset(&bwr, 0, sizeof(bwr));
+
+	writebuf[0] = BC_REPLY;
+	txn = (struct binder_transaction_data *)(&writebuf[1]);
+	memset(txn, 0, sizeof(*txn));
+	txn->target.handle = txn_in->target.handle;
+	txn->cookie = txn_in->cookie;
+	txn->code = txn_in->code;
+	txn->flags = TF_ACCEPT_FDS;
+
+	obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+	obj.hdr.type = BINDER_TYPE_HANDLE;
+	obj.handle = sp_handle;
+	obj.cookie = 0;
+
+	txn->data_size = sizeof(obj);
+	txn->data.ptr.buffer = (binder_uintptr_t)&obj;
+	txn->data.ptr.offsets = (binder_uintptr_t)&offset;
+	txn->offsets_size = sizeof(offset);
+
+	bwr.write_buffer = (binder_uintptr_t)writebuf;
+	bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn);
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr, "Manager ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		exit(30);
+	}
+
+	if (verbose)
+		printf("Manager sent Service Provider handle: %d to Client\n",
+		       sp_handle);
+}
+
+/* Parse response, reply as required and then return last CMD */
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
+{
+	binder_uintptr_t end = ptr + size;
+	uint32_t cmd;
+
+	while (ptr < end) {
+		cmd = *(uint32_t *)ptr;
+		ptr += sizeof(uint32_t);
+
+		if (verbose)
+			printf("Manager command: %s\n", cmd_name(cmd));
+
+		switch (cmd) {
+		case BR_NOOP:
+			break;
+		case BR_TRANSACTION_COMPLETE:
+			break;
+		case BR_INCREFS:
+		case BR_ACQUIRE:
+		case BR_RELEASE:
+		case BR_DECREFS:
+			ptr += sizeof(const struct binder_ptr_cookie);
+			break;
+		case BR_TRANSACTION: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Manager BR_TRANSACTION data:\n");
+				print_trans_data(txn);
+			}
+
+			do_service_manager(fd, txn);
+			ptr += sizeof(*txn);
+			break;
+		}
+		case BR_REPLY: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Manager BR_REPLY data:\n");
+				print_trans_data(txn);
+			}
+
+			ptr += sizeof(*txn);
+			break;
+		}
+		case BR_DEAD_BINDER:
+		case BR_FAILED_REPLY:
+		case BR_DEAD_REPLY:
+			break;
+		case BR_ERROR:
+			ptr += sizeof(uint32_t);
+			break;
+		default:
+			if (verbose)
+				printf("Manager parsed unknown command: %d\n",
+				       cmd);
+			exit(40);
+		}
+	}
+	fflush(stdout);
+	return cmd;
+}
+
+int main(int argc, char **argv)
+{
+	int opt, result, fd;
+	bool name = false;
+	pid_t pid;
+	char *context;
+	char *flag_file = NULL;
+	char dev_str[128];
+	FILE *flag_fd;
+	void *map_base;
+	size_t map_size = BINDER_MMAP_SIZE;
+	struct binder_write_read bwr;
+	unsigned int readbuf[32];
+
+	while ((opt = getopt(argc, argv, "f:nv")) != -1) {
+		switch (opt) {
+		case 'f':
+			flag_file = optarg;
+			break;
+		case 'n':
+			name = true;
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	/* Get our context and pid */
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Manager failed to obtain SELinux context\n");
+		exit(10);
+	}
+	pid = getpid();
+
+	if (verbose) {
+		printf("Manager PID: %d Process context:\n\t%s\n",
+		       pid, context);
+	}
+	free(context);
+
+	if (name)
+		result = sprintf(dev_str, "%s/%s", BINDERFS_DEV, BINDERFS_NAME);
+	else
+		result = sprintf(dev_str, "%s", BINDER_DEV);
+
+	if (result < 0) {
+		fprintf(stderr, "Manager failed to obtain Binder dev name\n");
+		exit(11);
+	}
+
+	fd = open(dev_str, O_RDWR | O_CLOEXEC);
+	if (fd < 0) {
+		fprintf(stderr, "Manager cannot open %s error: %s\n",
+			dev_str, strerror(errno));
+		exit(12);
+	}
+
+	map_base = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (map_base == MAP_FAILED) {
+		fprintf(stderr, "Manager mmap error: %s\n", strerror(errno));
+		close(fd);
+		exit(13);
+	}
+
+	result = ioctl(fd, BINDER_SET_CONTEXT_MGR, 0);
+	if (result < 0) {
+		fprintf(stderr,
+			"Manager failed to become context manager: %s\n",
+			strerror(errno));
+		result = 14;
+		goto brexit;
+	}
+
+	if (flag_file) {
+		flag_fd = fopen(flag_file, "w");
+		if (!flag_fd) {
+			fprintf(stderr,
+				"Manager failed to open %s: %s\n",
+				flag_file, strerror(errno));
+			result = 15;
+			goto brexit;
+		}
+		fprintf(flag_fd, "listening\n");
+		fclose(flag_fd);
+	}
+
+	memset(readbuf, 0, sizeof(readbuf));
+	memset(&bwr, 0, sizeof(bwr));
+
+	readbuf[0] = BC_ENTER_LOOPER;
+	bwr.write_size = sizeof(readbuf[0]);
+	bwr.write_consumed = 0;
+	bwr.write_buffer = (binder_uintptr_t)readbuf;
+	bwr.read_size = 0;
+	bwr.read_consumed = 0;
+	bwr.read_buffer = 0;
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Manager ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		result = 16;
+		goto brexit;
+	}
+
+	while (true) {
+		memset(readbuf, 0, sizeof(readbuf));
+		bwr.read_size = sizeof(readbuf);
+		bwr.read_consumed = 0;
+		bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+		result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+		if (result < 0) {
+			fprintf(stderr,
+				"Manager ioctl BINDER_WRITE_READ error: %s\n",
+				strerror(errno));
+			result = 17;
+			goto brexit;
+		}
+
+		if (bwr.read_consumed == 0)
+			continue;
+
+		if (verbose)
+			printf("Manager read_consumed: %lld\n",
+			       bwr.read_consumed);
+
+		binder_parse(fd, (binder_uintptr_t)readbuf, bwr.read_consumed);
+	}
+
+brexit:
+	munmap(map_base, map_size);
+	close(fd);
+
+	return result;
+}
diff --git a/tests/binder/service_provider.c b/tests/binder/service_provider.c
new file mode 100644
index 0000000..2873af8
--- /dev/null
+++ b/tests/binder/service_provider.c
@@ -0,0 +1,404 @@
+#include "binder_common.h"
+
+static char *expected_ctx;
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size);
+
+static void usage(char *progname)
+{
+	fprintf(stderr,
+		"usage:  %s [-e expected_ctx] [-f file] [-n] [-v]\n"
+		"Where:\n\t"
+		"-e  Expected security context.\n\t"
+		"-f  Write a line to the file when listening starts.\n\t"
+		"-n  Use the /dev/binderfs name service.\n\t"
+		"-v  Print context and command information.\n\t"
+		"\nNote: Ensure this boolean command is run when "
+		"testing after a reboot:\n\t"
+		"setsebool allow_domain_fd_use=0\n", progname);
+	exit(-1);
+}
+
+static void request_service_provider_fd(int fd,
+					struct binder_transaction_data *txn_in)
+{
+	int result;
+	unsigned int writebuf[1024];
+	struct binder_fd_object obj;
+	binder_size_t offset = 0;
+	struct binder_write_read bwr;
+	struct binder_transaction_data *txn;
+
+	if (txn_in->flags == TF_ONE_WAY && verbose) {
+		printf("Service Provider no reply to BC_TRANSACTION as flags = TF_ONE_WAY\n");
+		return;
+	}
+
+	if (verbose)
+		printf("Service Provider sending BC_REPLY with its FD\n");
+
+	memset(writebuf, 0, sizeof(writebuf));
+	memset(&bwr, 0, sizeof(bwr));
+	memset(&obj, 0, sizeof(obj));
+
+	writebuf[0] = BC_REPLY;
+	txn = (struct binder_transaction_data *)(&writebuf[1]);
+	memset(txn, 0, sizeof(*txn));
+	txn->target.handle = txn_in->target.handle;
+	txn->cookie = txn_in->cookie;
+	txn->code = txn_in->code;
+	txn->flags = TF_ACCEPT_FDS;
+
+	obj.hdr.type = BINDER_TYPE_FD;
+#if HAVE_BINDERFS
+	obj.pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS |
+			FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+#else
+	obj.pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+#endif
+	obj.cookie = txn->cookie;
+	/* The Service Providers binder fd is used for testing as it allows
+	 * policy to set whether the Service Provider and Client can be
+	 * allowed access (fd use) or not.
+	 * This also allows a check for the impersonate permission later as
+	 * the Client will use the Service Provider fd to send a transaction.
+	 */
+	obj.fd = fd;
+
+	if (verbose)
+		printf("Service Provider handle: %d and its FD: %d\n",
+		       txn->target.handle, fd);
+
+	txn->data_size = sizeof(obj);
+	txn->data.ptr.buffer = (binder_uintptr_t)&obj;
+	txn->data.ptr.offsets = (binder_uintptr_t)&offset;
+	txn->offsets_size = sizeof(offset);
+
+	bwr.write_buffer = (binder_uintptr_t)writebuf;
+	bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn);
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		exit(70);
+	}
+}
+
+/* Parse response, reply as required and then return last CMD */
+static int binder_parse(int fd, binder_uintptr_t ptr, binder_size_t size)
+{
+	binder_uintptr_t end = ptr + size;
+	uint32_t cmd;
+
+	while (ptr < end) {
+		cmd = *(uint32_t *)ptr;
+		ptr += sizeof(uint32_t);
+
+		if (verbose)
+			printf("Service Provider command: %s\n",
+			       cmd_name(cmd));
+
+		switch (cmd) {
+		case BR_NOOP:
+			break;
+		case BR_TRANSACTION_COMPLETE:
+			break;
+		case BR_INCREFS:
+		case BR_ACQUIRE:
+		case BR_RELEASE:
+		case BR_DECREFS:
+			ptr += sizeof(const struct binder_ptr_cookie);
+			break;
+		case BR_TRANSACTION: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Service Provider BR_TRANSACTION data:\n");
+				print_trans_data(txn);
+			}
+
+			if (txn->code == TEST_SERVICE_SEND_CLIENT_SP_FD)
+				request_service_provider_fd(fd, txn);
+
+			ptr += sizeof(*txn);
+			break;
+		}
+#if HAVE_BINDERFS
+		case BR_TRANSACTION_SEC_CTX: {
+			struct binder_transaction_data_secctx *txn_ctx =
+				(struct binder_transaction_data_secctx *)ptr;
+
+			if (verbose) {
+				printf("\tclient context:\n\t\t%s\n",
+				       (char *)txn_ctx->secctx);
+				print_trans_data(&txn_ctx->transaction_data);
+			}
+
+			if (expected_ctx) {
+				int result = strcmp(expected_ctx,
+						    (char *)txn_ctx->secctx);
+				if (result) {
+					fprintf(stderr, "Service Provider received incorrect context:\n");
+					fprintf(stderr, "Expected: %s\nReceived: %s\n",
+						expected_ctx,
+						(char *)txn_ctx->secctx);
+					exit(80);
+				}
+			}
+
+			if (txn_ctx->transaction_data.code ==
+			    TEST_SERVICE_SEND_CLIENT_SP_FD)
+				request_service_provider_fd(fd,
+							    &txn_ctx->transaction_data);
+
+			ptr += sizeof(*txn_ctx);
+			break;
+		}
+#endif
+		case BR_REPLY: {
+			struct binder_transaction_data *txn =
+				(struct binder_transaction_data *)ptr;
+
+			if (verbose) {
+				printf("Service Provider BR_REPLY data:\n");
+				print_trans_data(txn);
+			}
+
+			ptr += sizeof(*txn);
+			break;
+		}
+		case BR_DEAD_BINDER:
+		case BR_FAILED_REPLY:
+		case BR_DEAD_REPLY:
+			break;
+		case BR_ERROR:
+			ptr += sizeof(uint32_t);
+			break;
+		default:
+			if (verbose)
+				printf("Service Provider parsed unknown command: %d\n",
+				       cmd);
+			exit(81);
+		}
+	}
+	fflush(stdout);
+	return cmd;
+}
+
+int main(int argc, char **argv)
+{
+	int opt, result, fd;
+	bool name = false;
+	uint32_t cmd;
+	pid_t pid;
+	char *context;
+	char *flag_file = NULL;
+	char dev_str[128];
+	FILE *flag_fd;
+	void *map_base;
+	size_t map_size = BINDER_MMAP_SIZE;
+	binder_size_t offset = 0;
+	struct binder_write_read bwr;
+	struct flat_binder_object obj;
+	struct {
+		uint32_t cmd;
+		struct binder_transaction_data txn;
+	} __attribute__((packed)) writebuf;
+	unsigned int readbuf[32];
+
+	expected_ctx = NULL;
+
+	while ((opt = getopt(argc, argv, "e:f:nv")) != -1) {
+		switch (opt) {
+		case 'e':
+			expected_ctx = optarg;
+			break;
+		case 'f':
+			flag_file = optarg;
+			break;
+		case 'n':
+			name = true;
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+
+	/* Get our context and pid */
+	result = getcon(&context);
+	if (result < 0) {
+		fprintf(stderr, "Service Provider failed to obtain SELinux context\n");
+		exit(60);
+	}
+	pid = getpid();
+
+	if (verbose) {
+		printf("Service Provider PID: %d Process context:\n\t%s\n",
+		       pid, context);
+	}
+	free(context);
+
+	if (name)
+		result = sprintf(dev_str, "%s/%s", BINDERFS_DEV, BINDERFS_NAME);
+	else
+		result = sprintf(dev_str, "%s", BINDER_DEV);
+
+	if (result < 0) {
+		fprintf(stderr, "Manager failed to obtain Binder dev name\n");
+		exit(61);
+	}
+
+	fd = open(dev_str, O_RDWR | O_CLOEXEC);
+	if (fd < 0) {
+		fprintf(stderr, "Cannot open %s error: %s\n", dev_str,
+			strerror(errno));
+		exit(62);
+	}
+
+	map_base = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (map_base == MAP_FAILED) {
+		fprintf(stderr, "mmap error: %s\n", strerror(errno));
+		close(fd);
+		exit(63);
+	}
+
+	if (flag_file) {
+		flag_fd = fopen(flag_file, "w");
+		if (!flag_fd) {
+			fprintf(stderr,
+				"Service Provider failed to open %s: %s\n",
+				flag_file, strerror(errno));
+			result = 64;
+			goto brexit;
+		}
+		fprintf(flag_fd, "listening\n");
+		fclose(flag_fd);
+	}
+
+	memset(&writebuf, 0, sizeof(writebuf));
+	memset(&obj, 0, sizeof(obj));
+	memset(readbuf, 0, sizeof(readbuf));
+
+	writebuf.cmd = BC_TRANSACTION;
+	writebuf.txn.target.handle = TEST_SERVICE_MANAGER_HANDLE;
+	writebuf.txn.cookie = 0;
+	writebuf.txn.code = TEST_SERVICE_ADD;
+	writebuf.txn.flags = TF_ROOT_OBJECT;
+
+	obj.hdr.type = BINDER_TYPE_BINDER;
+#if HAVE_BINDERFS
+	obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS |
+		    FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+#else
+	obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+#endif
+	obj.binder = (binder_uintptr_t)NULL;
+	obj.cookie = 0;
+
+	writebuf.txn.data_size = sizeof(obj);
+	writebuf.txn.offsets_size = sizeof(offset);
+
+	writebuf.txn.data.ptr.buffer = (binder_uintptr_t)&obj;
+	writebuf.txn.data.ptr.offsets = (binder_uintptr_t)&offset;
+
+	bwr.write_buffer = (binder_uintptr_t)&writebuf;
+	bwr.write_size = sizeof(writebuf);
+	bwr.write_consumed = 0;
+
+	if (verbose)
+		printf("Service Provider sending transaction to Manager - TEST_SERVICE_ADD\n");
+
+	bwr.read_size = sizeof(readbuf);
+	bwr.read_consumed = 0;
+	bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		result = 65;
+		goto brexit;
+	}
+
+	if (verbose)
+		printf("Service Provider read_consumed: %lld\n",
+		       bwr.read_consumed);
+
+	cmd = binder_parse(fd, (binder_uintptr_t)readbuf,
+			   bwr.read_consumed);
+
+	if (cmd == BR_FAILED_REPLY ||
+	    cmd == BR_DEAD_REPLY ||
+	    cmd == BR_DEAD_BINDER) {
+		fprintf(stderr, "Service Provider %s() failing command %s, exiting.\n",
+			__func__, cmd_name(cmd));
+		result = 66;
+		goto brexit;
+	}
+
+	/* Service Provider loops on commands */
+	memset(readbuf, 0, sizeof(readbuf));
+	readbuf[0] = BC_ENTER_LOOPER;
+	bwr.write_size = sizeof(readbuf[0]);
+	bwr.write_consumed = 0;
+	bwr.write_buffer = (binder_uintptr_t)readbuf;
+
+	bwr.read_size = 0;
+	bwr.read_consumed = 0;
+	bwr.read_buffer = 0;
+
+	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+	if (result < 0) {
+		fprintf(stderr,
+			"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
+			strerror(errno));
+		result = 67;
+		goto brexit;
+	}
+
+	while (true) {
+		memset(readbuf, 0, sizeof(readbuf));
+		bwr.read_size = sizeof(readbuf);
+		bwr.read_consumed = 0;
+		bwr.read_buffer = (binder_uintptr_t)readbuf;
+
+		result = ioctl(fd, BINDER_WRITE_READ, &bwr);
+		if (result < 0) {
+			fprintf(stderr,
+				"Service Provider ioctl BINDER_WRITE_READ error: %s\n",
+				strerror(errno));
+			result = 68;
+			goto brexit;
+		}
+
+		if (bwr.read_consumed == 0)
+			continue;
+
+		if (verbose)
+			printf("Service Provider read_consumed: %lld\n",
+			       bwr.read_consumed);
+
+		cmd = binder_parse(fd, (binder_uintptr_t)readbuf, bwr.read_consumed);
+
+		if (cmd == BR_FAILED_REPLY ||
+		    cmd == BR_DEAD_REPLY ||
+		    cmd == BR_DEAD_BINDER) {
+			fprintf(stderr, "Service Provider %s() failing command %s, exiting.\n",
+				__func__, cmd_name(cmd));
+			result = 69;
+			goto brexit;
+		}
+	}
+
+brexit:
+	munmap(map_base, map_size);
+	close(fd);
+
+	return result;
+}
diff --git a/tests/binder/test b/tests/binder/test
index e8aaec4..2ccaa23 100755
--- a/tests/binder/test
+++ b/tests/binder/test
@@ -5,7 +5,11 @@ BEGIN {
     $basedir = $0;
     $basedir =~ s|(.*)/[^/]*|$1|;
 
-    # allow binder info to be shown
+    $test_count      = 0;
+    $test_binderfs   = 0;
+    $test_binder_ctx = 0;
+
+    # Allow binder info to be shown.
     $v = $ARGV[0];
     if ($v) {
         if ( $v ne "-v" ) {
@@ -17,10 +21,10 @@ BEGIN {
     }
 
     # check if binder driver available and kernel/userspace versions.
-    $result = system("$basedir/check_binder 2> /dev/null");
+    $result = system("$basedir/check_binder $v 2>/dev/null");
 
     if ( $result >> 8 eq 0 ) {
-        plan tests => 6;
+        $test_count += 7;
     }
     elsif ( $result >> 8 eq 1 ) {
         plan skip_all => "Binder not supported by kernel";
@@ -31,73 +35,238 @@ BEGIN {
     else {
         plan skip_all => "Error checking Binder driver";
     }
+
+    # Check if kernel may have "binder: Add thread->process_todo flag" patch.
+    # This has been backported to some earlier kernels.
+    # Patch available from: https://lore.kernel.org/patchwork/patch/851324/
+    $kvercur = `uname -r`;
+    chomp($kvercur);
+    $kverminstream = "4.16";
+    $result        = `$basedir/../kvercmp $kvercur $kverminstream`;
+    if ( $result < 0 ) {
+        print "This $kvercur kernel may fail some tests, if so may require\n";
+        print
+          "\"binder: Add thread->process_todo flag\" patch available from:\n";
+        print "https://lore.kernel.org/patchwork/patch/851324/\n";
+    }
+
+    # Check if kernel supports binderfs and return of security context.
+    $kverminstream = "5.0";
+    $result        = `$basedir/../kvercmp $kvercur $kverminstream`;
+
+    if ( $result > 0 ) {
+        $test_binder_ctx = 1;
+        $test_count += 1;
+        system("mkdir /dev/binderfs 2>/dev/null");
+        system(
+"mount -t binder binder /dev/binderfs -o context=system_u:object_r:device_t:s0 2>/dev/null"
+        );
+        $result = system("$basedir/check_binderfs $v 2>/dev/null");
+        if ( $result == 0 ) {
+            $test_binderfs = 1;
+            $test_count += 8;
+        }
+        elsif ( $result >> 8 eq 1 or $result >> 8 eq 2 ) {
+            print
+"Error BINDERFS: May require kernel \"CONFIG_ANDROID_BINDERFS=y\" or test rebuild.\n";
+            system("umount binder 2>/dev/null");
+            system("rmdir /dev/binderfs 2>/dev/null");
+        }
+    }
+
+    plan tests => $test_count;
 }
 
-sub manager_start {
-    my ( $runcon_args, $args ) = @_;
+sub service_start {
+    my ( $service, $runcon_args, $args ) = @_;
     my $pid;
+    my $flag = $service . "_flag";
 
-    system("mkfifo $basedir/flag");
+    system("mkfifo $basedir/$flag");
 
     if ( ( $pid = fork() ) == 0 ) {
-        exec "runcon $runcon_args $basedir/test_binder -f $basedir/flag $args";
+        exec "runcon $runcon_args $basedir/$service -f $basedir/$flag $args";
     }
 
     # Wait for it to initialize.
-    system("cat $basedir/flag >/dev/null");
+    system("cat $basedir/$flag >/dev/null");
     return $pid;
 }
 
-sub manager_end {
-    my ($pid) = @_;
+sub service_end {
+    my ( $service, $pid ) = @_;
+    my $flag = $service . "_flag";
 
     kill KILL, $pid;
-    system("rm -f $basedir/flag");
+    system("rm -f $basedir/$flag");
 }
 
-$pid = manager_start( "-t test_binder_mgr_t", "$v manager" );
+$sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v" );
+$sp_pid =
+  service_start( "service_provider", "-t test_binder_provider_t", "$v" );
 
-# 1 Verify that authorized provider can transact with the manager.
-$result =
-  system
-  "runcon -t test_binder_provider_t $basedir/test_binder $v -r 1 provider";
+# 1 Verify that authorized client and service provider can communicate with the binder service manager.
+$result = system "runcon -t test_binder_client_t $basedir/client $v -c -r 3";
 ok( $result eq 0 );
 
-# 2 Verify that provider cannot call manager (no call perm).
-$result = system
-"runcon -t test_binder_provider_no_call_t $basedir/test_binder $v -r 2 provider 2>&1";
-ok( $result >> 8 eq 8 );
-
-# 3 Verify that provider cannot communicate with manager (no impersonate perm).
-$result = system
-"runcon -t test_binder_provider_no_im_t $basedir/test_binder $v -r 2 provider 2>&1";
-ok( $result >> 8 eq 103 );
-
-# 4 Verify that provider cannot communicate with manager (no transfer perm).
-$result = system
-"runcon -t test_binder_provider_no_transfer_t $basedir/test_binder $v -r 1 provider 2>&1";
-ok( $result >> 8 eq 8 );
-
-# Kill the manager.
-manager_end($pid);
+# 2 Verify that client cannot call manager (no call perm).
+$result =
+  system
+  "runcon -t test_binder_client_no_call_mgr_t $basedir/client $v -r 1 2>&1";
+ok( $result >> 8 eq 125 );
 
-# 5 Verify that provider cannot become a manager (no set_context_mgr perm).
+# 3 Verify that client cannot call service provider (no call perm).
 $result =
   system
-  "runcon -t test_binder_provider_t $basedir/test_binder $v manager 2>&1";
-ok( $result >> 8 eq 4 );
+  "runcon -t test_binder_client_no_call_sp_t $basedir/client $v -r 2 2>&1";
+ok( $result >> 8 eq 141 );
 
-# Start manager to test that selinux_binder_transfer_file() fails when fd { use } is denied by policy.
-$pid = manager_start( "-t test_binder_mgr_no_fd_t", "$v manager" );
+# 4 Verify that client cannot communicate with service provider (no impersonate perm).
+$result =
+  system "runcon -t test_binder_client_no_im_t $basedir/client $v -r 2 2>&1";
+ok( $result >> 8 eq 133 );
 
-# 6 Verify that authorized provider can communicate with the server, however the fd passed will not be valid for manager
-# domain and binder will return BR_FAILED_REPLY.
+# 5 Verify that client cannot communicate with service provider (no transfer perm).
 $result =
   system
-  "runcon -t test_binder_provider_t $basedir/test_binder $v provider -r 2 2>&1";
-ok( $result >> 8 eq 8 );
+  "runcon -t test_binder_client_no_transfer_t $basedir/client $v -r 2 2>&1";
+ok( $result >> 8 eq 125 );
+
+# Kill the service provider & manager before next tests:
+service_end( "service_provider", $sp_pid );
+service_end( "manager",          $sm_pid );
+
+# 6 Verify that provider domain cannot become a manager (no set_context_mgr perm).
+$result = system "runcon -t test_binder_provider_t $basedir/manager $v 2>&1";
+ok( $result >> 8 eq 14 );
+
+# 7 Test that selinux_binder_transfer_file() fails when fd { use } is denied by policy.
+#   Note that this test requires the Reference Policy boolean "allow_domain_fd_use" set to FALSE.
+#   (setsebool allow_domain_fd_use=0)
+# 7a Start Manager
+$sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v" );
+
+# 7b Start Service Provider
+$sp_pid =
+  service_start( "service_provider", "-t test_binder_provider_no_fd_t", "$v" );
+
+# 7c Verify that authorized client can communicate with the service provider, however the sp's binder fd passed
+#    to the client will not be valid for service provider domain and binder will return BR_FAILED_REPLY.
+$result = system "runcon -t test_binder_client_t $basedir/client $v -r2 2>&1";
+ok( $result >> 8 eq 141 );
 
-# Kill the manager
-manager_end($pid);
+# Kill the service provider & manager
+service_end( "service_provider", $sp_pid );
+service_end( "manager",          $sm_pid );
+
+if ($test_binder_ctx) {
+    #### Binder return security context test ######################
+    #
+    $sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v" );
+    $sp_pid = service_start(
+        "service_provider",
+        "-t test_binder_provider_t",
+        "$v -e unconfined_u:unconfined_r:test_binder_client_t:s0-s0:c0.c1023"
+    );
+
+# 8 Verify that authorized client and service provider can communicate with the binder service manager.
+#   Also check that the service provider can receive the Clients security context.
+    $result =
+      system "runcon -t test_binder_client_t $basedir/client $v -c -r 3";
+    ok( $result eq 0 );
+
+    # Kill the service provider & manager.
+    service_end( "service_provider", $sp_pid );
+    service_end( "manager",          $sm_pid );
+}
+
+if ($test_binderfs) {
+    #### Linux 5.0+ Test binder 'Dynamically Allocated Binder Devices'.
+    $sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v -n" );
+    $sp_pid =
+      service_start( "service_provider", "-t test_binder_provider_t", "$v -n" );
+
+# 9 Verify that authorized client and service provider can communicate with the binder service manager.
+    $result =
+      system "runcon -t test_binder_client_t $basedir/client $v -n -c -r 3";
+    ok( $result eq 0 );
+
+    # 10 Verify that client cannot call manager (no call perm).
+    $result =
+      system
+"runcon -t test_binder_client_no_call_mgr_t $basedir/client $v -n -r 1 2>&1";
+    ok( $result >> 8 eq 125 );
+
+    # 11 Verify that client cannot call service provider (no call perm).
+    $result =
+      system
+"runcon -t test_binder_client_no_call_sp_t $basedir/client $v -n -r 2 2>&1";
+    ok( $result >> 8 eq 141 );
+
+# 12 Verify that client cannot communicate with service provider (no impersonate perm).
+    $result =
+      system
+      "runcon -t test_binder_client_no_im_t $basedir/client $v -n -r 2 2>&1";
+    ok( $result >> 8 eq 133 );
+
+# 13 Verify that client cannot communicate with service provider (no transfer perm).
+    $result =
+      system
+"runcon -t test_binder_client_no_transfer_t $basedir/client $v -n -r 2 2>&1";
+    ok( $result >> 8 eq 125 );
+
+    # Kill the service provider & manager before next tests:
+    service_end( "service_provider", $sp_pid );
+    service_end( "manager",          $sm_pid );
+
+# 14 Verify that provider domain cannot become a manager (no set_context_mgr perm).
+    $result =
+      system "runcon -t test_binder_provider_t $basedir/manager $v -n 2>&1";
+    ok( $result >> 8 eq 14 );
+
+# 15 Test that selinux_binder_transfer_file() fails when fd { use } is denied by policy.
+#    Note that this test requires the Reference Policy boolean "allow_domain_fd_use" set to FALSE.
+#    (setsebool allow_domain_fd_use=0)
+# 15a Start Manager
+    $sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v -n" );
+
+    # 15b Start Service Provider
+    $sp_pid =
+      service_start( "service_provider", "-t test_binder_provider_no_fd_t",
+        "$v -n" );
+
+# 15c Verify that authorized client can communicate with the service provider, however the sp's binder fd passed
+#    to the client will not be valid for service provider domain and binder will return BR_FAILED_REPLY.
+    $result =
+      system "runcon -t test_binder_client_t $basedir/client $v -n -r2 2>&1";
+    ok( $result >> 8 eq 141 );
+
+    # Kill the service provider & manager
+    service_end( "service_provider", $sp_pid );
+    service_end( "manager",          $sm_pid );
+
+    #### Binder return security context test #########################
+    #
+    $sm_pid = service_start( "manager", "-t test_binder_mgr_t", "$v -n" );
+    $sp_pid = service_start(
+        "service_provider",
+        "-t test_binder_provider_t",
+        "$v -n -e unconfined_u:unconfined_r:test_binder_client_t:s0-s0:c0.c1023"
+    );
+
+# 16 Verify that authorized client and service provider can communicate with the binder service manager.
+#    Also check that the service provider can receive the Clients security context.
+    $result =
+      system "runcon -t test_binder_client_t $basedir/client $v -n -c -r 3";
+    ok( $result eq 0 );
+
+    # Kill the service provider & manager.
+    service_end( "service_provider", $sp_pid );
+    service_end( "manager",          $sm_pid );
+
+    # Cleanup binderfs stuff.
+    system("umount binder 2>/dev/null");
+    system("rmdir /dev/binderfs 2>/dev/null");
+}
 
 exit;
diff --git a/tests/binder/test_binder.c b/tests/binder/test_binder.c
deleted file mode 100644
index 62194bf..0000000
--- a/tests/binder/test_binder.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * This is a simple binder Service Manager/Service Provider that only uses
- * the raw ioctl commands to test the SELinux binder permissions:
- *     set_context_mgr, call, transfer, impersonate.
- *
- * Using binder test policy the following will be validated:
- *    security_binder_set_context_mgr() binder { set_context_mgr }
- *    security_binder_transaction()     binder { call impersonate }
- *    security_binder_transfer_binder() binder { transfer }
- *    security_binder_transfer_file()   fd { use }
- *
- * TODO security_binder_transfer_file() uses BPF if configured in kernel.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <stdbool.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <selinux/selinux.h>
-#include <linux/android/binder.h>
-
-/* These are the Binder txn->code values used by the Service Provider and
- * Manager to request/retrieve a binder handle.
- */
-#define ADD_TEST_SERVICE 100 /* Sent by Service Provider */
-#define GET_TEST_SERVICE 101 /* Sent by Client */
-
-#define TEST_SERVICE_MANAGER_HANDLE 0
-
-static int binder_parse(int fd, uintptr_t ptr, size_t size, bool manager);
-
-static bool verbose;
-uint32_t sp_handle;
-static unsigned char *shm_base;
-static int shm_fd;
-static int shm_size = 32;
-
-static void usage(char *progname)
-{
-	fprintf(stderr,
-		"usage:  %s [-f file] [-r replies] [-v] manager | provider\n"
-		"Where:\n\t"
-		"-f       Write a line to the file when listening starts.\n\t"
-		"-r       Number of replies to expect from test - default 0.\n\t"
-		"-v       Print context and command information.\n\t"
-		"manager  Act as Service Manager.\n\t"
-		"service  Act as Service Provider.\n"
-		"\nNote: Ensure this boolean command is run when "
-		"testing after a reboot:\n\t"
-		"setsebool allow_domain_fd_use=0\n", progname);
-	exit(-1);
-}
-
-/* Create a small piece of shared memory between the Manager and Service
- * Provider to share a handle as explained in the do_service_manager()
- * function.
- */
-static void create_shm(bool manager)
-{
-	char *name =  "sp_handle";
-
-	if (manager)
-		shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
-	else
-		shm_fd = shm_open(name, O_RDONLY, 0666);
-	if (shm_fd < 0) {
-		fprintf(stderr, "%s shm_open: %s\n", __func__, strerror(errno));
-		exit(-1);
-	}
-
-	ftruncate(shm_fd, shm_size);
-
-	if (manager)
-		shm_base = mmap(0, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED,
-				shm_fd, 0);
-	else
-		shm_base = mmap(0, shm_size, PROT_READ, MAP_SHARED, shm_fd, 0);
-	if (shm_base == MAP_FAILED) {
-		fprintf(stderr, "%s mmap: %s\n", __func__, strerror(errno));
-		close(shm_fd);
-		exit(-1);
-	}
-}
-
-static const char *cmd_name(uint32_t cmd)
-{
-	switch (cmd) {
-	case BR_NOOP:
-		return "BR_NOOP";
-	case BR_TRANSACTION_COMPLETE:
-		return "BR_TRANSACTION_COMPLETE";
-	case BR_INCREFS:
-		return "BR_INCREFS";
-	case BR_ACQUIRE:
-		return "BR_ACQUIRE";
-	case BR_RELEASE:
-		return "BR_RELEASE";
-	case BR_DECREFS:
-		return "BR_DECREFS";
-	case BR_TRANSACTION:
-		return "BR_TRANSACTION";
-	case BR_REPLY:
-		return "BR_REPLY";
-	case BR_FAILED_REPLY:
-		return "BR_FAILED_REPLY";
-	case BR_DEAD_REPLY:
-		return "BR_DEAD_REPLY";
-	case BR_DEAD_BINDER:
-		return "BR_DEAD_BINDER";
-	case BR_ERROR:
-		return "BR_ERROR";
-	/* fallthrough */
-	default:
-		return "Unknown command";
-	}
-}
-
-static void print_trans_data(struct binder_transaction_data *txn_in)
-{
-	struct flat_binder_object *obj;
-	binder_size_t *offs = (binder_size_t *)
-			      (uintptr_t)txn_in->data.ptr.offsets;
-	size_t count = txn_in->offsets_size / sizeof(binder_size_t);
-
-	printf("\thandle: %ld\n", (unsigned long)txn_in->target.handle);
-	printf("\tcookie: %lld\n", txn_in->cookie);
-	printf("\tcode: %d\n", txn_in->code);
-	switch (txn_in->flags) {
-	case TF_ONE_WAY:
-		printf("\tflag: TF_ONE_WAY\n");
-		break;
-	case TF_ROOT_OBJECT:
-		printf("\tflag: TF_ROOT_OBJECT\n");
-		break;
-	case TF_STATUS_CODE:
-		printf("\tflag: TF_STATUS_CODE\n");
-		break;
-	case TF_ACCEPT_FDS:
-		printf("\tflag: TF_ACCEPT_FDS\n");
-		break;
-	default:
-		printf("Unknown flag: %x\n", txn_in->flags);
-		return;
-	}
-	printf("\tsender pid: %u\n", txn_in->sender_pid);
-	printf("\tsender euid: %u\n", txn_in->sender_euid);
-	printf("\tdata_size: %llu\n", txn_in->data_size);
-	printf("\toffsets_size: %llu\n", txn_in->offsets_size);
-
-	while (count--) {
-		obj = (struct flat_binder_object *)
-		      (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs++);
-
-		switch (obj->hdr.type) {
-		case BINDER_TYPE_BINDER:
-			printf("\thdr: BINDER_TYPE_BINDER\n");
-			printf("\tbinder: %llx\n", obj->binder);
-			break;
-		case BINDER_TYPE_HANDLE:
-			printf("\thdr: BINDER_TYPE_HANDLE\n");
-			printf("\thandle: %x\n", obj->handle);
-			break;
-		case BINDER_TYPE_FD:
-			printf("\thdr: BINDER_TYPE_FD\n");
-			printf("\tfd: %x\n", obj->handle);
-			break;
-		default:
-			printf("Unknown header: %u\n", obj->hdr.type);
-			return;
-		}
-		printf("\tflags: priority: 0x%x accept FDS: %s\n",
-		       obj->flags & FLAT_BINDER_FLAG_PRIORITY_MASK,
-		       obj->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS ? "YES" : "NO");
-		printf("\tcookie: %llx\n", obj->cookie);
-	}
-}
-
-/* If add a service provider, then obtain a handle for it and store in
- * shared memory. The handle will then be used by the service provider
- * process to contact the Manager for its file descriptor, thus triggering
- * the 'impersonate' permission (as current_sid() != task_sid(from))
- * It is done this way as being a cheapskate it saved adding code to the
- * GET_TEST_SERVICE process plus running a Client as well. This achieves
- * the same objective.
- */
-static void do_service_manager(int fd, struct binder_transaction_data *txn_in)
-{
-	int result;
-	struct flat_binder_object *obj;
-	struct binder_write_read bwr;
-	uint32_t acmd[2];
-	binder_size_t *offs;
-
-	switch (txn_in->code) {
-	case ADD_TEST_SERVICE:
-		offs = (binder_size_t *)(uintptr_t)txn_in->data.ptr.offsets;
-
-		/* Get fbo that contains the Managers binder file descriptor. */
-		obj = (struct flat_binder_object *)
-		      (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs);
-
-		if (obj->hdr.type == BINDER_TYPE_HANDLE) {
-			sp_handle = obj->handle;
-			memcpy(shm_base, &sp_handle, sizeof(sp_handle));
-			if (verbose)
-				printf("Manager has BINDER_TYPE_HANDLE obj->handle: %d\n",
-				       sp_handle);
-		} else {
-			fprintf(stderr, "Failed to obtain a handle\n");
-			exit(-1);
-		}
-
-		acmd[0] = BC_ACQUIRE;
-		acmd[1] = obj->handle;
-
-		memset(&bwr, 0, sizeof(bwr));
-		bwr.write_buffer = (uintptr_t)&acmd;
-		bwr.write_size = sizeof(acmd);
-
-		result = ioctl(fd, BINDER_WRITE_READ, &bwr);
-		if (result < 0) {
-			fprintf(stderr,
-				"ServiceProvider ioctl BINDER_WRITE_READ: %s\n",
-				strerror(errno));
-			exit(-1);
-		}
-
-		if (verbose)
-			printf("Manager acquired handle: %d for Service Provider\n",
-			       sp_handle);
-		break;
-
-	case GET_TEST_SERVICE:
-		if (verbose)
-			printf("GET_TEST_SERVICE not supported\n");
-		break;
-	default:
-		fprintf(stderr, "Unknown txn->code: %d\n", txn_in->code);
-		exit(-1);
-	}
-}
-
-static void request_manager_fd(int fd, struct binder_transaction_data *txn_in)
-{
-	int result;
-	unsigned int writebuf[1024];
-	struct binder_fd_object obj;
-	binder_size_t offset = 0;
-	struct binder_write_read bwr;
-	struct binder_transaction_data *txn;
-
-	if (txn_in->flags == TF_ONE_WAY) {
-		if (verbose)
-			printf("Manager no reply to BC_TRANSACTION as flags = TF_ONE_WAY\n");
-		return;
-	}
-
-	if (verbose)
-		printf("Manager sending BC_REPLY to obtain its FD\n");
-
-	writebuf[0] = BC_REPLY;
-	txn = (struct binder_transaction_data *)(&writebuf[1]);
-
-	memset(txn, 0, sizeof(*txn));
-	txn->target.handle = txn_in->target.handle;
-	txn->cookie = txn_in->cookie;
-	txn->code = txn_in->code;
-	txn->flags = TF_ACCEPT_FDS;
-	memset(&obj, 0, sizeof(obj));
-	obj.hdr.type = BINDER_TYPE_FD;
-	obj.pad_flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-	obj.cookie = txn->cookie;
-	/* The binder fd is used for testing as it allows policy to set
-	 * whether the Service and Manager can be allowed access (fd use)
-	 * or not. For example test_binder_mgr_t has:
-	 *        allow test_binder_service_t test_binder_mgr_t:fd use;
-	 * whereas test_binder_mgr_no_fd_t does not allow this fd use.
-	 *
-	 * This also allows a check for the impersonate permission later
-	 * as the Service Provider will use this (the Managers fd) to
-	 * send a transaction.
-	 */
-	obj.fd = fd;
-
-	if (verbose)
-		printf("Manager handle: %d and its FD: %d\n",
-		       txn->target.handle, fd);
-
-	txn->data_size = sizeof(obj);
-	txn->offsets_size = sizeof(offset);
-	txn->data.ptr.buffer = (uintptr_t)&obj;
-	txn->data.ptr.offsets = (uintptr_t)&offset;
-
-	memset(&bwr, 0, sizeof(bwr));
-	bwr.write_buffer = (uintptr_t)writebuf;
-	bwr.write_size = sizeof(writebuf[0]) + sizeof(*txn);
-
-	result = ioctl(fd, BINDER_WRITE_READ, &bwr);
-	if (result < 0) {
-		fprintf(stderr, "%s ioctl BINDER_WRITE_READ: %s\n",
-			__func__, strerror(errno));
-		exit(-1);
-	}
-}
-
-/* This retrieves the requested Managers file descriptor, then using this
- * sends a simple transaction to trigger the impersonate permission.
- */
-static void extract_fd_and_respond(struct binder_transaction_data *txn_in,
-				   bool manager)
-{
-	int result;
-	uint32_t cmd;
-	struct stat sb;
-	struct binder_write_read bwr;
-	struct binder_fd_object *obj;
-	struct {
-		uint32_t cmd;
-		struct binder_transaction_data txn;
-	} __attribute__((packed)) writebuf;
-	unsigned int readbuf[32];
-
-	memset(readbuf, 0, sizeof readbuf);
-
-	binder_size_t *offs = (binder_size_t *)
-			      (uintptr_t)txn_in->data.ptr.offsets;
-
-	/* Get the bfdo that contains the Managers binder file descriptor. */
-	obj = (struct binder_fd_object *)
-	      (((char *)(uintptr_t)txn_in->data.ptr.buffer) + *offs);
-
-	if (obj->hdr.type != BINDER_TYPE_FD) {
-		fprintf(stderr, "Header not BINDER_TYPE_FD: %d\n",
-			obj->hdr.type);
-		exit(100);
-	}
-
-	/* fstat this just to see if a valid fd */
-	result = fstat(obj->fd, &sb);
-	if (result < 0) {
-		fprintf(stderr, "Not a valid fd: %s\n", strerror(errno));
-		exit(101);
-	}
-
-	if (verbose)
-		printf("Service Provider retrieved Managers fd: %d st_dev: %ld\n",
-		       obj->fd, sb.st_dev);
-
-	/* Send response using Managers fd to trigger impersonate check. */
-	writebuf.cmd = BC_TRANSACTION;
-	memcpy(&writebuf.txn.target.handle, shm_base, sizeof(uint32_t));
-
-	writebuf.txn.cookie = 0;
-	writebuf.txn.code = 0;
-	writebuf.txn.flags = TF_ONE_WAY;
-
-	writebuf.txn.data_size = 0;
-	writebuf.txn.data.ptr.buffer = (uintptr_t)NULL;
-	writebuf.txn.data.ptr.offsets = (uintptr_t)NULL;
-	writebuf.txn.offsets_size = 0;
-
-	memset(&bwr, 0, sizeof(bwr));
-	bwr.write_size = sizeof(writebuf);
-	bwr.write_consumed = 0;
-	bwr.write_buffer = (uintptr_t)&writebuf;
-	bwr.read_size = sizeof(readbuf);
-	bwr.read_consumed = 0;
-	bwr.read_buffer = (uintptr_t)readbuf;
-
-	result = ioctl(obj->fd, BINDER_WRITE_READ, &bwr);
-	if (result < 0) {
-		fprintf(stderr,
-			"Service Provider ioctl BINDER_WRITE_READ: %s\n",
-			strerror(errno));
-		exit(102);
-	}
-
-	if (verbose)
-		printf("Service Provider read_consumed: %lld\n",
-		       bwr.read_consumed);
-
-	cmd = binder_parse(obj->fd, (uintptr_t)readbuf,
-			   bwr.read_consumed, manager);
-
-	if (verbose)
-		printf("Service Provider using Managers FD\n");
-
-	if (cmd == BR_FAILED_REPLY ||
-	    cmd == BR_DEAD_REPLY ||
-	    cmd == BR_DEAD_BINDER) {
-		fprintf(stderr,
-			"Failed response from Service Provider using Managers FD\n");
-		exit(103);
-	}
-}
-
-/* Parse response, reply as required and then return last CMD */
-static int binder_parse(int fd, uintptr_t ptr, size_t size, bool manager)
-{
-	uintptr_t end = ptr + (uintptr_t)size;
-	uint32_t cmd;
-
-	while (ptr < end) {
-		cmd = *(uint32_t *)ptr;
-		ptr += sizeof(uint32_t);
-
-		if (verbose)
-			printf("%s command: %s\n",
-			       manager ? "Manager" : "Service Provider",
-			       cmd_name(cmd));
-
-		switch (cmd) {
-		case BR_NOOP:
-			break;
-		case BR_TRANSACTION_COMPLETE:
-			break;
-		case BR_INCREFS:
-		case BR_ACQUIRE:
-		case BR_RELEASE:
-		case BR_DECREFS:
-			ptr += sizeof(struct binder_ptr_cookie);
-			break;
-		case BR_TRANSACTION: {
-			struct binder_transaction_data *txn =
-				(struct binder_transaction_data *)ptr;
-
-			if (verbose) {
-				printf("%s BR_TRANSACTION data:\n",
-				       manager ? "Manager" : "Service Provider");
-				print_trans_data(txn);
-			}
-
-			if (manager) {
-				do_service_manager(fd, txn);
-				request_manager_fd(fd, txn);
-			}
-
-			ptr += sizeof(*txn);
-			break;
-		}
-		case BR_REPLY: {
-			struct binder_transaction_data *txn =
-				(struct binder_transaction_data *)ptr;
-
-			if (verbose) {
-				printf("%s BR_REPLY data:\n",
-				       manager ? "Manager" : "Service Provider");
-				print_trans_data(txn);
-			}
-
-			/* Service Provider extracts the Manager fd, and responds */
-			if (!manager)
-				extract_fd_and_respond(txn, manager);
-
-			ptr += sizeof(*txn);
-			break;
-		}
-		case BR_DEAD_BINDER:
-			break;
-		case BR_FAILED_REPLY:
-			break;
-		case BR_DEAD_REPLY:
-			break;
-		case BR_ERROR:
-			ptr += sizeof(uint32_t);
-			break;
-		default:
-			if (verbose)
-				printf("%s Parsed unknown command: %d\n",
-				       manager ? "Manager" : "Service Provider",
-				       cmd);
-			exit(-1);
-		}
-	}
-
-	return cmd;
-}
-
-int main(int argc, char **argv)
-{
-	int opt, result, binder_fd, provider_replies = 0;
-	uint32_t cmd;
-	bool manager;
-	pid_t pid;
-	char *driver = "/dev/binder";
-	char *context;
-	char *flag_file = NULL;
-	void *map_base;
-	size_t map_size = 1024 * 8;
-	struct binder_write_read bwr;
-	struct flat_binder_object obj;
-	binder_size_t offset = 0;
-	struct {
-		uint32_t cmd;
-		struct binder_transaction_data txn;
-	} __attribute__((packed)) writebuf;
-	unsigned int readbuf[32];
-
-	verbose = false;
-
-	while ((opt = getopt(argc, argv, "f:vr:")) != -1) {
-		switch (opt) {
-		case 'f':
-			flag_file = optarg;
-			break;
-		case 'v':
-			verbose = true;
-			break;
-		case 'r':
-			provider_replies = atoi(optarg);
-			break;
-		default:
-			usage(argv[0]);
-		}
-	}
-
-	if ((argc - optind) != 1)
-		usage(argv[0]);
-
-	if (!strcmp(argv[optind], "manager"))
-		manager = true;
-	else if (!strcmp(argv[optind], "provider"))
-		manager = false;
-	else
-		usage(argv[0]);
-
-	binder_fd = open(driver, O_RDWR | O_CLOEXEC);
-	if (binder_fd < 0) {
-		fprintf(stderr, "Cannot open %s error: %s\n", driver,
-			strerror(errno));
-		exit(1);
-	}
-
-	map_base = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, binder_fd, 0);
-	if (map_base == MAP_FAILED) {
-		fprintf(stderr, "mmap error: %s\n", strerror(errno));
-		close(binder_fd);
-		exit(2);
-	}
-
-	/* Create the appropriate shared memory for passing the Service
-	 * Providers handle from the Manager to the Service Provider for
-	 * use in the impersonate tests. This saves adding a Client to
-	 * do this job.
-	 */
-	create_shm(manager);
-
-	/* Get our context and pid */
-	result = getcon(&context);
-	if (result < 0) {
-		fprintf(stderr, "Failed to obtain SELinux context\n");
-		result = 3;
-		goto brexit;
-	}
-	pid = getpid();
-
-	if (manager) { /* Service Manager */
-		if (verbose) {
-			printf("Manager PID: %d Process context:\n\t%s\n",
-			       pid, context);
-		}
-
-		result = ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
-		if (result < 0) {
-			fprintf(stderr,
-				"Failed to become context manager: %s\n",
-				strerror(errno));
-			result = 4;
-			goto brexit;
-		}
-
-		writebuf.cmd = BC_ENTER_LOOPER;
-		bwr.write_size = sizeof(writebuf.cmd);
-		bwr.write_consumed = 0;
-		bwr.write_buffer = (uintptr_t)&writebuf;
-
-		bwr.read_size = 0;
-		bwr.read_consumed = 0;
-		bwr.read_buffer = 0;
-
-		result = ioctl(binder_fd, BINDER_WRITE_READ, &bwr);
-		if (result < 0) {
-			fprintf(stderr,
-				"Manager ioctl BINDER_WRITE_READ: %s\n",
-				strerror(errno));
-			result = 5;
-			goto brexit;
-		}
-
-		if (flag_file) {
-			FILE *f = fopen(flag_file, "w");
-			if (!f) {
-				perror("Flag file open");
-				result = 9;
-				goto brexit;
-			}
-			fprintf(f, "listening\n");
-			fclose(f);
-		}
-
-		while (true) {
-			memset(readbuf, 0, sizeof readbuf);
-			bwr.read_size = sizeof(readbuf);
-			bwr.read_consumed = 0;
-			bwr.read_buffer = (uintptr_t)readbuf;
-
-			result = ioctl(binder_fd, BINDER_WRITE_READ, &bwr);
-			if (result < 0) {
-				fprintf(stderr,
-					"Manager ioctl BINDER_WRITE_READ: %s\n",
-					strerror(errno));
-				result = 6;
-				goto brexit;
-			}
-
-			if (bwr.read_consumed == 0)
-				continue;
-
-			if (verbose)
-				printf("Manager read_consumed: %lld\n",
-				       bwr.read_consumed);
-
-			cmd = binder_parse(binder_fd, (uintptr_t)readbuf,
-					   bwr.read_consumed, manager);
-		}
-	} else { /* Service Provider */
-		if (verbose) {
-			printf("Service Provider PID: %d Process context:\n\t%s\n",
-			       pid, context);
-		}
-
-		writebuf.cmd = BC_TRANSACTION;
-		writebuf.txn.target.handle = TEST_SERVICE_MANAGER_HANDLE;
-		writebuf.txn.cookie = 0;
-		writebuf.txn.code = ADD_TEST_SERVICE;
-		writebuf.txn.flags = TF_ACCEPT_FDS;
-
-		memset(&obj, 0, sizeof(obj));
-		obj.hdr.type = BINDER_TYPE_BINDER;
-		obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-		obj.binder = (uintptr_t)NULL;
-		obj.cookie = 0;
-
-		writebuf.txn.data_size = sizeof(obj);
-		writebuf.txn.offsets_size = sizeof(offset);
-
-		writebuf.txn.data.ptr.buffer = (uintptr_t)&obj;
-		writebuf.txn.data.ptr.offsets = (uintptr_t)&offset;
-
-		bwr.write_buffer = (uintptr_t)&writebuf;
-		bwr.write_size = sizeof(writebuf);
-		bwr.write_consumed = 0;
-
-		if (verbose)
-			printf("Service Provider sending transaction to Manager - ADD_TEST_SERVICE\n");
-
-		/* Each test will expect a different number of replies */
-		while (provider_replies) {
-			memset(readbuf, 0, sizeof readbuf);
-			bwr.read_size = sizeof(readbuf);
-			bwr.read_consumed = 0;
-			bwr.read_buffer = (uintptr_t)readbuf;
-
-			result = ioctl(binder_fd, BINDER_WRITE_READ, &bwr);
-			if (result < 0) {
-				fprintf(stderr,
-					"xxService Provider ioctl BINDER_WRITE_READ: %s\n",
-					strerror(errno));
-				result = 7;
-				goto brexit;
-			}
-
-			if (verbose)
-				printf("Service Provider read_consumed: %lld\n",
-				       bwr.read_consumed);
-
-			cmd = binder_parse(binder_fd, (uintptr_t)readbuf,
-					   bwr.read_consumed, manager);
-
-			if (cmd == BR_FAILED_REPLY ||
-			    cmd == BR_DEAD_REPLY ||
-			    cmd == BR_DEAD_BINDER) {
-				result = 8;
-				goto brexit;
-			}
-			provider_replies--;
-		}
-	}
-
-brexit:
-	free(context);
-	munmap(shm_base, shm_size);
-	close(shm_fd);
-	munmap(map_base, map_size);
-	close(binder_fd);
-
-	return result;
-}
