Shared memory region in NDK

喜欢而已 提交于 2019-12-01 12:55:24

On all versions of Android since 1.5 to 4.1, FileDescriptor has an int data member called descriptor. It's package-private on earlier versions of Android, private on recent ones. With a bit of deliberate access control subversion, you can access it - either via reflection, or via JNI. Each can bypass access control - in case of reflection, via Field.setAccessible(), in case of JNI - by default.

With that in mind, you can construct a FileDescriptor around a native FD just fine. Construct a blank one, then set descriptor. That's what bits and pieces of Android code do when constructing those.

Whether this dirty hack will break eventually, who knows. Fortunately, it's not a core piece of functionality in my case - there's some graceful degradation.

One may conditionally employ supported ParcelFileDescriptor methods, if the platform allows, using the field access hack as a fallback. This way, it'll be relatively future proof.

There is a method in helper library libnativehelper.so for this jniCreateFileDescriptor() https://android.googlesource.com/platform/libnativehelper/+/jb-dev/include/nativehelper/JNIHelp.h. It basically does the same thing as stated in previous answer but you might find this approach a bit cleaner.

This is how it worked for me while working with a similar problem:

Instead of using shmfd = open(SHM_PATH, O_RDWR) for creating and getting file descriptor I replaced it with

int fd = ashmem_create_region("SharedRegionName", size); 

and used the file descriptor to get base address:

int base_address = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

// write data You can pass the base_address to your java code from the native code using a native function that returns the descriptor.

Then I create a Service with aidl interface and used this interface to bind this service from another process. From the Service I have used a ParcelFileDescriptor object to return to another process. You can create ParcelFileDescriptor by:

ParcelFileDescriptor desc = ParcelFileDescriptor.fromFd(fd);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!