Android系统中如何在Native层调用java实现的系统服务
继<在Android中利用抽象类对外提供系统接口>后,出现了个新需求,就是想在Native层代码中也能使用之前定制服务(用java实现的)中已经实现好的各种功能和机制。
实现原理
如上图,右边的
java服务层
部分已在<在Android中利用抽象类对外提供系统接口>中实现了,现在需要实现左边的BpCustomManagerService
, 以供其它Native程序调用:

实现代码
ICustomManagerService.h
cpp
#pragma once
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <optional>
#ifdef __ANDROID_VNDK__
#error "This header is not visible to vendors"
#endif
namespace android {
// ----------------------------------------------------------------------
class ICustomManagerService : public IInterface
{
public:
DECLARE_META_INTERFACE(CustomManagerService)
virtual String16 getVersion() = 0;
enum {
TRANSACTION_getVersion = 1,
};
};
其中TRANSACTION_getVersion
需要在系统编译输出目录out
下找到文件ICustomManagerService$Stub.class
, 然后用java反编译工具JD-GUI打开, 查看TRANSACTION_getVersion
的值:
java
public abstract class Stub extends Binder implements ICustomManagerService {
static final int TRANSACTION_getVersion = 1;
}
在binder通信中,通过类似于TRANSACTION_getVersion
的硬编码值来确定调用的哪个接口。这个值与接口在aidl文件中的顺序有关。 如果ICustomManagerService.aidl的定义如下,
java
interface ICustomManager {
String getVersion();
String xyz();
}
则ICustomManagerService$Stub.class
就会有以下2个接口编号:
java
public abstract class Stub extends Binder implements ICustomManagerService {
static final int TRANSACTION_getVersion = 1;
static final int TRANSACTION_xyz = 2;
}
当ICustomManagerService.aidl里接口的顺序发生变化后,需要在ICustomManagerService.h中同步更改。
ICustomManagerService.cpp
cpp
//#define LOG_NDEBUG 0
#define LOG_TAG "CustomManagerService"
#include <binder/ICustomManagerService.h>
#include <android-base/logging.h>
#include <binder/Parcel.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <optional>
namespace android {
// ----------------------------------------------------------------------
class BpCustomManagerService : public BpInterface<ICustomManagerService>
{
public:
explicit BpCustomManagerService(const sp<IBinder>& impl)
: BpInterface<ICustomManagerService>(impl)
{
}
virtual String16 getVersion() {
Parcel data, reply;
data.writeInterfaceToken(ICustomManagerService::getInterfaceDescriptor());
remote()->transact(TRANSACTION_getVersion, data, &reply);
if (reply.readExceptionCode() != 0) return String16("");
return reply.readString16();
}
};
IMPLEMENT_META_INTERFACE(CustomManagerService, "com.android.internal.xyz.ICustomManagerService")
} // namespace android
ICustomManagerService.cpp
为BpCustomManagerService的具体实现,在函数getVersion()
中往binder传入com.android.internal.xyz.ICustomManagerService
表示要调用的远程服务名称,传入TRANSACTION_getVersion
表示要调用远程服务接口。返回的是一个Parcel类型的数据reply, reply里有服务端给的ExceptionCode和version值。
在ICustomManagerService$Stub.class
里可看到服务端收到TRANSACTION_getVersion
命令号后的处理:
java
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case 1:
str16 = getVersion();
reply.writeNoException();
reply.writeString(str16);
return true;
......
}
}
CustomManager.h
cpp
#pragma once
#include <binder/ICustomManagerService.h>
#include <utils/threads.h>
#include <optional>
#ifdef __ANDROID_VNDK__
#error "This header is not visible to vendors"
#endif
// ---------------------------------------------------------------------------
namespace android {
class CustomManager
{
public:
CustomManager();
String16 getVersion();
private:
Mutex mLock;
sp<ICustomManagerService> mService;
sp<ICustomManagerService> getService();
};
} // namespace android
CustomManager.cpp
cpp
#define LOG_NDEBUG 0
#include <mutex>
#include <binder/CustomManager.h>
#include <binder/Binder.h>
#include <binder/IServiceManager.h>
#include <utils/SystemClock.h>
#include <sys/types.h>
#include <private/android_filesystem_config.h>
#include <fcntl.h>
#include <termios.h>
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "CustomManager"
namespace android {
CustomManager::CustomManager()
{
}
sp<ICustomManager> CustomManager::getService()
{
static String16 _cmser("CustomManagerService");
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
sp<ICustomManagerService> service = mService;
while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(_cmser);
if (binder == nullptr) {
if (startTime == 0) {
startTime = uptimeMillis();
ALOGI("Waiting for CustomManagerService");
} else if ((uptimeMillis()-startTime) > 10000) {
ALOGW("Waiting too long for CustomManagerService, giving up");
service = nullptr;
break;
}
sleep(1);
} else {
service = interface_cast<ICustomManagerService>(binder);
mService = service;
}
}
return service;
}
String16 CustomManager::getVersion()
{
sp<ICustomManagerService> service = getService();
if (service == nullptr) {
return String16("");
}
return service->getVersion();
}
}
将ICustomManagerService.h, ICustomManagerService.cpp, CustomManager.h, CustomManager.cpp编译成libcustommanager.so:
makefile
cc_library {
name: "libcustommanager",
double_loadable: true,
target: {
android: {
compile_multilib: "both",
},
},
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
srcs: [
"CustomManager.cpp",
"ICustomManagerService.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
"libutils",
"libbinder",
"libcutils",
"liblog",
],
}
还有个地方需要添加个白名单:
frameworks/native/libs/binder/include/binder/IInterface.h
diff
constexpr const char* const kManualInterfaces[] = {
"IAAudioService",
"VtsFuzzer",
+ "com.android.internal.xyz.ICustomManagerService",
nullptr,
};
其中,CustomManager.h为对外提供的头文件。
使用范例
在准备使用CustomManager的程序的Android.bp加入:
ini
shared_libs: [
libcustommanager
]
或Android.mk里加入
makefile
LOCAL_SHARED_LIBRARIES += libcustommanager
代码里:
cpp
#include <binder/CustomManager.h>
#include <binder/IServiceManager.h>
const char* string16ToChar(const android::String16& str16) {
// 创建 String8 对象进行自动转换(UTF-16 → UTF-8)
android::String8 str8(str16);
// 返回 UTF-8 字符串(生命周期与 str8 对象绑定)
return str8.string();
}
void test() {
android::CustomManager cm;
cm.getVersion();
ALOGD("%s: getVersion = %s\n", __func__, string16ToChar(cm.getVersion()));
}