NATIVE层定制系统服务,APP层使用该服务
版权说明
此文乃业余时研究过程与结果的记录,任何个人或组织均不允许转载或牟利。
其他说明
-
本文不讨论Android Binder架构。
-
本文不讨论Android编译。
-
本文不讨论SELinux。
-
本文不讨论GNU MAKE。
-
Android系统服务不等价于Binder服务,而Binder服务也不完全等价于Binder对象。
研究环境准备
操作系统
- Ubuntu 20
- Ubuntu 18
上述免费操作系统任选其一。
AOSP 源码
从清华或中科大源下载AOSP压缩包,解压后repo sync即可。
中科大镜像网站:https://mirrors.ustc.edu.cn/help/aosp.html
中科大AOSP压缩包:https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/
APP IDE
- Android Studio
- IDEA 社区版
上述免费软件任选其一。
ADB
可将Android Studio自带的adb工具路径添加到环境变量PATH:
# ~/.bashrc
export PATH=$PATH:~/Android/Sdk/platform-tools
或直接安装:
sudo apt install adb
Emulator
可将Android Studio自带的emulator工具路径添加到环境变量PATH:
# ~/.bashrc
export PATH=$PATH:~/Android/Sdk/emulator
制作AVD
- 不采用
aosp_arm64-eng
的原因是需要刷机,需要实体设备,且反复刷机也浪费时间。 - 不采用
aosp_cf_x86_64_phone-userdebug
以构建 Cuttlefish 虚拟 Android 设备的原因是acloud
构建莫名失败,而国内又无法访问android-building 网上论坛。
AVD的优点就是AVD系统映像编译完成后就可在虚拟设备立即运行以便快速检查修改结果。
编译部分的Shell命令如下:
source ./build/envsetup.sh
lunch sdk_phone_x86_64
make -j8
运行编译后的系统映像的Shell命令:
emulator
模拟器运行图
sdk_phone_x64.png参考
https://source.android.google.cn/setup/create/avd#building_avd_images
服务设计
名称设计
可执行目标文件名称owner
。
服务名称设定为native_owner_service
,Binder能力模型名称设定为com.fmy.remote.IAbilityModel
。
SELinux
类型强制文件名称owner
。
Android 初始化脚本名称owner
。
能力设计
-
获取设备主人名称
- 无需传入参数。
- 返回字符串,数据类型
android::String16
。
-
关闭服务
-
描述:创建一个新的posix线程,该线程先休眠6s,再终止整个进程。
-
无需参数。
-
无返回数据。
-
启动设计
- 启动时机:
data
分区准备完毕后。 - 启动次数:不可重复启动
- 启动标签:
u:object_r:owner:s0
service owner /system/bin/owner
oneshot
seclabel u:object_r:owner:s0
on post-fs-data
start owner
SELinux设计
域
名称owner
,关联类型coredomain
与 mlstrustedsubject
。
上下文u:object_r:owner:s0
对象
可执行目标文件owner
的上下文u:object_r:owner_exec:s0
。
type owner, coredomain, mlstrustedsubject;
permissive owner;
#typeattribute owner coredomain;
#typeattribute owner mlstrustedsubject;
type owner_exec, exec_type, system_file_type, file_type;
init_daemon_domain(owner)
文件设计
-
src
目录存放源文件-
main.cpp
存放主逻辑,负责将服务添加到系统服务器,并等待客户端调用或关闭服务 -
binderService
目录存放服务定义与实现-
AbilityModel.h
与AbilityModel.cpp
存放服务定义 -
LocalAbilityModelImpl.h
与LocalAbilityModelImpl.cpp
存放服务实现
-
-
编码环境设计
采用Visual Studio Code
,安装C/C++
扩展,添加include
搜索路径:
${workspaceFolder}/**
~/aosp/system/logging/liblog/include
~/aosp/frameworks/native/include/
~/aosp/system/core/libutils/include/
~/aosp/system/libbase/include/
~/aosp/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/x86_64-linux/include/c++/4.8.3/bits/
~/aosp/system/core/libcutils/include/
编译设计
在generic_system.mk
中引入可执行目标模块的编译:
# Applications
PRODUCT_PACKAGES += \
owner \
c++标准由编译系统决定。
Android.bp
cc_binary {
name : "owner",
srcs : [
"src/binderService/LocalAbilityModelImpl.cpp",
"src/binderService/AbilityModel.cpp",
"src/main.cpp",
],
init_rc : ["owner.rc"],
cppflags : ["-O1", "-Werror", "-Wall", "-Wno-unused-parameter"],
shared_libs : ["liblog", "libbinder", "libutils"],
}
编码设计
- 服务定义与实现在名称空间
np_owner
中完成。 - Log利用Android log库实现
- 利用Looper无限期等待Binder通信过程调用
实现
owner/src/main.cpp
#define LOG_TAG "OWNER_NATIVE"
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <log/log.h>
#include <unistd.h>
#include <utils/Looper.h>
#include <binder/IPCThreadState.h>
#include <cstdlib>
#include "binderService/LocalAbilityModelImpl.h"
int main(int argc, char const *argv[]) {
using android::IBinder;
using android::interface_cast;
using android::IServiceManager;
using android::sp;
using android::status_t;
using android::String16;
using android::Looper;
using android::ProcessState;
/**
* 1. Obtain service manager
*/
sp<IServiceManager> smp = android::defaultServiceManager();
if (smp == nullptr) {
ALOGE("service manager pointer is nullptr");
exit(EXIT_FAILURE);
}
/**
* 2. Set up the binder
*/
sp<ProcessState> ps(ProcessState::self());
ps->setThreadPoolMaxThreadCount(2);
ps->startThreadPool();
/**
* 3. Add binder service
* Checking method:
* adb shell service check native_owner_service
* Service native_owner_service: found
*/
if (smp->addService(String16("native_owner_service"), new np_owner::LocalAbilityModelImpl()) != android::OK)
{
ALOGE("Failed add service");
exit(EXIT_FAILURE);
}
/**
* 4. Wait exit
*/
// Set up the looper
sp<Looper> looper(Looper::prepare(0 /* opts */));
// Loop forever -- the reports run on this thread in a handler, and the
// binder calls remain responsive in their pool of one thread.
while (true) {
looper->pollAll(-1 /* timeoutMillis */);
}
return 0;
}
owner/src/binderService/AbilityModel.h
#ifndef ABILITY_MODEL_H_
#define ABILITY_MODEL_H_
#include <binder/IBinder.h>
#include <binder/IInterface.h>
namespace np_owner {
using android::IBinder;
using android::IInterface;
using android::String16;
const String16 OWNER("unknow owner");
/**
* 类名必须由 I 开头,后面是能力模型名称
*/
class IAbilityModel : public IInterface {
DECLARE_META_INTERFACE(AbilityModel)
virtual String16 getDeviceOwner();
virtual void shutdown();
enum {
GET_DEVICE_OWNER = IBinder::FIRST_CALL_TRANSACTION,
SHUTDOWN = IBinder::FIRST_CALL_TRANSACTION + 1
};
};
} // namespace np_owner
#endif
owner/src/binderService/AbilityModel.cpp
#include "AbilityModel.h"
#include <log/log.h>
namespace np_owner
{
const String16 IAbilityModel::descriptor("com.fmy.remote.IAbilityModel");
IAbilityModel::IAbilityModel(){
}
IAbilityModel::~IAbilityModel(){
}
const String16& IAbilityModel::getInterfaceDescriptor() const {
return descriptor;
}
String16 IAbilityModel::getDeviceOwner() {
return OWNER;
}
void IAbilityModel::shutdown() {
ALOGD("Prototype can not shutdown!");
}
} // namespace np_owner
owner/src/binderService/LocalAbilityModelImpl.h
#ifndef LOCAL_ABILITY_MODEL_IMPL_H
#define LOCAL_ABILITY_MODEL_IMPL_H
#include "AbilityModel.h"
namespace np_owner {
using android::BnInterface;
using android::Parcel;
using android::sp;
using android::status_t;
using android::String16;
class LocalAbilityModelImpl : public BnInterface<IAbilityModel> {
private:
/* data */
public:
LocalAbilityModelImpl(/* args */);
~LocalAbilityModelImpl();
virtual String16 getDeviceOwner();
virtual void shutdown();
protected:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0);
};
} // namespace np_owner
#endif
owner/src/binderService/LocalAbilityModelImpl.cpp
#include "LocalAbilityModelImpl.h"
#include <log/log.h>
#include <binder/Parcel.h>
#include <stdlib.h>
#include <pthread.h>
namespace np_owner {
void * shutdownTask(void *);
void * shutdownTask(void *) {
if (sleep(6) != 0)
{
ALOGE("LocalAbilityModelImpl: shutdownTask sleep error ");
return nullptr;
}
exit(EXIT_SUCCESS);
}
status_t LocalAbilityModelImpl::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
switch (code) {
case GET_DEVICE_OWNER:
ALOGD("LocalAbilityModelImpl::onTransact:GET_DEVICE_OWNER");
/**
* Set responsive status
*/
if (reply->writeInt32(android::OK) != android::OK)
{
ALOGE("LocalAbilityModelImpl::onTransact:writeInt32 error");
return android::UNKNOWN_ERROR;
}
if (reply->writeString16(LocalAbilityModelImpl::getDeviceOwner()) != android::OK)
{
ALOGE("LocalAbilityModelImpl::onTransact:writeCString error");
return android::UNKNOWN_ERROR;
}
return android::OK;
case SHUTDOWN:
ALOGD("LocalAbilityModelImpl::onTransact:SHUTDOWN");
/**
* Set responsive status
*/
if (reply->writeInt32(android::OK) != android::OK)
{
ALOGE("LocalAbilityModelImpl::onTransact:writeInt32 error");
return android::UNKNOWN_ERROR;
}
shutdown();
return android::OK;
default:
return android::UNKNOWN_ERROR;
}
}
String16 LocalAbilityModelImpl::getDeviceOwner(){
ALOGD("LocalAbilityModelImpl::getDeviceOwner");
return String16("fmy");
}
void LocalAbilityModelImpl::shutdown(){
ALOGD("LocalAbilityModelImpl::shutdown");
pthread_t pid;
if (pthread_create(&pid, NULL, shutdownTask, NULL) != 0)
{
ALOGE("LocalAbilityModelImpl::shutdown:Failed create pthread");
return;
}
}
LocalAbilityModelImpl::LocalAbilityModelImpl(/* args */) {}
LocalAbilityModelImpl::~LocalAbilityModelImpl() {}
} // namespace np_owner
检查
进程运行状态
adb shell ps -eZ | grep owner
u:object_r:owner:s0 root 314 1 10797932 4024 do_epoll_wait 0 S owner
可以看到进程正在执行轮询等待过程。
进程的资源占用情况:
adb shell top -p 314
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Mem: 2013628K total, 1792460K used, 221168K free, 13616K buffers
Swap: 1510216K total, 256K used, 1509960K free, 1039512K cached
200%cpu 0%user 0%nice 0%sys 200%idle 0%iow 0%irq 0%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
314 root 20 0 10G 3.9M 3.2M S 0.0 0.1 0:00.00 owner
可以看到:无Binder IPC
时,<font color='green'>主线程处于休眠状态,CPU资源占用为0</font>。
服务添加到系统服务器
adb shell service check native_owner_service
Service native_owner_service: found
客户端设计
先利用Android Studio
以三方应用的形式编写代码,再将必要的源文件拷贝到~/aosp/packages/apps/FMY_NativeBinderRemote/
,从而编译出系统APK
。
用户通过点击名为IPC
的按钮来触发Binder IPC
:
- 从服务管理器获取到
Binder Service
对象; - 将
Binder Service
对象转化为Binder Proxy
对象; - 利用
Binder Proxy
对象执行Binder IPC
。 - 通过LOG展示设备主人名称
- 关闭native服务
编译设计
在generic_system.mk
中引入可执行目标模块的编译:
# Applications
PRODUCT_PACKAGES += \
FMY_NativeBinderRemote \
Android.bp
android_app {
name: "FMY_NativeBinderRemote",
srcs: ["src/**/*.java", "src/**/I*.aidl"],
platform_apis: true,
static_libs: [
"androidx.appcompat_appcompat",
"androidx.legacy_legacy-support-core-ui",
"androidx.legacy_legacy-support-v13",
"androidx.legacy_legacy-support-v4",
"com.google.android.material_material",
"guava",
],
}
实现
IAbilityModel.aidl
// IAbilityModel.aidl
package com.fmy.remote;
// Declare any non-default types here with import statements
interface IAbilityModel {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
String getDeviceOwner();
void shutdown();
}
MainActivity
package com.fmy.remote;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.native_ipc_btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IBinder binder = null;
try {
binder = ServiceManager.getServiceOrThrow("native_owner_service");
} catch (ServiceManager.ServiceNotFoundException e) {
Log.e(TAG, "onClick: ", e);
}
if (binder != null) {
IAbilityModel proxy = IAbilityModel.Stub.asInterface(binder);
try {
Log.d(TAG, "onClick: device owner is " + proxy.getDeviceOwner());
} catch (RemoteException e) {
Log.e(TAG, "onClick: ", e);
}
Log.d(TAG, "onClick: attempt to shutdown native binder service");
try {
proxy.shutdown();
} catch (RemoteException e) {
Log.e(TAG, "onClick: ", e);
}
}
}
});
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/native_ipc_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ipc"/>
</LinearLayout>
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fmy.remote">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NativeBinderRemote">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
检查
解析为系统应用
adb shell pm list packages -f | grep FMY_NativeBinderRemote
package:/system/app/FMY_NativeBinderRemote/FMY_NativeBinderRemote.apk=com.fmy.remote
IPC
2021-07-04 19:13:47.627 1815-1815/com.fmy.remote D/MainActivity: onClick: device owner is fmy
2021-07-04 19:13:47.627 1815-1815/com.fmy.remote D/MainActivity: onClick: attempt to shutdown native binder service
网友评论