Ahao's Technical Blog Ahao's Technical Blog
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

阿豪讲Framework

不积跬步无以至千里
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础篇

  • 玩转AOSP篇

  • 学穿Binder篇

    • 000.Binder 专题导学 —— 如何深入掌握 Binder
    • 001.学习 Binder 的预备知识
    • 002.Binder 基本原理
    • 003.Binder 程序示例之 C 语言篇
    • 004.Binder 服务注册过程情景分析之 C 语言篇
    • 005.Binder 服务获取与使用过程情景分析之C语言篇
    • 006.Android Binder 驱动框架设计与分析
    • 007.Binder 驱动情景分析之 ServiceManager 启动过程
    • 008.Binder 驱动情景分析之服务注册过程
    • 009.Binder 驱动情景分析之服务获取与使用过程
    • 010.Binder 程序示例之 C++ 篇
    • 011.Binder C++ 程序分析之主要类解析
    • 012.Binder 服务注册过程情景分析之 C++ 篇
    • 013.Binder 服务获取与使用过程情景分析之C++篇
    • 014.Binder 程序示例之 aidl-cpp 篇
    • 015.添加 Android Native 系统服务
    • 016.添加 Native 系统服务回调
    • 017.Binder 程序示例之 Java 篇
    • 018.Binder Java 层初始化
    • 019.Binder Java 层服务注册过程分析
    • 020.Binder Java 层服务获取与使用过程分析
    • 021.添加 Java 系统服务
    • 022.Android Java 系统服务框架与第三方 App 使用自定义 Java 系统服务
    • 023.添加 Java 系统服务回调
    • 024.AIDL 数据类型详解之 Java 篇
    • 025.AIDL 数据类型详解之 C++ 篇
    • 026.Java 调用 Native 服务
    • 027.Native 调用 Java Binder 服务
      • 参考资料
    • 028.AIDL 关键字 in out inout oneway 解析
    • 029.Binder 驱动 Debug 入门指南
    • 030.Binder 匿名服务源码分析
    • 031.Binder 中的 Parcel 数据结构分析(C++)
    • 032.Binder 中的 Parcel 数据结构分析(Java)
    • 033.Binder 多线程情景分析
    • 034.Binder 线程池溢出问题
    • 035.Binder 代理对象泄露问题分析
    • 036.Binder 死亡通知情景分析
    • 037.Binder 异常处理机制
    • 038.Binder 系统源码演进
    • 039.Binder 面试题汇总
    • 补充——LocalService
  • 基础组件篇

  • 系统启动过程分析

  • Hal开发入门与实践

  • 显示系统

  • Framework
  • 学穿Binder篇
阿豪
2023-08-08
目录

027.Native 调用 Java Binder 服务

本文介绍一下怎么通过 Native 代码使用 Java Binder Service。

接下来我们演示使用 Cpp 代码访问 Binder 程序示例之 java 篇 (opens new window) 编写的 Java Binder Service。

在 device/jelly/rice14 目录下创建如下的文件与文件夹:

NativeCallJavaServiceSimple/
├── Android.bp
└── CppClient.cpp
1
2
3

其中 CppClient.cpp 内容如下: ····················

#define LOG_TAG "aidl_cpp"
#include <log/log.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <android/log.h>
#include <errno.h>
#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <private/binder/binder_module.h>
#include <string.h>
#include <cutils/properties.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <stdarg.h>
#include <stdlib.h>

