Android 8.0 添加自定义服务流程简述
最近正在做一个项目,需要添加额外的传感器,如温湿度等。可以通过Android sensor的架构的支持添加应用层调用接口。但我拿到的温度传感器没有厂家HAL层的支持,而我对C++目前不是很熟悉。所以我采用自定义服务对上层的支持。这里我忽略了传感器的具体使用实现,只记录下自定义服务的实现流程。(以温度传感器为例)
一,添加AIDL文件
1.在frameworks\base\core\java\android\os下添加IGetTemperature.aidl文件:
// IGetTemperature.aidl
package android.os;
// Declare any non-default types here with import statements
interface IGetTemperature {
int getTemperature();
}
2.在frameworks\base\android.mk 文件添加该AIDL文件的编译链接:
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \
... ...
core/java/android/os/IGetTemperature.aidl \
二,添加服务端(温度传感器服务实现者)
1,在frameworks\base\services\core\java\com\android\server添加TemperatureService.java 实现IGetTemperature.Stub接口 :
package com.android.server;
import android.os.IGetTemperature;
import android.os.RemoteException;
public class TemperatureService extends IGetTemperature.Stub {
public TemperatureService(){
//调用native层方法native_init()
native_init();
}
@Override
public int getTemperature() throws RemoteException {
//调用native层方法native_getTemperature()
return native_getTemperature();
}
//声明native函数 (和我们平时定义的JNI不同的是frameworks\base\services\core\下的JNI不需要单独调用System.loadLibrary("JNI_so_name"))
private static native int native_getTemperature();
private static native void native_init();
}
2.在frameworks\base\services\core\jni 中添加JNI层实现com_android_server_TemperatureService.cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <nativehelper/JNIHelp.h>
namespace android {
/*
* Class: com_android_server_TemperatureService
* Method: _getTemperature
* Signature: ()I
*/
static jint com_android_server_TemperatureService_native_getTemperature
(JNIEnv* env, jobject thiz) {
//TODO 获取温度值,这里不实现直接返回100用于调试
return 100;
}
/*
* Class: com_android_server_TemperatureService
* Method: _init
* Signature: ()I
*/
static void com_android_server_TemperatureService_native_init
(JNIEnv* env, jobject thiz) {
}
//定义一个 JNINativeMethod数组
static JNINativeMethod gMethod[]{
//格式为{"java层的方法名","(参数类型)返回值类型",(void *)+JNI层队友的方法名}
{"native_getTemperature", "()I", (void *) com_android_server_TemperatureService_native_getTemperature},
{"native_init", "()V", (void *) com_android_server_TemperatureService_native_init}
};
//实现注册方法
int register_android_server_temperature(JNIEnv* env){
//jniRegisterNativeMethods()函数向Android虚拟机中注册该JNI
return jniRegisterNativeMethods(env, "com/android/server/TemperatureService", gMethod, NELEM(gMethod));
}
//和我们在应用层定义的动态JNI不同的是,JNI_OnLoad()函数在onload.cpp统一实现
}
3,在frameworks\base\services\core\jni\onload.cpp 中注册
onload.cpp:
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_BatteryStatsService(JNIEnv* env);
... ...
int register_android_server_temperature(JNIEnv* env);//声明
};
... ...
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_broadcastradio_BroadcastRadioService(env);
register_android_server_broadcastradio_Tuner(vm, env);
... ...
register_android_server_temperature(env);//注册
return JNI_VERSION_1_4;
}
3,frameworks\base\services\core\jni\android.mk中添加com_android_server_TemperatureService.cpp编译链接
# This file is included by the top level services directory to collect source
# files
LOCAL_REL_DIR := core/jni
LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/BroadcastRadio/JavaRef.cpp \
$(LOCAL_REL_DIR)/BroadcastRadio/NativeCallbackThread.cpp \
... ...
$(LOCAL_REL_DIR)/com_android_server_TemperatureService.cpp \
$(LOCAL_REL_DIR)/onload.cpp
三,启动服务(TemperatureService.java)
1,frameworks\base\services\java\com\android\server\SystemServer.java -->private void startOtherServices() :
private void startOtherServices() {
... ...
try {
final String SECONDARY_ZYGOTE_PRELOAD = "SecondaryZygotePreload";
// We start the preload ~1s before the webview factory preparation, to
// ensure that it completes before the 32 bit relro process is forked
// from the zygote. In the event that it takes too long, the webview
// RELRO process will block, but it will do so without holding any locks.
mZygotePreload = SystemServerInitThreadPool.get().submit(() -> {
... ...
//启动服务并添加到ServiceManager中
//add for aaa@qq.com{
try {
mTemperatureService = new TemperatureService();
ServiceManager.addService("temperature_service", mTemperatureService);
} catch (Exception e) {
android.util.Log.d("TemperatureService", "Failure mTemperatureService", e);
}
//add for TemperatureService @}
} catch (RuntimeException e) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting core service", e);
}
2.添加SELinux权限
(1),system\sepolicy\private\service_context
# 添加这句
temperature_service u:object_r:my_temperature_service:s0
(2),system\sepolicy\public\service.te
#添加这句
type my_temperature_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
PS:若不添加权限会出现如下报错:
05-01 11:58:08.415 205 205 E SELinux : avc: denied { add } for service=temperature_service pid=468 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
05-01 11:58:08.416 205 205 E ServiceManager: add_service('temperature_service',3e) uid=1000 - PERMISSION DENIED
05-01 11:58:08.418 468 468 D TemperatureService: Failure mTemperatureService
05-01 11:58:08.418 468 468 D TemperatureService: java.lang.SecurityException
05-01 11:58:08.418 468 468 D TemperatureService: at android.os.BinderProxy.transactNative(Native Method)
05-01 11:58:08.418 468 468 D TemperatureService: at android.os.BinderProxy.transact(Binder.java:790)
05-01 11:58:08.418 468 468 D TemperatureService: at android.os.ServiceManagerProxy.addService(ServiceManagerNative.java:161)
05-01 11:58:08.418 468 468 D TemperatureService: at android.os.ServiceManager.addService(ServiceManager.java:88)
05-01 11:58:08.418 468 468 D TemperatureService: at com.android.server.SystemServer.startOtherServices(SystemServer.java:943)
05-01 11:58:08.418 468 468 D TemperatureService: at com.android.server.SystemServer.run(SystemServer.java:408)
05-01 11:58:08.418 468 468 D TemperatureService: at com.android.server.SystemServer.main(SystemServer.java:284)
05-01 11:58:08.418 468 468 D TemperatureService: at java.lang.reflect.Method.invoke(Native Method)
05-01 11:58:08.418 468 468 D TemperatureService: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:449)
05-01 11:58:08.418 468 468 D TemperatureService: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:787)
四,添加应用层调用接口
在frameworks\base\core\java\android\os添加TemperatureManager.java:
package android.os;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.IGetTemperature;
import android.util.Log;
public class TemperatureManager {
private IGetTemperature iGetTemperature;
private static final String TAG="TemperatureManager";
public TemperatureManager(){
iGetTemperature = IGetTemperature.Stub.asInterface(ServiceManager.getService("temperature_service"));
if(iGetTemperature==null){
Log.d(TAG,"iGetTemperature==null");
}
}
public int getTemperature(){
try {
return iGetTemperature.getTemperature();
} catch (RemoteException e) {
e.printStackTrace();
return -10000;
}
}
}
至此,大功告成!
六,调试
编写一个简单的app
package test.weiyi.com.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.os.TemperatureManager;
public class MainActivity extends Activity {
private TextView textView;
private Button button;
private TemperatureManager temperatureManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
temperatureManager =new TemperatureManager();
textView = findViewById(R.id.main_t);
button = findViewById(R.id.getT);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
android.util.Log.d("TemperatureManagerTest","?="+temperatureManager.getTemperature());
textView.setText("温度:"+temperatureManager.getTemperature());
}
});
}
}
效果:
上一篇: kettle表数据比较
下一篇: kettle循环取结果集进行处理