Binder 架构
名词解析:Bn: Bindernative,本地;Bp:Binderproxy,代理。I:IInterface;Binder 应用架构逻辑如下:
备注:实心箭头为调用关系;空心箭头为继承关系;
iclient的实现
/***************************************************************************/
itestclient.h
#ifndef ANDROID_ITESTCLIENT_H
#define ANDROID_ITESTCLIENT_H
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
namespace android {
class ITestClient: public IInterface
{
public:
DECLARE_META_INTERFACE(TestClient);
virtual void notify(int msg, int ext1, int ext2,const Parcel*p_obj) = 0;
};
// ----------------------------------------------------------------------------
class BnTestClient: public BnInterface<ITestClient>
{
public:
virtual status_t onTransact( uint32_tcode,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
}; // namespace android
#endif // ANDROID_ITESTCLIENT_H
/***************************************************************************/
itestclient.cpp
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <utils/Errors.h> // for status_t
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include "itestclient.h"
namespace android {
enum {
NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
};
class BpTestClient: public BpInterface<ITestClient>
{
public:
BpTestClient(const sp<IBinder>& impl)
: BpInterface<ITestClient>(impl)
{
}
virtual void notify(int msg, int ext1, int ext2, constParcel *p_obj)
{
Parcel data, reply;
data.writeInterfaceToken(ITestClient::getInterfaceDescriptor());
data.writeInt32(msg);
data.writeInt32(ext1);
data.writeInt32(ext2);
if (p_obj &&p_obj->dataSize() > 0) {
data.appendFrom(const_cast<Parcel *>(p_obj), 0, p_obj->dataSize());
}
//remote()->transact(NOTIFY,data, &reply, IBinder::FLAG_ONEWAY);/****async,异步调用*****/
remote()->transact(NOTIFY, data,&reply);/***sync,同步调用**/
reply.readInt32();
return;
}
};
IMPLEMENT_META_INTERFACE(TestClient, "android.os.ITestClient");
// ----------------------------------------------------------------------
status_t BnTestClient::onTransact(
uint32_t code, const Parcel& data, Parcel* reply,uint32_t flags)
{
switch (code) {
case NOTIFY: {
CHECK_INTERFACE(ITestClient, data, reply);
int msg =data.readInt32();
int ext1 =data.readInt32();
int ext2 =data.readInt32();
Parcel obj;
if(data.dataAvail() > 0) {
obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(),data.dataAvail());
}
//__android_log_print(ANDROID_LOG_VERBOSE, "itestclient","notify:0x%x-0x%x-0x%x\n",msg,ext1,ext2);
notify(msg,ext1, ext2, &obj);
reply->writeInt32(NO_ERROR);
returnNO_ERROR;
} break;
default:
returnBBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android
client的实现
/***************************************************************************/
testclient.h
#ifndef _TESTCLIENT_H_
#define _TESTCLIENT_H_
#include "listener.h"
namespace android {
class Testclient : public BnTestClient
{
public:
Testclient();
~Testclient();
int destory();
int testSiRequest(test_request_t *p_test);
int testSiFree(test_request_t *p_test);
status_t setListener(const sp<Listener>&listener);
sp<Listener> getListener(void);
virtual void notify(int msg, int ext1, int ext2, constParcel *p_obj);
private:
sp<Testclient> mclient_class;
sp<ITESTService> test_service_proxy;
sp<IServiceManager> sm;
sp<IBinder> binder;
Mutex mLock;
sp<Listener> mListener;
};
};
#endif
/***************************************************************************/
testclient.cpp
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h> // for status_t
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include "itestclient.h"
#include "itestservice.h"
#include "listener.h"
#include <utils/Log.h>
extern "C" {
#include "sys_types.h"
#include "dvb_test_attr.h"
};
#include "testclient.h"
#define TEST_CLIENT_LOG_TAG "testclient"
#ifdef TEST_CLIENT_LOG_TAG
#define Testclientprintfv(...) __android_log_print(ANDROID_LOG_VERBOSE, TEST_CLIENT_LOG_TAG,__VA_ARGS__)
#define Testclientprintfd(...) __android_log_print(ANDROID_LOG_DEBUG, TEST_CLIENT_LOG_TAG,__VA_ARGS__)
#define Testclientprintfi(...) __android_log_print(ANDROID_LOG_INFO, TEST_CLIENT_LOG_TAG,__VA_ARGS__)
#define Testclientprintfw(...) __android_log_print(ANDROID_LOG_WARN, TEST_CLIENT_LOG_TAG,__VA_ARGS__)
#define Testclientprintfe(...) __android_log_print(ANDROID_LOG_ERROR, TEST_CLIENT_LOG_TAG,__VA_ARGS__)
#else
#define Testclientprintfv(...)
#define Testclientprintfd(...)
#define Testclientprintfi(...)
#define Testclientprintfw(...)
#define Testclientprintfe(...)
#endif
namespace android
{
Testclient::Testclient()
{
mclient_class = this;
Testclientprintfv("#### testclientinit\n");
sm = defaultServiceManager();
binder = sm->getService(String16("service.test"));
if (binder == NULL) {
//aout << "service.test cannot found!"<< endl;
Testclientprintfe("#### service.si cannotfound\n");
return;
}
test_service_proxy = interface_cast<ITESTService>(binder);
test_service_proxy->createClient(this,(int)mclient_class.get());
Testclientprintfv("#### testclient[0x%x] init isok\n", (int)mclient_class.get());
return;
}
Testclient::~Testclient()
{
Testclientprintfv("#### testclient ~Testclient\n");
}
int Testclient::destory(void)
{
if (test_service_proxy == NULL) {
Testclientprintfe("#### test_service_proxy cannotfound\n");
return (UNKNOWN_ERROR);
}
Testclientprintfv("#### destory testclient[0x%x]\n",(int)mclient_class.get());
Mutex::Autolock _l(mLock);
test_service_proxy->destoryClient(this, (int)mclient_class.get());
mclient_class = NULL;
return (NO_ERROR);
}
int Testclient::testSiRequest(test_request_t *p_test)
{
if (test_service_proxy == NULL) {
Testclientprintfe("#### test_service_proxy cannotfound\n");
return (UNKNOWN_ERROR);
}
Mutex::Autolock _l(mLock);
Parcel mobj;
mobj.setDataPosition(0);
mobj.write((u8 *)p_test, sizeof(test_request_t));
mobj.setDataPosition(0);
test_service_proxy->testSiRequest(&mobj);
mobj.freeData();
return (NO_ERROR);
}
int Testclient::testSiFree(test_request_t *p_test)
{
if (test_service_proxy == NULL) {
Testclientprintfe("#### test_service_proxy cannotfound\n");
return (UNKNOWN_ERROR);
}
Mutex::Autolock _l(mLock);
Parcel mobj;
mobj.setDataPosition(0);
mobj.write((u8 *)p_test, sizeof(test_request_t));
mobj.setDataPosition(0);
test_service_proxy->testSiFree(&mobj);
mobj.freeData();
return (NO_ERROR);
}
status_t Testclient::setListener(const sp<Listener> &listener)
{
Testclientprintfv("setListener");
Mutex::Autolock _l(mLock);
mListener = listener;
return NO_ERROR;
}
sp<Listener> Testclient::getListener(void)
{
return mListener;
}
void Testclient::notify(int msg, int ext1, int ext2, const Parcel *p_obj)
{
//Testclientprintfv("notify msg=%d, ext1=%d,ext2=%d", msg, ext1, ext2);
sp<Listener> listener = mListener;
if (listener != NULL) {
int size = p_obj->dataSize();
unsigned char *p_buffer_parcel = NULL;
if (size > 0) {
p_buffer_parcel = (unsigned char*)malloc(size);
if (NULL != p_buffer_parcel) {
p_obj->setDataPosition(0);
p_obj->read(p_buffer_parcel, size);
p_obj->setDataPosition(0);
} else {
size = 0;
;
}
}
listener->notify(msg, ext1, ext2, p_buffer_parcel, size);
if ((size > 0) && (NULL != p_buffer_parcel)) {
free(p_buffer_parcel);
}
}
}
}
iservice的实现
/***************************************************************************/
itestservice.h
#ifndef _ITESTSERVICE_H_
#define _ITESTSERVICE_H_
#include <utils/Errors.h> // for status_t
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
namespace android {
class ITESTService: public IInterface
{
public:
DECLARE_META_INTERFACE(TESTService);
// declare what this service can do
virtual status_t createClient(const sp<ITestClient>&client,int clientId) =0;
virtual status_t destoryClient(const sp<ITestClient>&client,int clientId) =0;
virtual status_t testSiRequest(const Parcel *p_obj) = 0;
virtual status_t testSiFree(const Parcel *p_obj) = 0;
enum {
TEST_SERVICE_CREAT =IBinder::FIRST_CALL_TRANSACTION,
TEST_SERVICE_DESTORY,
TEST_SERVICE_SI_REQUEST,
TEST_SERVICE_SI_FREE,
};
};
// ----------------------------------------------------------------------------
class BnTESTService: public BnInterface<ITESTService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel *reply,
uint32_t flags = 0);
};
};// namespace android
#endif//end of _ITESTSERVICE_H_
/***************************************************************************/
itestservice.cpp
#include <stdint.h>
#include <sys/types.h>
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include "itestclient.h"
#include "itestservice.h"
namespace android {
// ----------------------------------------------------------------------
class BpTESTService : public BpInterface<ITESTService>
{
public:
BpTESTService(const sp<IBinder> &impl)
: BpInterface<ITESTService>(impl)
{
}
virtual status_t createClient(const sp<ITestClient>&client,int clientId)
{
Parcel data, reply;
data.writeInterfaceToken(ITESTService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(clientId);
remote()->transact(TEST_SERVICE_CREAT,data, &reply);
return reply.readInt32();
}
virtual status_t destoryClient(const sp<ITestClient>&client,int clientId)
{
Parcel data, reply;
data.writeInterfaceToken(ITESTService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(clientId);
remote()->transact(TEST_SERVICE_DESTORY,data, &reply);
return reply.readInt32();
}
virtual status_t testSiRequest(const Parcel *p_obj)
{
Parcel data, reply;
//__android_log_print(ANDROID_LOG_VERBOSE,"itestservice","TestServiceControl:%d,%d,%d\n",cmd,data1,data2);
data.writeInterfaceToken(ITESTService::getInterfaceDescriptor());
if (p_obj && p_obj->dataSize() >0) {
data.appendFrom(const_cast<Parcel *>(p_obj), 0, p_obj->dataSize());
}
remote()->transact(TEST_SERVICE_SI_REQUEST,data, &reply);
return reply.readInt32();
}
virtual status_t testSiFree(const Parcel *p_obj)
{
Parcel data, reply;
//__android_log_print(ANDROID_LOG_VERBOSE,"itestservice","TestServiceControl:%d,%d,%d\n",cmd,data1,data2);
data.writeInterfaceToken(ITESTService::getInterfaceDescriptor());
if (p_obj && p_obj->dataSize() >0) {
data.appendFrom(const_cast<Parcel *>(p_obj), 0, p_obj->dataSize());
}
remote()->transact(TEST_SERVICE_SI_FREE,data, &reply);
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(TESTService, "android.os.ITESTService");
// ----------------------------------------------------------------------
String16 TESTServiceID("android.os.ITESTService");
status_t BnTESTService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply,uint32_t flags)
{
CHECK_INTERFACE(ITESTService, data, reply);
switch (code) {
case TEST_SERVICE_CREAT:
{
sp<ITestClient>client =
interface_cast<ITestClient>(data.readStrongBinder());
int clientId =data.readInt32();
createClient(client,clientId);
return(reply->writeInt32(NO_ERROR));
}
break;
case TEST_SERVICE_DESTORY:
{
sp<ITestClient> client =
interface_cast<ITestClient>(data.readStrongBinder());
int clientId =data.readInt32();
destoryClient(client,clientId);
return(reply->writeInt32(NO_ERROR));
}
break;
case TEST_SERVICE_SI_REQUEST:
{
Parcelobj;
if(data.dataAvail() > 0) {
obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(),data.dataAvail());
}
//__android_log_print(ANDROID_LOG_VERBOSE, "itestservice","TestServiceControl(ontransact):%d,%d,%d\n",cmd,data1,data2);
testSiRequest(&obj);
return(reply->writeInt32(NO_ERROR));
}
break;
case TEST_SERVICE_SI_FREE:
{
Parcel obj;
if (data.dataAvail() > 0) {
obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(),data.dataAvail());
}
//__android_log_print(ANDROID_LOG_VERBOSE, "itestservice","TestServiceControl(ontransact):%d,%d,%d\n",cmd,data1,data2);
testSiFree(&obj);
return(reply->writeInt32(NO_ERROR));
}
break;
default:
return(BBinder::onTransact(code, data, reply, flags));
}
return (0);
}
};// namespace android
service的实现
testservice.h
#define TEST_CLIENT_MAX_NUMBER 16
namespace android
{
typedef struct tg_ITestClient
{
int gfixed;
int client_id;
sp<ITestClient> mclient;
} ITestClient_t;
class TESTService : public BnTESTService
{
public:
TESTService();
~TESTService();
void clientNotify(BOOL msgSync, int clientId, int msg, intext1, int ext2, const Parcel *p_obj);
virtual status_t createClient(const sp<ITestClient>&client, int clientId);
virtual status_t destoryClient(const sp<ITestClient>&client, int clientId);
virtual status_t testSiRequest(const Parcel *p_obj);
virtual status_t testSiFree(const Parcel *p_obj);
private:
ITestClient_t *getFreeTestClient(int clientId);
ITestClient_t *getBusyTestClient(int clientId);
ITestClient_t clientTab[TEST_CLIENT_MAX_NUMBER];
Mutex mLock;
BOOL gFail;
};
}; // namespace android
/***************************************************************************/
testservice.cpp
#include <stdint.h>
#include <sys/types.h>
#include <utils/Errors.h> // for status_t
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include "itestclient.h"
#include "testservice.h"
#include <utils/Log.h>
#define TEST_SERVICE_LOG_TAG "testservie"
#ifdef TEST_SERVICE_LOG_TAG
#define Testserviceprintfv(...) __android_log_print(ANDROID_LOG_VERBOSE, TEST_SERVICE_LOG_TAG,__VA_ARGS__)
#define Testserviceprintfd(...) __android_log_print(ANDROID_LOG_DEBUG, TEST_SERVICE_LOG_TAG,__VA_ARGS__)
#define Testserviceprintfi(...) __android_log_print(ANDROID_LOG_INFO, TEST_SERVICE_LOG_TAG,__VA_ARGS__)
#define Testserviceprintfw(...) __android_log_print(ANDROID_LOG_WARN, TEST_SERVICE_LOG_TAG,__VA_ARGS__)
#define Testserviceprintfe(...) __android_log_print(ANDROID_LOG_ERROR, TEST_SERVICE_LOG_TAG,__VA_ARGS__)
#else
#define Testserviceprintfv(...)
#define Testserviceprintfd(...)
#define Testserviceprintfi(...)
#define Testserviceprintfw(...)
#define Testserviceprintfe(...)
#endif
#define ALIGN4_SIZE(s) (((s) + 3) & ~3)
//using namespace android;
namespace android
{
static sp<TESTService> mServiceheadle = NULL;
extern "C" {
void testSiNotify(notify_msg_t *p_msg)
{
// int i = 0;
int msg_id = p_msg->msg_type;
int data1 = p_msg->tableId;
int data2 = p_msg->dataType;
int data_size = p_msg->data_size;
int clientId = p_msg->clientId;
unsigned char *p_parce_buff = (unsigned char*)p_msg->p_data;
if (mServiceheadle == NULL) {
Testserviceprintfe("serviece is NULL\n");
return;
}
if (p_parce_buff != NULL) {
Parcel mobj;
int parcel_size = 0;
parcel_size = ALIGN4_SIZE(data_size);
/****user java parcel readByteArray*******/
mobj.writeInt32(parcel_size);
mobj.write(p_parce_buff, parcel_size);
mobj.setDataPosition(0);
//Testserviceprintfv("send message(parcel) msg id =0x%x,data1 =x%x,data1 =x%x, data size =%d\n",msg_id,data1,data2,mobj.dataSize());
//Testserviceprintfv("send message(parcel) msg info:%s\n",(char *)p_parce_buff);
mServiceheadle->clientNotify(p_msg->msgSync, clientId,msg_id, data1, data2, &mobj);
mobj.freeData();
} else {
//Testserviceprintfv("send message msg id = 0x%x,data1=x%x,data1 =x%x,\n",msg_id,data1,data2);
mServiceheadle->clientNotify(p_msg->msgSync, clientId,msg_id, data1, data2, NULL);
}
}
};
TESTService::TESTService()
{
void *p_handle = NULL;
Testserviceprintfv("test service init\n");
gFail = FALSE;
memset(clientTab, 0, sizeof(ITestClient_t) * TEST_CLIENT_MAX_NUMBER);
p_handle = test_svc_init();
if (p_handle == NULL) {
gFail = TRUE;
Testserviceprintfv("test service init fail!\n");
}
mServiceheadle = this;
}
TESTService::~TESTService()
{
Testserviceprintfv("test service destory\n");
if (gFail == FALSE) {
test_svc_deinit();
}
memset(clientTab, 0, sizeof(ITestClient_t) * TEST_CLIENT_MAX_NUMBER);
mServiceheadle = NULL;
}
ITestClient_t *TESTService::getFreeTestClient(int clientId)
{
int i = 0;
for (i = 0; i < TEST_CLIENT_MAX_NUMBER; i++) {
if ((clientTab[i].client_id == clientId) &&
(clientTab[i].gfixed == true)) {
return NULL;
}
}
for (i = 0; i < TEST_CLIENT_MAX_NUMBER; i++) {
if (clientTab[i].gfixed == false) {
return &clientTab[i];
}
}
return NULL;
}
ITestClient_t *TESTService::getBusyTestClient(int clientId)
{
int i = 0;
for (i = 0; i < TEST_CLIENT_MAX_NUMBER; i++) {
if ((clientTab[i].client_id == clientId) &&
(clientTab[i].gfixed == true)) {
return &clientTab[i];
}
}
return NULL;
}
void TESTService::clientNotify(BOOL msgSync, int clientId, int msg, int ext1,int ext2, const Parcel *p_obj)
{
unsigned char i = 0;
if (msgSync != TRUE) {
Mutex::Autolock l(mLock);
}
for (i = 0; i < TEST_CLIENT_MAX_NUMBER; i++) {
if ((clientTab[i].gfixed == true) &&(clientTab[i].client_id == clientId)) {
sp<ITestClient> testclient =clientTab[i].mclient;
testclient->notify(msg, ext1, ext2,p_obj);
}
}
}
status_t TESTService::createClient(const sp<ITestClient> &client, intclientId)
{
ITestClient_t *p_iclient = NULL;
Testserviceprintfv("create client[0x%x] start\n",clientId);
Mutex::Autolock l(mLock);
Testserviceprintfv("create client[0x%x]endlock\n", clientId);
p_iclient = getFreeTestClient(clientId);
if (p_iclient == NULL) {
Testserviceprintfe("create client[0x%x] fail\n",clientId);
return (UNKNOWN_ERROR);
}
p_iclient->mclient = client;
p_iclient->client_id = clientId;
p_iclient->gfixed = true;
Testserviceprintfv("create client[0x%x]\n",clientId);
return (NO_ERROR);
}
status_t TESTService::destoryClient(const sp<ITestClient> &client,int clientId)
{
ITestClient_t *p_iclient = NULL;
Mutex::Autolock l(mLock);
p_iclient = getBusyTestClient(clientId);
if (p_iclient == NULL) {
Testserviceprintfe("destory client[0x%x]\n",clientId);
return (UNKNOWN_ERROR);
}
p_iclient->mclient = NULL;
p_iclient->client_id = 0;
p_iclient->gfixed = false;
Testserviceprintfv("create client[0x%x]\n",clientId);
return (NO_ERROR);
}
status_t TESTService::testSiRequest(const Parcel *p_obj)
{
unsigned char *p_data_buff = NULL;
int data_size = 0;
req_test_t requestParam;
memset(&requestParam, 0, sizeof(req_test_t));
Mutex::Autolock l(mLock);
if (p_obj && p_obj->dataSize() > 0) {
data_size = p_obj->dataSize();
p_data_buff = (unsigned char *)malloc(data_size);
if (p_data_buff != NULL) {
p_obj->setDataPosition(0);
p_obj->read(p_data_buff, data_size);
} else {
Testserviceprintfe("TestServiceControl:malloc:%d fail\n", data_size);
return (UNKNOWN_ERROR);
}
if (data_size == sizeof(test_request_t)) {
memcpy(&requestParam.request,p_data_buff, data_size);
requestParam.notify = (test_notify_t)testSiNotify;
test_svc_request(&requestParam);
free(p_data_buff);
return (NO_ERROR);
} else {
free(p_data_buff);
}
}
return (UNKNOWN_ERROR);
}
status_t TESTService::testSiFree(const Parcel *p_obj)
{
unsigned char *p_data_buff = NULL;
int data_size = 0;
req_test_t requestParam;
memset(&requestParam, 0, sizeof(req_test_t));
Mutex::Autolock l(mLock);
if (p_obj && p_obj->dataSize() > 0) {
data_size = p_obj->dataSize();
p_data_buff = (unsigned char *)malloc(data_size);
if (p_data_buff != NULL) {
p_obj->setDataPosition(0);
p_obj->read(p_data_buff, data_size);
} else {
Testserviceprintfe("TestServiceControl:malloc:%d fail\n", data_size);
return (UNKNOWN_ERROR);
}
if (data_size == sizeof(test_request_t)) {
memcpy(&requestParam.request,p_data_buff, data_size);
requestParam.notify = (test_notify_t)testSiNotify;
test_svc_free(&requestParam);
free(p_data_buff);
return (NO_ERROR);
} else {
free(p_data_buff);
}
}
return (UNKNOWN_ERROR);
}
}; // namespace android
Lister
/***************************************************************************/
listener.h
#ifndef _LISTENER_H_
#define _LISTENER_H_
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/Errors.h> // for status_t
#include "utils/KeyedVector.h"
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
namespace android {
class Listener : virtual public RefBase
{
public:
virtual void notify(int msg, int ext1, int ext2, unsigned char *p_data,unsigned int dataSize) =0;
};
class JNIListener: public Listener
{
public:
JNIListener(JNIEnv* env, jobject thiz,jmethodID callMethodId);
~JNIListener();
virtual void notify(int msg, int ext1, int ext2,unsigned char *p_data,unsigned int dataSize) ;
private:
JNIListener();
jmethodID mpost_event;
jclass mClass; // Reference to MediaPlayer class
};
};
#endif
/***************************************************************************/
listener.cpp
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <utils/threads.h>
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/Errors.h> // for status_t
#include "utils/KeyedVector.h"
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Log.h>
#include <android/log.h>
#include <cutils/log.h>
#include <log/log.h>
#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "listener.h"
namespace android
{
JNIListener::JNIListener(JNIEnv *env, jobject thiz, jmethodID callMethodId)
{
// Hold onto the MediaPlayer class for use in calling the static method
// that posts events to the application thread.
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
ALOGE("Can't find android/os/dvb");
jniThrowException(env, "java/lang/Exception", NULL);
return;
}
mClass = (jclass)env->NewGlobalRef(clazz);
mpost_event = callMethodId;
__android_log_print(ANDROID_LOG_VERBOSE, "dvbclientlistener", "#### JNIListener ok\n");
}
JNIListener::~JNIListener()
{
// remove global references
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteGlobalRef(mClass);
__android_log_print(ANDROID_LOG_VERBOSE, "dvbclientlistener", "#### ~JNIListener ok\n");
}
void JNIListener::notify(int msg, int ext1, int ext2, unsigned char *p_data, unsigned int dataSize)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
//__android_log_print(ANDROID_LOG_VERBOSE,"dvbclientjni","notify");
if ((p_data != NULL) && (dataSize > 0)) {
#if 1
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
Parcel *nativeParcel = parcelForJavaObject(env, jParcel);
if (NULL != nativeParcel) {
nativeParcel->setData(p_data, dataSize);
nativeParcel->setDataPosition(0);
env->CallStaticVoidMethod(mClass, mpost_event,
msg, ext1, ext2, jParcel);
}
env->DeleteLocalRef(jParcel);
}
#else
int size = p_obj->dataSize();
__android_log_print(ANDROID_LOG_VERBOSE, "dvbclientjni", "notify call message(parcel) msg id = 0x%x,data1 =x%x,data1 =x%x, data size = %d\n",
msg, ext1, ext2, size);
char *p_buffer_parcel = (char *)malloc(size);
if (NULL != p_buffer_parcel) {
p_obj->setDataPosition(0);
p_obj->read(p_buffer_parcel, size);
p_obj->setDataPosition(0);
// __android_log_print(ANDROID_LOG_VERBOSE, "dvbclientjni","notify call message(parcel) msg info:%s\n",(char *)p_buffer_parcel);
jbyteArray jbarr = env->NewByteArray(size);
if (jbarr != NULL) {
jbyte *bytekey = env->GetByteArrayElements(jbarr, 0);
if (bytekey != NULL) {
int bytekeylen = env->GetArrayLength(jbarr);
memcpy(bytekey, p_buffer_parcel, bytekeylen);
env->CallStaticVoidMethod(mClass, mpost_event, msg, ext1, ext2, jbarr);
env->ReleaseByteArrayElements(jbarr, bytekey, 0);
env->DeleteLocalRef(jbarr);
}
}
free(p_buffer_parcel);
}
#endif
} else {
// __android_log_print(ANDROID_LOG_VERBOSE, "dvbclientjni","notify call message msg id = 0x%x,data1 =x%x,data1 =x%x\n",
// msg,ext1,ext2);
env->CallStaticVoidMethod(mClass, mpost_event, msg, ext1, ext2, NULL);
}
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
//LOGW_EX(env);
env->ExceptionClear();
}
}
}
service process
#include<binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include "testservice.h"
using namespace android;
int main(int argc, char **argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("service.test"), new TESTService());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return(0);
}
android.mk
LOCAL_C_INCLUDES := \
external/jhead \
external/tremor/Tremor \
$(TOP)/frameworks/base/core/jni
LOCAL_SRC_FILES := \
$(call all-cpp-files-under,binder) \
$(call all-cpp-files-under,jniListener) \
LOCAL_SHARED_LIBRARIES += libutils libbinder libandroid_runtime
加入启动服务
service testserver /system/bin/testserver
class main