简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:在android源码中手动生成aidl对应的java/cpp/ndk/rust语言的binder服务。
2.生成aidl对应的java服务
<1>.编写ITest.aidl
# mkdir -p aidl/com/test
# cd aidl/com/test
# emacs ITest.aidl
package aidl.com.test;
interface ITest {
void get(int arg);
}
注意:路径名(aidl/com/test)和包名(aidl.com.test)要一样,唯一不同是"/“和”."区分,否则编译报错。
<2>.生成ITest.aidl对应ITest.java服务文件
不指定参数,默认生成java服务文件
# aidl aidl/com/test/ITest.aidl
或者使用如下命令
# 这3条命令和上边一样,只是指定了参数
# aidl -o ./java --lang=java aidl/com/test/ITest.aidl
# tree java
java
└── aidl
└── com
└── test
└── ITest.java
Or
# aidl -o ./java aidl/com/test/ITest.aidl
Or
# aidl -I ./aidl/ -o ./java aidl/com/test/ITest.aidl
注意:
-o:表示输出路径,为当前目录的java文件,它会创建一个java目录,然后在java目录中存放生成的ITest.java文件。
-I:表示依赖其他的.aidl文件。
--lang:表示支持生成的语言有哪些,如:java、cpp、ndk、rust,目前到Android12,只支持这四种语言。
# ls -al aidl/com/test/ITest.java
ITest.java
/*
* This file is auto-generated. DO NOT MODIFY.
*/
package aidl.com.test;
public interface ITest extends android.os.IInterface
{
/** Default implementation for ITest. */
public static class Default implements aidl.com.test.ITest
{
@Override public void get(int arg) throws android.os.RemoteException
{
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements aidl.com.test.ITest
{
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an aidl.com.test.ITest interface,
* generating a proxy if needed.
*/
public static aidl.com.test.ITest asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof aidl.com.test.ITest))) {
return ((aidl.com.test.ITest)iin);
}
return new aidl.com.test.ITest.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
}
switch (code)
{
case TRANSACTION_get:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
this.get(_arg0);
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements aidl.com.test.ITest
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void get(int arg) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(arg);
boolean _status = mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);
if (!_status) {
if (getDefaultImpl() != null) {
getDefaultImpl().get(arg);
return;
}
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public static aidl.com.test.ITest sDefaultImpl;
}
static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
public static boolean setDefaultImpl(aidl.com.test.ITest impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static aidl.com.test.ITest getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public static final java.lang.String DESCRIPTOR = "aidl.com.test.ITest";
public void get(int arg) throws android.os.RemoteException;
}
3.生成aidl对应的cpp服务
还是以ITest.aidl为例子,生成对应的cpp的binder服务
# aidl -h ./aidl_cpp/ -o ./aidl_cpp --lang=cpp aidl/com/test/ITest.aidl
Or
# aidl -I ./aidl_dep -h ./aidl_cpp/ -o ./aidl_cpp --lang=cpp aidl/com/test/ITest.aidl
注意:
--lang=cpp:表示生成Android源码下编译的C++接口文件。
-o:表示.cpp文件输出路径
-h:表示.h文件输出的路径
-I:表示依赖其他*.aidl文件
# tree aidl_cpp
aidl_cpp
└── aidl
└── com
└── test
├── BnTest.h
├── BpTest.h
├── ITest.cpp
└── ITest.h
注意:
Interface头文件:ITest.h
Bp头文件:BpTest.h
Bn头文件:BnTest.h
源码文件:ITest.cpp
4.生成aidl对应的ndk服务
还是以ITest.aidl为例子,生成对应的ndk的binder服务
# aidl -h ./aidl_ndk -o ./aidl_ndk --lang=ndk aidl/com/test/ITest.aidl
# tree aidl_ndk
aidl_ndk
└── aidl
├── aidl
│ └── com
│ └── test
│ ├── BnTest.h
│ ├── BpTest.h
│ └── ITest.h
└── com
└── test
└── ITest.cpp
5.生成aidl对应的rust服务(因为Android已经支持Rust语言开发)
Rust是一个跨平台开发语言,支持Android,iOS,桌面,Web和后端的开发。
还是以ITest.aidl为例子,生成对应的Rust的binder服务
# aidl -o ./aidl_rust --lang=rust aidl/com/test/ITest.aidl
# tree aidl_rust
aidl_rust/
└── aidl
└── com
└── test
└── ITest.rs
6.在Android.bp中自动生成aidl对应的java/cpp/ndk/rust服务
Android.bp
aidl_interface {
name: "Test",
srcs: [ "aidl/com/test/*.aidl", ],
unstable: true,
backend: {
java: {
enabled: false,
platform_apis: true,
},
cpp: {
enabled: false,
},
ndk: {
enabled: true,
vndk: {
enabled: false,
},
},
//Android12才支持编译aidl对应Rust服务
rust: {
enabled: true,
},
},
}
注意:编译aidl对应哪个语言支持,将enabled设置为:true,如果不想生成则设置为:false。