3/14/2018
Ref:https://wenku.baidu.com/view/5846922a647d27284b7351d5.html
起点:
- Android 6.0源代码。
- 不做任何改动时,可以顺利编译通过。
- 编译得到的img文件,可以顺利地刷写到安卓中,测试正常。
第一步:服务实现
此步将新建native service并编译为so库
在源码目录中,新建一个目录frameworks/base/addservice/libaddservice
,编写了3个文件,分别如下:
- AddService.h
- AddService.cpp
- Android.mk
文件1:AddService.h
四点:
- 实例化 instantiate
- 构造函数AddService
- 析构函数~AddService
- onTransact
//AddService.h
#ifndef ANDROID_GUILH_ADD_SERVICE_H
#define ANDROID_GUILH_ADD_SERVICE_H
#include
#include
#include
#include
namespace android {
class AddService:public BBinder {
mutable Mutex mLock;
int32_t mNextConnId;
public:
static int instantiate();
AddService();
virtual ~AddService();
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
};
}; //namespace
#endif
文件2:AddService.cpp
把这四点具体实现:
- 实例化 instantiate
- 构造函数AddService
- 析构函数~AddService
- onTransact
//AddService.cpp
#include "AddService.h"
#include
#include
namespace android {
static struct sigaction oldact;
static pthread_key_t sigbuskey;
int AddService::instantiate(){
ALOGE("AddService instantiate");
int r=defaultServiceManager()->addService(String16("guilh.add"), new AddService());
//上面这一行是把AddSerice这个服务添加到Binder Driver中,服务取名为 guilh.add
ALOGE("AddService r = %d\n", r);
return r;
}
AddService::AddService() { //构造函数
ALOGV("AddService created");
mNextConnId =1 ;
pthread_key_create(&sigbuskey, NULL);
}
AddService::~AddService() { //析构函数
pthread_key_delete(sigbuskey);
ALOGV("AddService destroyed");
}
//下面这个onTransact是服务具体的本地实现,功能实现都应该放在这里面,通过传入执行代码(code)的不同来执行不同的操作,上层映射为不同的API
status_t AddService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
switch(code) {//根据code的不同执行不同的操作
case 0: {
pid_t pid=data.readInt32();
int num = data.readInt32();
num = num + 1000;
reply-> writeInt32(num);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; //namespace
文件3:Android.mk
目的:指定源cpp文件;列出共享库;指定输出的so库文件名为
libAdd.so
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
AddService.cpp
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libandroid_runtime
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libAdd
include $(BUILD_SHARED_LIBRARY) #这一行表示编译为动态库
编译
先要退回Android源码根目录,执行以下命令来设置好编译环境。
source build/envsetup.sh
lunch 15 //(对应15. full_espresso8890-eng, 按需更改)
然后回到刚才的目录,并执行mm:
cd frameworks/base/addservice/libaddservice
mm
mm -B //如果已经编译过,可以用此命令覆盖旧的文件
mma -B -j50 //编译当前文件夹,以及所有依赖(50为线程个数,按需更改)
编译成功。生成的so文件位于:
out/target/product/espresso8890/system/lib/libAdd.so
第二步:服务进程实现
目的:把服务添加到Binder闭合循环进程(Binder Driver)中
在源码中新建一个目录:
frameworks/base/addservice/addserver
编写2个文件:
- addserver.cpp
- Android.mk
文件1:addserver.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "../libaddservice/AddService.h"
//#include
using namespace android;
int main(int argc, char** argv) {
printf("ServiceManager Started!!!\n");
sp proc(ProcessState::self());
sp sm= defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
printf("ServiceManager: %p\n", sm.get());
AddService::instantiate();
printf("instatiated! \n");
ProcessState::self()->startThreadPool();
//下面这一行是把服务添加到Binder闭合循环进程中
IPCThreadState::self()->joinThreadPool();
}
以上为底层服务的标准操作。
文件2:Android.mk
- 指定cpp文件
- 指定要使用的共享库
- 定义生成的程序的名称:addserver (倒数第2行)
- 编译为可执行文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -L$(SYSROOT)/lib -llog
LOCAL_SRC_FILES := \
addserver.cpp
LOCAL_SHARED_LIBRARIES := \
libAdd \
libutils \
libbinder
LOCAL_MODULE := addserver
include $(BUILD_EXECUTABLE)
编译
在当前目录中执行:
mm
编译成功,得到的可执行文件addserver
位于:
out/target/product/espresso8890/system/bin/addserver
第三步:真机测试
把以上得到的so库
和可执行文件
手工复制到安卓设备上进行测试。
- 使用
adb push
命令,把so库文件拷贝到/system/lib64
中(如果是32位so文件则放在/system/lib
中) - 使用
adb push
命令,把可执行文件addserver
拷贝到/system/bin
下 - 然后手动执行此命令。
3.1 如果执行命令时,使用的是cd /system/bin
然后./addserver
,在用top
检查时,会看到./addserver
这个进程。
3.2 如果执行命令时,使用的是/system/bin/addserver
,在用top
检查时,会看到/system/bin/addserver
这个进程。
>>>>>>>>>>>>>>>> 以下为可选步骤 <<<<<<<<<<<<<<<<
第四步:修改init.rc
文件让服务开机启动
在源码的android/system/core/rootdir/
目录下,修改init.rc
文件,让addserver这个程序可以在开机时自动启动。
service addservice /system/bin/addserver
class core
group root system
第五步:安卓全编译
回到源码根目录,执行make -j50
进行全编译。编译成功后的镜像文件位于out/target/product/espresso8890/boot.img
。
...
Installed file list: out/target/product/espresso8890/installed-files.txt
Target system fs image: out/target/product/espresso8890/obj/PACKAGING/systemimage_intermediates/system.img
Running: mkuserimg.sh -s out/target/product/espresso8890/system out/target/product/espresso8890/obj/PACKAGING/systemimage_intermediates/system.img ext4 system 2097152000 -D out/target/product/espresso8890/system -L system out/target/product/espresso8890/root/file_contexts
make_ext4fs -s -T -1 -S out/target/product/espresso8890/root/file_contexts -L system -l 2097152000 -a system out/target/product/espresso8890/obj/PACKAGING/systemimage_intermediates/system.img out/target/product/espresso8890/system out/target/product/espresso8890/system
Creating filesystem with parameters:
Size: 2097152000
Block size: 4096
Blocks per group: 32768
Inodes per group: 8000
Inode size: 256
Journal blocks: 8000
Label: system
Blocks: 512000
Block groups: 16
Reserved block group size: 127
Created filesystem with 1873/128000 inodes and 173299/512000 blocks
Install system fs image: out/target/product/espresso8890/system.img
out/target/product/espresso8890/system.img+out/target/product/espresso8890/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p maxsize=2141061120 blocksize=4224 total=677120414 reserve=21626880
#### make completed successfully (02:36 (mm:ss)) ####
第六步:验证
- 将安卓开发板启动到fastboot模式
- 用
fastboot flash boot boot.img
命令,将boot.img
这个镜像写入到安卓开发板。 - 刷写成功后,重启开发板。
- Android正常启动
- 启动完成后,通过
adb shell
进入开发板,执行top |grep addserver
命令。 - 此时应该能看到一个
/system/bin/addserver
的进程!
130|root@espresso8890:/ # top | grep addserver
3820 4 0% S 2 56084K 19944K fg root /system/bin/addserver