using namespace android;
 
 
int  main(void)
{   

    sp<IServiceManager> sm = defaultServiceManager();
	sp<IBinder> ibinder =  sm->getService(String16("hello")); 

	Parcel data,reply;

	if(ibinder != NULL)
	{
    	static String16 descriptor = String16("com.yuandaima.IHelloService");
        data.writeInterfaceToken(descriptor);
		//data.writeString16(String16("client from Native"));
		ibinder->transact(IBinder::FIRST_CALL_TRANSACTION + 0, data, &reply, 0);
		int result = reply.readInt32();
		ALOGI("transact result : %d\n", result);
	    return 0;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

主要分为 4 步执行:

  • 获得 Hello 服务,与 Java 程序区别是这里不做转换了,直接使用 IBinder(实际类型是 BpBinder)
  • 构建好两个 Parcel 结构,data reply
  • 通过 BpBinder 的 transact 方法发起远程调用
  • 处理返回的 reply

接着我们在系统源码下执行:

source build/envsetup.sh
lunch 
make installclean
1
2
3

然后终端进入到 device/jelly/rice14/NativeCallJavaServiceSimple,编译我们的源码:

mm
1

接着我们进入 device/jelly/rice14/BinderJavaDemo 目录下,编译 C++ 服务端:

mm
1

接着回到系统源码目录下,push 源码产物到 Android 模拟器上:

adb push out/target/product/rice14/system/bin/CppClient /data/local/tmp
adb push out/target/product/rice14/system/framework/BinderServer.jar /data/local/tmp
1
2

接着进入 Andorid shell,执行程序:

adb shell
cd /data/local/tmp
# 执行服务端
export CLASSPATH=/data/local/tmp/BinderServer.jar
app_process /data/local/tmp com.yuandaima.Server &
# 执行客户端
./CppClient
1
2
3
4
5
6
7

最后查看log:

logcat | grep "aidl_cpp" 
1

从 log 中看出 Client 收到了回复的数据 0,证明我们的调用成功了。

以上介绍的方法算是一种简易的零时解决方案,更为完整的做法是利用 aidl 生成的文件来“衔接” Java 层和 C++ 层:

首先在 device/jelly/rice14 目录下创建如下的文件与文件夹:

NativeCallJavaService/
├── Android.bp
└── CppClient.cpp
1
2
3

我们把 device/jelly/rice14/BinderJavaDemo/com/yuandaima/IHelloService.aidl 文件拷贝到 device/jelly/rice14/NativeCallJavaService/com/yuandaima,接着我们在终端中进入 device/jelly/rice14/NativeCallJavaService 目录,接着使用 aidl 生成代码:

aidl-cpp com/yuandaima/IHelloService.aidl ./ ./IHelloService.cpp
1

然后修改源码:

package com.yuandaima;

import android.util.Log;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.os.IBinder;
import android.os.Parcel;

public class JavaClient {

    public static final String TAG = "JavaClient";

    public static void main(String[] args) {
        //获取Native Binder Service的代理
        IBinder binder = ServiceManager.getService("IHello");
        String DESCRIPTOR = "com.yuandaima.IHello";

        IHello svr = IHello.Stub.asInterface(binder);

        try {
	        svr.hello();
	        Log.i(TAG, "call hello");
        } catch (Exception e) {

        }
           
        try {
	        int cnt = svr.sum(3, 4);
	        Log.i(TAG, "call sum(3, 4)");
        } catch (Exception e) {
    
        }
    
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

然后修改编译文件 Android.bp:

cc_binary {
    name: "CppClient",
    srcs: ["CppClient.cpp", "IHelloService.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libutils",
        "libbinder",
    ],
}

1
2
3
4
5
6
7
8
9
10
11

接着在 device/jelly/rice14/NativeCallJavaService 目录下单编模块:

mm
1

最后我们来测试一下:

adb push out/target/product/rice14/system/bin/CppClient /data/local/tmp

# 进入 Android shell 环境
adb shell
cd /data/local/tmp
export CLASSPATH=/data/local/tmp/BinderServer.jar
app_process /data/local/tmp com.yuandaima.Server &
./CppClient
1
2
3
4
5
6
7
8

接着查看 log:

logcat | grep HelloService
08-07 14:34:54.086  1636  1636 I SystemServer: JavaHelloService
08-07 14:34:54.089  1636  1636 D SystemServerTiming: JavaHelloService took to complete: 3ms
08-08 18:10:42.498  6029  6039 I HelloService: sayhello : cnt = 1
08-08 18:10:42.499  6029  6039 I HelloService: sayhello_to nihao : cnt = 1
1
2
3
4
5

从 Log 可以看出我们的 Native 客户端已经成功访问到 Java Binder 服务了。

# 参考资料

  • AIDL interface between Java and C++ (opens new window)
026.Java 调用 Native 服务
028.AIDL 关键字 in out inout oneway 解析

← 026.Java 调用 Native 服务 028.AIDL 关键字 in out inout oneway 解析→

最近更新
01
如何调试 SurfaceFlinger
10-05
02
SurfaceFlinger 概述
10-05
03
HWC 接口分析
10-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 AHao Framework | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式