欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 8.0 添加自定义服务流程简述

程序员文章站 2024-02-14 09:54:16
...

        最近正在做一个项目,需要添加额外的传感器,如温湿度等。可以通过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());

            }
        });
     }
}

效果:

Android 8.0 添加自定义服务流程简述