Skip to content

Commit e475f07

Browse files
committed
Use Binder and ashmem to share memory
1 parent 74c3ca2 commit e475f07

File tree

7 files changed

+224
-2
lines changed

7 files changed

+224
-2
lines changed

.syntastic_cpp_config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-Ijni
2+
-Ijni/android/include/system/core/include
3+
-Ijni/android/include/frameworks/native/include

jni/Android.mk

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
4+
include $(CLEAR_VARS)
5+
6+
ANDROID_INCLUDE := $(LOCAL_PATH)/android/include
7+
ANDROID_LIB := $(LOCAL_PATH)/android/lib
8+
9+
LOCAL_CFLAGS += -DHAVE_PTHREADS -DHAVE_SYS_UIO_H
10+
11+
LOCAL_C_INCLUDES += $(ANDROID_INCLUDE)/system/core/include
12+
LOCAL_C_INCLUDES += $(ANDROID_INCLUDE)/frameworks/native/include
13+
14+
LOCAL_LDLIBS += -L$(ANDROID_LIB)
15+
LOCAL_LDLIBS += -llog -lutils -lbinder
16+
17+
LOCAL_SRC_FILES := BinderSHM.cpp
18+
19+
LOCAL_MODULE := ipc_shared
20+
include $(BUILD_SHARED_LIBRARY)
21+
22+
23+
24+
25+
include $(CLEAR_VARS)
26+
27+
ANDROID_INCLUDE := $(LOCAL_PATH)/android/include
28+
ANDROID_LIB := $(LOCAL_PATH)/android/lib
29+
30+
LOCAL_CFLAGS += -DHAVE_PTHREADS -DHAVE_SYS_UIO_H
31+
32+
LOCAL_C_INCLUDES += $(ANDROID_INCLUDE)/system/core/include
33+
LOCAL_C_INCLUDES += $(ANDROID_INCLUDE)/frameworks/native/include
34+
35+
LOCAL_LDLIBS += -L$(ANDROID_LIB)
36+
LOCAL_LDLIBS += -llog -lutils -lbinder
37+
38+
LOCAL_SRC_FILES := BinderSHM.cpp
39+
40+
LOCAL_MODULE := ipc
41+
include $(BUILD_EXECUTABLE)

jni/Application.mk

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
NDK_TOOLCHAIN_VERSION=4.8
2+
3+
APP_ABI := armeabi-v7a
4+
APP_PLATFORM := android-18
5+
6+
APP_STL := stlport_static
7+
APP_CPPFLAGS += -fno-rtti -Wno-psabi -Wno-switch
8+
STLPORT_FORCE_REBUILD := false

