怎么写一个native层的ssh service层怎么写

c/c++ 技术开发(10)
Android 系统开发(17)
一、 Android Service 介绍
Android 的 Service 分为两种: Android Service 和 Native Service 。
Android Service :又称为 Java Service ,是实现在框架层( framework )里的 Server 。 Android Service 以 Java 编写。
Native Service :又称为 System Service ,是实现在 Runtime 层里的 Server 。
以 MediaPlayer 为例,从下图我们可以得出两种服务的关系:
接下来要讨论的 Service 是 Native Service ,与应用程序设计上所讨论的 Service ( android.app.Service )不同。
二、为什么要写底层的核心服务呢?
( 1 ) 因为底层核心服务是 Android 框架里最接近 Linux/Driver 的部分。为了充分发挥硬件设备的差异化特性,核心服务是让上层 Java 应用程序来使用 Driver/HW Device 特色的重要管道。
( 2 ) 在开机过程中,就可以启动核心服务 ( 例如汉字输入法服务等 ) ,让众多应用程序来共享之。
( 3 ) 由于共享,所以能有效降低 Java 应用程序的大小 (Size) 。
三、如何实现一个核心服务呢 ?
要点如下:
( 1 )核心服务通常在独立的进程 (Process) 里执行。
( 2 )必须提供 IBinder 接口,让应用程序可以进行跨进程的绑定 (Binding) 和呼叫。
( 3 )因为共享,所以必须确保多线裎安全 (Thread-safe) 。
( 4 )以 C++ 类别定义,诞生其对象,透过 SM 之协助,将该对象参考值传给 IServiceManager::addService() 函数,就加入到 Binder Driver 里了。
( 5 )应用程序可透过 SM 之协助而远距绑定该核心服务,此时 SM 会回传 IBinder 接口给应用程序。
( 6 )应用程序可透过 IBinder::transact() 函数来与核心服务互传数据。
四、 Server 实现实践
下面以一个小例子来说明具体实现一个 Server 的步骤。此实例功能为简单的整数加法 (Add) 运算,我们将其命名 AddService 。
Step-1 :以 C++ 撰写 AddService 类别,其完整程序代码为:
AddService.h 文件:
#ifndef ANDROID_GUILH_ADD_SERVICE_H
#define ANDROID_GUILH_ADD_SERVICE_H
#include &utils.h&
#include &utils/RefBase.h&
#include &utils/IInterface.h&
#include &utils/Parcel.h&
namespace android
& & & &class AddService : public BBinder
& & & & & & & mutable Mutex mL
& & & & & & & int32_t mNextConnId;
& & & & & & & public:
& & & & & & & static int instantiate();
& & & & & & & AddService();
& & & & & & & virtual ~AddService();
& & & & & & & virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
AddService.cpp 文件:
#include &AddService.h&
#include &utils/IServiceManager.h&
#include &utils/IPCThreadState.h&
namespace android {
& & & &static str
& & & &static pthread_key_
& & & &int AddService::instantiate() {
& & & & & & & LOGE(&AddService instantiate&);
& & & & & & & int r = defaultServiceManager()-&addService(
& & & & & & & & & & & & & & String16(&guilh.add&), new AddService());
& & & & & & & LOGE(&AddService r = %d\n&, r);
& & & & & & &
& & & &AddService::AddService()
& & & &{ LOGV(&AddService created&);
& & & & & & & mNextConnId = 1;
& & & & & & & pthread_key_create(&sigbuskey, NULL);
& & & &AddService::~AddService()
& & & &{ pthread_key_delete(sigbuskey);
& & & & & & & LOGV(&AddService destroyed&);
& & & &status_t AddService::onTransact(
& & & & & & & & & & &uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
& & & & & & & switch(code) {
& & & & & & & & & & &case 0: {
& & & & & & & & & & & & & & & & & &pid_t pid = data.readInt32();
& & & & & & & & & & & & & & & & & &int num = data.readInt32();
& & & & & & & & & & & & & & & & & &num = num + 1000;
& & & & & & & & & & & & & & & & & &reply-&writeInt32(num);
& & & & & & & & & & & & & & & & & &return NO_ERROR;
& & & & & & & & & & & & & & }
& & & & & & & & & & &default:
& & & & & & & & & & & & & & return BBinder::onTransact(code, data, reply, flags);
& & & & & & & }
Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= AddService.cpp
#LOCAL_C_INCLUDES:= $(JNI_H_INCLUDE) &&
LOCAL_SHARED_LIBRARIES:= libutils
LOCAL_MODULE:= libAddService
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
Step-2 :以 C++ 撰写一个可独立执行的 addserver.cpp 程序,它的用途是:诞生一个 AddService 类别之对象,然后将该对象参考存入 Binder Driver 里。其内容为:
addserver.cpp 文件:
#include &sys/types.h&
#include &unistd.h&
#include &grp.h&
#include &utils/IPCThreadState.h&
#include &utils/ProcessState.h&
#include &utils/IServiceManager.h&
#include &utils/Log.h&
#include &private/android_filesystem_config.h&
#include &../libaddservice/AddService.h&
int main(int argc, char** argv)
sp&ProcessState& proc(ProcessState::self());
sp&IServiceManager& sm = defaultServiceManager();
LOGI(&ServiceManager: %p&, sm.get());
AddService::instantiate();
ProcessState::self()-&startThreadPool();
IPCThreadState::self()-&joinThreadPool();
Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= addserver.cpp
LOCAL_SHARED_LIBRARIES:= libutils libAddService
LOCAL_MODULE:= addservice
include $(BUILD_EXECUTABLE)
Step-3 :编译上述两个文件分别产出了 libAdd.so 类别库和 addserver 可执行程序。接着将 libAdd.so 拷贝到 Android 仿真器的 /system/lib/ 里;也把 addserver 拷贝到 /system/bin/ 里。
Step-4 :执行 addserver 。其中的指令: AddServer::instantiate() 就执行到 AddServer 类别的 instantiate() 函数,其内容为:
int AddService::instantiate() {
LOGE(&AddService instantiate&);
int r = defaultServiceManager()-&addService(
String16(&guilh.add&), new AddService());
LOGE(&AddService r = %d\n&, r);
其先执行到 new AddServer() ,就诞生一个 AddServer 类别之对象;
接着,呼叫 defaultServiceManager() 函数取得 SM 的 IServiceManager 接口;
再呼叫 IServiceManager::addServer() 将该对象参考存入 Binder Driver 里。
Step-5 :这样就成功地将 AddService 服务加入到 Binder Driver 里了。现在就可以写个 Add 类来使用 AddService 核心服务了。以 C++ 撰写 Add 类别,其完整程序代码为:
Add.h 文件:
#ifndef ANDROID _ADD_H
#define ANDROID _ADD_H
namespace android {
& & & &class Add {
& & & & & & & public:
& & & & & & & & & & &int setN(int n);
& & & & & & & private:
& & & & & & & & & & &static const void getAddService();
}; //namespace
#endif // ANDROID _ADD_H
Add.cpp 文件:
#include &utils/IServiceManager.h&
#include &utils/IPCThreadState.h&
#include &Add.h&
namespace android {
& & & &sp&IBinder&
& & & &int Add::setN(int n){
& & & & & & & getAddService();
& & & & & & & Parcel data,
& & & & & & & data.writeInt32(getpid());
& & & & & & & data.writeInt32(n);
& & & & & & & LOGE(&BpAddService::create remote()-&transact()\n&);
& & & & & & & binder-&transact(0, data, &reply);
& & & & & & & int i = reply.readInt32();
& & & & & & &
& & & &const void Add::getAddService(){
& & & & & & & sp&IServiceManager& sm = defaultServiceManager();
& & & & & & & binder = sm-&getService(String16(&guilh.add&));
& & & & & & & LOGE(&Add::getAddService %p\n&,sm.get());
& & & & & & & if (binder == 0) {
& & & & & & & & & & &LOGW(&AddService not published, waiting...&);
& & & & & & & & & & &
& & & & & & & }
Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=Add.cpp
LOCAL_SHARED_LIBRARIES := libutils libAddService
LOCAL_MODULE := libAdd
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
Step-6 :下面写个 JNI Native 类别来使用 Add 类别之对象。透过 JNI Native 函数,就可以与 Java 层的 Service 服务衔接起来。
首选使用 javah 命令生成相应头文件。
com_hello_Service_MySer.h 文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include &jni.h&
/* Header for class com_hello_Service_MySer */
#ifndef _Included_com_hello_Service_MySer
#define _Included_com_hello_Service_MySer
#ifdef __cplusplus
extern &C& {
& * Class: & & com_hello_Service_MySer
& * Method: & &intFromJNI
& * Signature: ()I
JNIEXPORT jint JNICALL Java_com_hello_Service_MySer_intFromJNI
& (JNIEnv *, jobject);
#ifdef __cplusplus
然后实现相应函数。
com_hello_Service_MySer.cpp 文件:
#include &jni.h&
#include &JNIHelp.h&
#include &../libadd/Add.h&
#include &com_hello_Service_MySer.h&
JNIEXPORT jint JNICALL Java_com_hello_Service_MySer_intFromJNI(JNIEnv * env, jobject thiz)
& & android::A
& & & &int r = myadd.setN(5);
Android.mk 文件:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=com_hello_Service_MySer.cpp
LOCAL_C_INCLUDES:= $(JNI_H_INCLUDE) &&
LOCAL_SHARED_LIBRARIES := libutils libAdd
LOCAL_MODULE := libJniAdd
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
所有相关文件组织:
a@ubuntu:~/work/android/source_android/development/my_module$ tree service
|-- addserver
| & |-- Android.mk
| & `-- addserver.cpp
| & |-- Android.mk
| & |-- com_hello_Service_MySer.cpp
| & `-- com_hello_Service_MySer.h
|-- libadd
| & |-- Add.cpp
| & |-- Add.h
| & `-- Android.mk
`-- libaddservice
& & |-- AddService.cpp
& & |-- AddService.h
& & `-- Android.mk
4 directories, 11 files
在 Eclipse 中创建一个工程使用以上的 Add 类,即可使用我们的 AddService 了。
MySer.java 文件:
package com.hello.S
import android.app.A
import android.os.B
import android.widget.TextV
public class MySer extends Activity {
& & /** Called when the activity is first created. */
& & @Override
& & public void onCreate(Bundle savedInstanceState) {
& & & & super.onCreate(savedInstanceState);
& & & & int i = intFromJNI();
& & & & TextView &tv = new TextView(this);
& & & & tv.setText( String.valueOf(i) );
& & & & setContentView(tv);
& & public native int intFromJNI();
& & & & System.loadLibrary(&JniAdd&);
五、Service 编译问题
Android 所用的 Toolchain (即交叉编译工具链)可从下面的网址下载:
http://android.kernel.org/pub/android-toolchain-.tar.bz2 。如果下载了完整的 Android 项目的源代码,则可以在“ &your_android&/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin ”目录下找到交叉编译工具,比如 Android 所用的 arm-eabi-gcc-4.2.1 。我们可以直接使用源码包来进行编译。
Android 并没有采用 glibc 作为 C 库,而是采用了 Google 自己开发的 Bionic Libc ,它的官方 Toolchain 也是基于 Bionic Libc 而并非 glibc 的。这使得使用或移植其他 Toolchain 来用于 Android 要比较麻烦:在 Google 公布用于 Android 的官方 Toolchain 之前,多数的 Android 爱好者使用的 Toolchain 是在 /gnu_toolchains/arm/download.html
下载的一个通用的 Toolchain ,它用来编译和移植 Android 的 Linux 内核是可行的,因为内核并不需要 C 库,但是开发 Android 的应用程序时,直接采用或者移植其他的 Toolchain 都比较麻烦,其他 Toolchain 编译的应用程序只能采用静态编译的方式才能运行于 Android 模拟器中,这显然是实际开发中所不能接受的方式。目前尚没有看到说明成功移植其他交叉编译器来编译 Android 应用程序的资料。
与 glibc 相比, Bionic Libc 有如下一些特点:
l & & & & 采用 BSD License ,而不是 glibc 的 GPL License ;
l & & & & 大小只有大约 200k ,比 glibc 差不多小一半,且比 glibc 更快;
l & & & & 实现了一个更小、更快的 pthread ;
l & & & & 提供了一些 Android 所需要的重要函数,如” getprop ” , “ LOGI ”等;
l & & & & 不完全支持 POSIX 标准,比如 C++ exceptions , wide chars 等;
l & & & & 不提供 libthread_db 和 libm 的实现
& 另外, Android 中所用的其他一些二进制工具也比较特殊:
加载动态库时使用的是 /system/bin/linker 而不是常用的 /lib/ld.
prelink 工具不是常用的 prelink 而是 apriori ,其源代码位于“ &your_android&/build/tools/apriori ”
strip 工具也没有采用常用的 strip ,而是“ &your_android&/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin ”目录下的 arm-eabi-strip ,而是位于 &your_android&/out/host/linux-x86/bin/ 的 soslim 工具。
下面就具体说一下如何编译我们刚才创建的 Service 程序。
1. 在 $(YOUR_ANDROID)/development 目录下创建 my_module 目录,然后将我们的 server 文件夹拷贝到此目录下,其中 $(YOUR_ANDROID) 指 Android 源代码所在的目录。
& # mkdir $(YOUR_ANDROID)/development/ my_module
2. Android.mk 这是 Android Makefile 的标准命名,不要更改。 Android.mk 文件的格式和内容可以参考其他已有的 Android.mk 文件的写法,针对 Add 程序的 Android.mk 文件内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=Add.cpp
LOCAL_SHARED_LIBRARIES := libutils libAddService
LOCAL_MODULE := libAdd
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
注意上面 LOCAL_SRC_FILES 用来指定源文件;, LOCAL_MODULE 指定要编译的模块的名字,下一步骤编译时就要用到; include $(BUILD_SHARED_LIBRARY) 表示要编译成动态库,如果想编译成一个可执行文件则可用 BUILD_EXECUTABLE ,这些可以在 $(YOUR_ANDROID)/build/core/config.mk 查到。
3. 回到 Android 源代码顶层目录进行编译:
# cd $(YOUR_ANDROID) && make libAdd
注意 make libAdd 中的目标名 libAdd 就是上面 Android.mk 文件中由 LOCAL_MODULE 指定的模块名。
4 .编译后的可执行文件存放在通过” adb push ”将它传送到模拟器上,再通过” adb shell ”登录到模拟器终端,就可以执行了。
六、出现问题及及解决办法:
( 1 )提示缺 bison ,安装 bison : sudo apt-get install bison
( 2 )出现 frameworks/policies/base/PolicyConfig.mk:22: *** No module defined for the given PRODUCT_POLICY (android.policy_phone). &Stop. 错误。
解决办法:
在 build/tools/findleaves.sh 中的第 89 行,
这一句 find &${@:0:$nargs}& $findargs -type f -name &$filename& -print |
改为 find &${@:1:$nargs-1}& $findargs -type f -name &$filename& -print |
&原文地址 http://micklongen./blog/static//
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:494849次
积分:5435
积分:5435
排名:第3524名
原创:73篇
转载:160篇
评论:50条
(20)(21)(2)(1)(1)(1)(3)(1)(6)(6)(6)(4)(2)(3)(2)(8)(1)(10)(5)(10)(10)(2)(2)(2)(4)(24)(8)(17)(2)(3)(8)(1)(20)(18)(1)Android开发(6)
Binder是Android特有的进程间通信(IPC)机制和远程方法调用系统,整个核心平台的跨进程操作几乎都是通过binder进行的,相对于其他的IPC方式,binder有如下特点:
通过驱动程序来进行进程间通信
通过共享内存来提高性能
每个进程都有处理请求的线程池
引用计数功能,支持跨进程的对象引用
进程间同步调用
可以跨进程传输文件描述符
服务端终止通知
这篇文章我通过一个实际的例子来演示如何创建一个本地的binder服务,并验证几个binder的特性,主要演示以下几个功能:
客户端通过binder获取一块共享的匿名内存,把内容给打印出来
客户端通过binder获取一个服务端已经打开的文件的文件描述符,写入内容,并在服务端打印出文件的内容
客户端通过binder设置和获取服务端的一个整数成员
客户端通过binder设置 和获取服务端一个字符串成员
验证binder的death notification功能
通过dumpsys工具获取服务端的信息
演示程序已经上传到,通过下面的命令获取:
git clone https:
1.定义接口
class IIpcTestService : public IInterface
DECLARE_META_INTERFACE(IpcTestService);
virtual sp&IMemory& getMemory() const = 0;
virtual int getFileDescriptor() = 0;
virtual void dumpFile() = 0;
virtual void setInt(int value) = 0;
virtual int getInt() = 0;
virtual void setString(const char* str) = 0;
virtual char* getString() = 0;
class BnIpcTestService : public BnInterface&IIpcTestService&
virtual status_t onTransact(uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
这个接口定义了客户端和服务端进程间通信所用到的所有接口,客户端和服务端都会继承这个接口,并实现。BnIpcTestService是服务端的代理。
2.实现接口
GET_MEMORY = IBinder,
DUMP_FILE,
class BpIpcTestService : public BpInterface&IIpcTestService&
BpIpcTestService(const sp&IBinder&& impl)
: BpInterface&IIpcTestService&(impl)
virtual sp&IMemory& getMemory() const
Parcel data,
sp&IMemory&
data.writeInterfaceToken(IIpcTestService());
status_t status = remote()-&transact(GET_MEMORY, data, &reply);
if (status == NO_ERROR) {
mem = interface_cast&IMemory&(reply.readStrongBinder());
if (mem != 0 && mem-&pointer() == NULL) {
mem.clear();
virtual int getFileDescriptor()
Parcel data,
data.writeInterfaceToken(IIpcTestService());
status_t status = remote()-&transact(GET_FD, data, &reply);
if (status == NO_ERROR) {
fd = dup(reply.readFileDescriptor());
virtual void dumpFile()
Parcel data,
data.writeInterfaceToken(IIpcTestService());
remote()-&transact(DUMP_FILE, data, &reply);
virtual void setInt(int value)
Parcel data,
data.writeInterfaceToken(IIpcTestService());
data.writeInt32(value);
remote()-&transact(SET_INT, data, &reply);
virtual int getInt()
Parcel data,
data.writeInterfaceToken(IIpcTestService());
remote()-&transact(GET_INT, data, &reply);
return reply.readInt32();
virtual void setString(const char* str)
Parcel data,
data.writeInterfaceToken(IIpcTestService());
data.writeCString(str);
remote()-&transact(SET_STR, data, &reply);
virtual char* getString()
Parcel data,
const char* str1;
char* str2;
data.writeInterfaceToken(IIpcTestService());
remote()-&transact(GET_STR, data, &reply);
str1 = reply.readCString();
str2 = (char *)malloc(strlen(str1) + 1);
strcpy(str2, str1);
return str2;
IMPLEMENT_META_INTERFACE(IpcTestService, "android.test.IIpcTestService");
status_t BnIpcTestService(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
switch (code) {
case GET_MEMORY: {
CHECK_INTERFACE(IIpcTestService, data, reply);
reply-&writeStrongBinder(getMemory()-&asBinder());
return NO_ERROR;
case GET_FD: {
CHECK_INTERFACE(IIpcTestService, data, reply);
reply-&writeFileDescriptor(getFileDescriptor());
return NO_ERROR;
case DUMP_FILE: {
CHECK_INTERFACE(IIpcTestService, data, reply);
dumpFile();
return NO_ERROR;
case SET_INT: {
CHECK_INTERFACE(IIpcTestService, data, reply);
setInt(data.readInt32());
return NO_ERROR;
case GET_INT: {
CHECK_INTERFACE(IIpcTestService, data, reply);
reply-&writeInt32(getInt());
return NO_ERROR;
case SET_STR: {
CHECK_INTERFACE(IIpcTestService, data, reply);
setString(data.readCString());
return NO_ERROR;
case GET_STR: {
CHECK_INTERFACE(IIpcTestService, data, reply);
reply-&writeCString(getString());
return NO_ERROR;
return BBinder(code, data, reply, flags);
BpIpcTestService是客户端的代理,客户端使用代理类来跟服务端通信,每一个方法调用都有一个唯一的ID,在服务端的onTransact方法中利用这个ID来调用对应的服务端方法。BpIpcTestService把客户端的方法调用的参数打包成Parcel,通过binder传输到服务端,在服务端解包parcel,把参数传递给对应的方法,服务端的返回值也是通过parcel传输。
3.定义服务端接口
class IpcTestService :
public BinderService&IpcTestService&,
public BnIpcTestService
static const char* getServiceName() { return "android.ipctest";}
IpcTestService();
virtual status_t dump(int fd, const Vector&String16&& args);
virtual sp&IMemory& getMemory() const;
virtual int getFileDescriptor();
virtual void dumpFile();
virtual void setInt(int value);
virtual int getInt();
virtual void setString(const char* str);
virtual char* getString();
virtual void onFirstRef();
sp&MemoryBase& mM
服务端继承自BnIpcTestService。
4. 实现服务端接口
IpcTestService::IpcTestService()
: mMem(NULL),
mIntVal(0),
mStr(NULL)
ALOGD("IpcTestService() is called.");
void IpcTestService::onFirstRef()
ALOGD("onFirstRef() is called.");
mMem = new MemoryBase(new MemoryHeapBase(512, 0, "IpcTestMem"), 0, 512);
strcpy((char *)mMem-&pointer(), "Hello Ashmem");
sp&IMemory& IpcTestService::getMemory() const
ALOGD("getMemory() is called.");
status_t IpcTestService::dump(int fd, const Vector&String16&& args
const size_t SIZE = 256;
char buffer[SIZE];
ALOGD("dump() is called.");
snprintf(buffer, SIZE, "mFd = %d\n"
"mIntVal = %d\n"
"mStr = %s\n",
mFd, mIntVal, mStr);
result.append(buffer);
write(fd, result.string(), result.size());
return NO_ERROR;
int IpcTestService::getFileDescriptor()
ALOGD("getFileDescriptor is called.");
mFd = open("/tmp/ipctest", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
return mFd;
void IpcTestService::dumpFile()
ALOGD("dumpFile is called.");
if (mFd & 0) return;
offset = lseek(mFd, 0, SEEK_CUR);
if (offset & 0) return;
ALOGD("dumpFile: current offset is %d.", offset);
size = lseek(mFd, 0, SEEK_END);
if (size & 0) return;
if (lseek(mFd, 0, SEEK_SET) & 0) return;
ALOGD("dumpFile: file size is %d.", size);
data = (char*)malloc(size);
if (data == 0) return;
if (read(mFd, data, size) & 0) {
free(data);
ALOGD("dumpFile:%s", data);
free(data);
void IpcTestService::setInt(int value)
ALOGD("setInt:%d", value);
int IpcTestService::getInt()
ALOGD("getInt is called");
return mIntV
void IpcTestService::setString(const char *str)
ALOGD("setString:%s", str);
int len = strlen(str);
mStr = (char *)malloc(len+1);
if (mStr != NULL) strcpy(mStr, str);
char* IpcTestService::getString()
ALOGD("getString is called.");
因为所有跟binder通信相关的操作都在服务端的代理BnIpcTestService中实现,所以服务端接口的实现非常简单。
5.实现服务端
int main(int argc __unused, char** argv __unused)
sp&ProcessState& proc(ProcessState::self());
sp&IServiceManager& sm = defaultServiceManager();
IpcTestService::publishAndJoinThreadPool();
服务端的实现非常简单,把Service添加到ServiceManager中,然后 等待客户端建立连接并处理其请求。
6. 实现客户端
class ServerDeathRecipient : public IBinder
virtual void binderDied(const wp&IBinder&& who __unused)
ALOGD("The android.ipctest server is dead!");
int main(int argc __unused, char** argv __unused)
sp&ProcessState& proc(ProcessState());
sp&IServiceManager& sm = defaultServiceManager();
sp&IBinder& binder = sm-&getService(String16("android.ipctest"));
sp&IIpcTestService& ipcTestS
sp&IMemory&
if (binder == 0) {
ALOGE("get ipctest service error!");
sp&ServerDeathRecipient& dr = new ServerDeathRecipient();
binder-&linkToDeath(dr);
ipcTestService = interface_cast&IIpcTestService&(binder);
mem = ipcTestService-&getMemory();
if (mem != 0) {
ALOGD("The ashmem content is:%s", mem-&pointer());
mem.clear();
int fd = ipcTestService-&getFileDescriptor();
if (fd & 0) {
ALOGE("Bad file descriptor!");
const char *str = "Hello World!";
write(fd, str, strlen(str) + 1);
ipcTestService-&dumpFile();
close(fd);
ipcTestService-&setInt(10);
int value = ipcTestService-&getInt();
ALOGD("Got int value:%d", value);
ipcTestService-&setString("Hello World!");
char* string = ipcTestService-&getString();
ALOGD("Got string:%s", string);
free(string);
proc-&startThreadPool();
IPCThreadState()-&joinThreadPool();
客户端先通过 ServiceManager获取服务,然后调用对应的接口来跟服务端交互。
把程序放到Android的代码目录下,在程序目录下执行mm编译,最后会产生/system/bin/IpcTestServer和/system/bin/IpcTestClient两个可执行文件,把这两个文件复制到Android系统中,例如/tmp目录下,然后就可以验证了。
先让服务端运行并打印log:
shell@android:/tmp # logcat | grep IpcTest
shell@android:/tmp # ./IpcTestServer &
可以看到有如下log
D/IpcTestService(18751): IpcTestService() is called.
D/IpcTestService(18751): onFirstRef() is called.
然后运行客户端:
shell@android:/tmp # ./IpcTestClient &
D/IpcTestService(18751): getMemory() is called.
D/IpcTestClient(18770): The ashmem content is:Hello Ashmem
D/IpcTestService(18751): getFileDescriptor is called.
D/IpcTestService(18751): dumpFile is called.
D/IpcTestService(18751): dumpFile: current offset is 13.
D/IpcTestService(18751): dumpFile: file size is 13.
D/IpcTestService(18751): dumpFile:Hello World!
D/IpcTestService(18751): setInt:10
D/IpcTestService(18751): getInt is called
D/IpcTestClient(18770): Got int value:10
D/IpcTestService(18751): setString:Hello World!
D/IpcTestService(18751): getString is called.
D/IpcTestClient(18770): Got string:Hello World!
我们接着试一下dumpsys工具的使用,dumpsys工具可以调用到服务端的dump方法,可以在这个方法中加入很多的状态信息,方便调试服务端。
shell@android:/tmp # dumpsys android.ipctest
log输出如下:
mIntVal = 10
mStr = Hello World!
D/IpcTestService(18751): dump() is called.
最后我们验证binder的death notification功能,我们把服务端kill掉,看客户端会不会有通知。
shell@android:/tmp # kill -9 18751
可以看到log输出如下:
D/IpcTestClient(18770): The android.ipctest server is dead!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4736次
排名:千里之外
(1)(1)(1)(4)(1)

我要回帖

更多关于 service层怎么写 的文章

 

随机推荐