jni/BinderSHM.cpp

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include <jni.h>
2+
#include <sys/mman.h>
3+
#include <binder/IInterface.h>
4+
#include <binder/IBinder.h>
5+
#include <binder/Binder.h>
6+
#include <binder/ProcessState.h>
7+
#include <binder/IServiceManager.h>
8+
#include <binder/IPCThreadState.h>
9+
10+
#undef LOG_TAG
11+
#define LOG_TAG "AndroidIPC::SHM"
12+
13+
using namespace android;
14+
15+
// The binder message ids
16+
enum {
17+
SET_FD = IBinder::FIRST_CALL_TRANSACTION
18+
};
19+
20+
21+
// The interface, binder client and server should both implement it
22+
class ISHM : public IInterface {
23+
public:
24+
virtual status_t setFD(uint32_t fd) = 0;
25+
26+
DECLARE_META_INTERFACE(SHM);
27+
};
28+
29+
30+
// The client interface
31+
class BpSHM : public BpInterface<ISHM> {
32+
public:
33+
BpSHM(const sp<IBinder>& impl) : BpInterface<ISHM>(impl) {
34+
ALOGD("BpSHM::BpSHM()");
35+
}
36+
37+
virtual status_t setFD(uint32_t fd)
38+
{
39+
ALOGD("BpSHM::setFD(%u)", fd);
40+
Parcel data, reply;
41+
data.writeInterfaceToken(ISHM::getInterfaceDescriptor());
42+
data.writeFileDescriptor(fd);
43+
remote()->transact(SET_FD, data, &reply);
44+
return reply.readInt32();
45+
}
46+
};
47+
48+
IMPLEMENT_META_INTERFACE(SHM, "io.vec.IPC");
49+
50+
51+
// The server interface
52+
class BnSHM : public BnInterface<ISHM> {
53+
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
54+
{
55+
ALOGD("BnSHM::onTransact(%u)", code);
56+
CHECK_INTERFACE(IScreenComposer, data, reply);
57+
switch(code) {
58+
case SET_FD: {
59+
reply->writeInt32(setFD(data.readFileDescriptor()));
60+
return NO_ERROR;
61+
} break;
62+
default: {
63+
return BBinder::onTransact(code, data, reply, flags);
64+
} break;
65+
}
66+
}
67+
};
68+
69+
70+
// The server implementation
71+
class SHM : public BnSHM {
72+
public:
73+
status_t setFD(uint32_t fd)
74+
{
75+
ALOGD("SHM::setFD(%u)", fd);
76+
uint8_t *shm = (uint8_t*)mmap(NULL, 1024, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
77+
if (shm == MAP_FAILED) {
78+
ALOGE("mmap failed! %d, %s", errno, strerror(errno));
79+
return UNKNOWN_ERROR;
80+
}
81+
ALOGD("mmap %p", shm);
82+
83+
// Now we can use shm to share data with Java MemoryFile.
84+
// For this demo, we just release it.
85+
munmap(shm, 1024);
86+
return NO_ERROR;
87+
}
88+
89+
static void registerService()
90+
{
91+
defaultServiceManager()->addService(String16("binder_shm"), new SHM());
92+
}
93+
94+
static sp<ISHM> getService()
95+
{
96+
sp<IBinder> binder = defaultServiceManager()->getService(String16("binder_shm"));
97+
return interface_cast<ISHM>(binder);
98+
}
99+
};
100+
101+
102+
// Start the server
103+
int main(int argc, char const* argv[])
104+
{
105+
SHM::registerService();
106+
android::ProcessState::self()->startThreadPool();
107+
ALOGI("The SHM service started!");
108+
IPCThreadState::self()->joinThreadPool();
109+
return 0;
110+
}
111+
112+
113+
// JNI related
114+
static jboolean jni_setMemoryFile(JNIEnv* env, jclass clz, jobject jmf)
115+
{
116+
jclass clsMF = env->FindClass("android/os/MemoryFile");
117+
jfieldID fldFD = env->GetFieldID(clsMF, "mFD", "Ljava/io/FileDescriptor;");
118+
jobject objFD = env->GetObjectField(jmf, fldFD);
119+
jclass clsFD = env->FindClass("java/io/FileDescriptor");
120+
fldFD = env->GetFieldID(clsFD, "descriptor", "I");
121+
jint fd = env->GetIntField(objFD, fldFD);
122+
env->DeleteLocalRef(clsFD);
123+
env->DeleteLocalRef(objFD);
124+
env->DeleteLocalRef(clsMF);
125+
ALOGD("jni_setMemoryFile(%d)", fd);
126+
sp<ISHM> service = SHM::getService();
127+
return (service->setFD(fd) == NO_ERROR);
128+
}
129+
130+
131+
JNINativeMethod jniMethods[1] = {
132+
{ "setMemoryFile", "(Landroid/os/MemoryFile;)Z", (void*)jni_setMemoryFile },
133+
};
134+
135+
136+
jint JNI_OnLoad(JavaVM* vm, void* reserved)
137+
{
138+
JNIEnv* env;
139+
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
140+
return -1;
141+
}
142+
143+
jclass clz = env->FindClass("io/vec/demo/android/ipc/IPC");
144+
env->RegisterNatives(clz, jniMethods, sizeof(jniMethods) / sizeof(JNINativeMethod));
145+
env->DeleteLocalRef(clz);
146+
147+
return JNI_VERSION_1_6;
148+
}

jni/android/lib/libcutils.so

-53.2 KB
Binary file not shown.

src/io/vec/demo/android/ipc/IPC.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.vec.demo.android.ipc;
2+
3+
import android.os.MemoryFile;
4+
5+
public class IPC {
6+
public static native boolean setMemoryFile(MemoryFile mfs);
7+
8+
static {
9+
System.loadLibrary("ipc_shared");
10+
}
11+
}

src/io/vec/demo/android/ipc/MainActivity.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package io.vec.demo.android.ipc;
22

3-
import android.os.Bundle;
3+
import java.io.IOException;
4+
45
import android.app.Activity;
6+
import android.os.Bundle;
7+
import android.os.MemoryFile;
8+
import android.util.Log;
59
import android.view.Menu;
610

711
public class MainActivity extends Activity {
@@ -10,11 +14,18 @@ public class MainActivity extends Activity {
1014
protected void onCreate(Bundle savedInstanceState) {
1115
super.onCreate(savedInstanceState);
1216
setContentView(R.layout.activity_main);
17+
try {
18+
MemoryFile mf = new MemoryFile("shm-demo", 1024);
19+
boolean ipcStatus = IPC.setMemoryFile(mf);
20+
Log.i("AndroidIPC::SHM", "IPC.setMemoryFile " + ipcStatus);
21+
mf.close();
22+
} catch (IOException e) {
23+
e.printStackTrace();
24+
}
1325
}
1426

1527
@Override
1628
public boolean onCreateOptionsMenu(Menu menu) {
17-
// Inflate the menu; this adds items to the action bar if it is present.
1829
getMenuInflater().inflate(R.menu.main, menu);
1930
return true;
2031
}

0 commit comments

Comments
 (0)