1. 程式人生 > >android framework新增自定義服務,實現java層api呼叫

android framework新增自定義服務,實現java層api呼叫

1.在frameworks/base/core/java/android/app/下新增aidl檔案

frameworks/base/core/java/android/app/IGMyTestService.aidl

package android.app;



// Declare any non-default types here with import statements



interface IGMyTestService {

  void setCmdData(int cmd,String data);

  void getCmdData(int cmd,String data);

}


2.修改frameworks/base/Android.mk檔案,將aidl加到該檔案中,這樣才可以被編譯到,否則編譯不過

將core/java/android/app/IGMyTestService.aidl \

 加到LOCAL_SRC_FILES後面


3.在frameworks/base/services/core/java/com/android/server/下新增service檔案

frameworks/base/services/core/java/com/android/server/ GMyTestManagerService.java

package com.android.server;

/**

 * Created by Administrator on 2018/6/6.

 */

import android.app.*;

import android.app.IGMyTestService;

import android.content.Context;

import android.os.RemoteException;

import android.util.Log;

public class GMyTestManagerService extends IGMyTestService.Stub {

    private static final String TAG = "GMyTestManagerService";

    private Context mContext = null;

    public GMyTestManagerService(Context context) {

        mContext = context;

    initNative();

    }

    @Override

    public void setCmdData(int cmd) throws RemoteException {

// TODO Auto-generated method stub

        Log.d(TAG, "setCmdData cmd"+cmd);

    setCmdDataNative(cmd);

    }

    @Override

    public void setCmdData(int cmd, int data1) throws RemoteException {

// TODO Auto-generated method stub

         Log.d(TAG, "setCmdData cmd"+cmd);

    setCmdDataNative(cmd,data1);

    }

    @Override

    public void setCmdData(int cmd, int data1,int data2) throws RemoteException {

// TODO Auto-generated method stub

         Log.d(TAG, "setCmdData cmd"+cmd);

    setCmdDataNative(cmd,data1,data2);

    }

    @Override

    public void setCmdData(int cmd, int data1,int data2,int data3) throws RemoteException {

// TODO Auto-generated method stub

         Log.d(TAG, "setCmdData cmd"+cmd);

    setCmdDataNative(cmd,data1,data2,data3);

    }

    @Override

    public void getCmdData(int cmd) throws RemoteException {

// TODO Auto-generated method stub

        Log.d(TAG, "getCmdData cmd"+cmd);

    getCmdDataNative(cmd);

    }

    @Override

    public void getCmdData(int cmd, int data1) throws RemoteException {

// TODO Auto-generated method stub

       Log.d(TAG, "getCmdData cmd"+cmd);

    getCmdDataNative(cmd,data1);

    }

    @Override

    public void getCmdData(int cmd, int data1,int data2) throws RemoteException {

// TODO Auto-generated method stub

       Log.d(TAG, "getCmdData cmd"+cmd);

    getCmdDataNative(cmd,data1,data2);

    }

    @Override

    public void getCmdData(int cmd, int data1,int data2,int data3) throws RemoteException {

// TODO Auto-generated method stub

        Log.d(TAG, "getCmdData cmd"+cmd);

    getCmdDataNative(cmd,data1,data2,data3);

    }

    public static native int initNative(); 

    public static native void setCmdDataNative(int cmd); 

    public static native void setCmdOneDataNative(int cmd,int data1); 

    public static native void setCmdTwoDataNative(int cmd,int data1,int data2); 

    public static native void setCmdThreeDataNative(int cmd,int data1,int data2,int data3); 

    public static native int getCmdDataNative(int cmd); 

    public static native int getCmdOneDataNative(int cmd,int data1);

    public static native int getCmdTwoDataNative(int cmd,int data1,int data2);

    public static native int getCmdThreeDataNative(int cmd,int data1,int data2,int data3);

}
4.在frameworks/base/core/java/android/app/下新增manager給上層api

frameworks/base/core/java/android/app/ GMyTestManager.java

package android.app;

/**

 * Created by Administrator on 2018/6/6.

 */

import android.content.Context;

import android.os.RemoteException;

public class GMyTestManager {

    private static final String TAG = "GMyTestManager";

    private IGMyTestService mService = null;

    private Context mContext;

    GMyTestManager(IGMyTestService service, Context context) {

        mService = service;

        mContext = context;

    }

    public void setCmdData(int cmd) {

        try {

            mService.setCmdData(cmd);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void setCmdData(int cmd, int data1) {

        try {

            mService.setCmdOneData(cmd, data1);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void setCmdData(int cmd, int data1,int data2) {

        try {

            mService.setCmdTwoData(cmd, data1,data2);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void setCmdData(int cmd, int data1,int data2,int data3) {

        try {

            mService.setCmdThreeData(cmd, data1,data2,data3);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void getCmdData(int cmd) {

        try {

            mService.getCmdData(cmd);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void getCmdData(int cmd, int data1) {

        try {

            mService.getCmdOneData(cmd, data1);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void getCmdData(int cmd, int data1,int data2) {

        try {

            mService.getCmdTwoData(cmd, data1,data2);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public void getCmdData(int cmd, int data1,int data2,int data3) {

        try {

            mService.getCmdThreeData(cmd, data1,data2,data3);

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

}

5.在frameworks/base/core/java/android/content/Context.java中新增service名稱定義

   public static final String GMYTEST_MANAGER_SERVICE = "gmyTestdevices";
6.在frameworks/base/services/java/com/android/server/SystemServer.java中新增服務

  • 在startOtherServices()方法中新增如下程式碼

    traceBeginAndSlog("StartGMyTestManagerService");

            myTestService = new GMyTestManagerService(context);

            ServiceManager.addService(Context.GMYTEST_MANAGER_SERVICE, myTestService);

            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);


7.在frameworks/base/core/java/android/app/ContextImpl.java中註冊服務,此註冊目前在android7.0的contextImple.java子類中SystemServiceRegistry.java.

  • 在static {}中新增如下程式碼

 registerService(Context.GMYTEST_MANAGER_SERVICE, GMyTestManager.class,

                new CachedServiceFetcher<GMyTestManager>() {

            @Override

            public GMyTestManager createService(ContextImpl ctx) {

                IBinder b = ServiceManager.getService(Context.GMYTEST_MANAGER_SERVICE);

                IGMyTestService service = IGMyTestService.Stub.asInterface(b);

                return new GMyTestManager(service,ctx);

            }}); 

如果需要訪問hal層的jni呼叫,需要配置訪問許可權 

8. 另外還需要更新sepolicy的配置,否則即使編譯通過也是不會生效的.

service.te主要用來定義我們自己服務的型別,在/system/sepolicy/service.te目錄下,不同廠商的定製可能導致該路徑不同在該檔案中已經定義了很多service型別.

type wifi_service, app_api_service, system_server_service, service_manager_type;

// 參照 wifi_service的定義新增自己的定義就行了

type gmyTestdevices_service, system_api_service, system_server_service, service_manager_type;

然後修改system/sepolicy/service_contexts檔案

gmyTestdevices        u:object_r:gmyTestdevices_service:s0    

9.jni檔案編寫,在目錄frameworks/base/services/core/jni下的com_android_server_GMyTestManagerService.cpp檔案中

#define LOG_TAG "GMyTestManagerServiceJNI" 

     #include "jni.h" 

     #include "JNIHelp.h" 

     #include "android_runtime/AndroidRuntime.h"      

     #include <utils/misc.h> 

     #include <utils/Log.h> 

     #include <stdio.h> 

     #include <binder/IPCThreadState.h>

#include <binder/ProcessState.h>

#include <binder/IServiceManager.h>

#include <utils/Log.h>

#include <utils/RefBase.h>

#include <binder/Parcel.h>

#include <binder/IMemory.h>

#include <YdManager/YdManager.h>

#include <instruct/yd_cmd_instruct.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <string.h>

#include <pthread.h>

#include <string>

     namespace android 

     { 

        static int jniData = 1;

        static jint devInit(JNIEnv* env, jobject clazz) 

        { 

            //ALOGI("Init dev_init ......");

              YdManager::getInstance();

            return 1; 

        } 

        static void devSetCmdData(JNIEnv* env, jobject clazz, jint cmd) 

        { 

            jniData = cmd; 

           YdManager &mgr(YdManager::getInstance());

           mgr.exeCmdSet(cmd);

            ALOGI("dev_setCmdData......jniData=%d\n",cmd); 

        }

        static void devSetCmdOneData(JNIEnv* env, jobject clazz, jint cmd,jint data1) 

        { 

            jniData = cmd; 

           YdManager &mgr(YdManager::getInstance());

           mgr.exeCmdSet(CMD_GPIO_NOPEN);

            ALOGI("dev_setCmdData......jniData=%d\n",cmd); 

        }

        static void devSetCmdTwoData(JNIEnv* env, jobject clazz, jint cmd,jint data1,jint data2) 

        { 

            jniData = cmd; 

           YdManager &mgr(YdManager::getInstance());

           mgr.exeCmdSet(CMD_GPIO_NOPEN);

            ALOGI("dev_setCmdData......jniData=%d\n",cmd); 

        }

        static void devSetCmdThreeData(JNIEnv* env, jobject clazz, jint cmd,jint data1,jint data2,jint data3) 

        { 

            jniData = cmd; 

           YdManager &mgr(YdManager::getInstance());

           mgr.exeCmdSet(CMD_GPIO_NOPEN);

            ALOGI("dev_setCmdData......jniData=%d\n",cmd); 

        } 

        static jint devGetCmdData(JNIEnv* env, jobject clazz,jint cmd) 

        { 

            ALOGI("dev_getCmdData......jniData=%d\n",cmd); 

            return jniData; 

        } 

        static jint devGetCmdOneData(JNIEnv* env, jobject clazz,jint cmd,jint data1) 

        { 

            ALOGI("dev_getCmdData......jniData=%d\n",cmd); 

            return jniData; 

        }

        static jint devGetCmdTwoData(JNIEnv* env, jobject clazz,jint cmd,jint data1,jint data2) 

        { 

            ALOGI("dev_getCmdData......jniData=%d\n",cmd); 

            return jniData; 

        }

        static jint devGetCmdThreeData(JNIEnv* env, jobject clazz,jint cmd,jint data1,jint data2,jint data3) 

        { 

            ALOGI("dev_getCmdData......jniData=%d\n",cmd); 

            return jniData; 

        }

        /*Java本地介面方法表*/ 

        static const JNINativeMethod method_table[] = { 

            {"initNative", "()I",(void*)devInit}, 

            {"setCmdDataNative", "(I)V",(void*)devSetCmdData}, 

{"setCmdOneDataNative", "(II)V",(void*)devSetCmdOneData},

{"setCmdTwoDataNative", "(III)V",(void*)devSetCmdTwoData},

{"setCmdThreeDataNative", "(IIII)V",(void*)devSetCmdThreeData},

            {"getCmdDataNative", "(I)I",(void*)devGetCmdData},

            {"getCmdOneDataNative", "(II)I",(void*)devGetCmdOneData},

            {"getCmdTwoDataNative", "(III)I",(void*)devGetCmdTwoData},

            {"getCmdThreeDataNative", "(IIII)I",(void*)devGetCmdThreeData}, 

        }; 

        /*註冊Java本地介面方法*/ 

        int register_android_server_GMyTestManagerService(JNIEnv *env) 

        { 

            return jniRegisterNativeMethods(env, "com/android/server/GMyTestManagerService", method_table, NELEM(method_table)); 

        } 

     }; 

10. 這個JNI的cpp檔案寫好後,就要在\frameworks\base\services\core\jni\onload.cpp檔案中添加註冊函式, 這個onload.cpp檔案實現在libandroid_servers模組中,當系統載入libandroid_servers模組時,就會呼叫實現在onload.cpp檔案中的JNI_OnLoad函式,這樣就把前面定義的三個JNI方法註冊到Java虛擬機器中去了。

namespace android {  

int register_android_server_GMyTestManagerService (JNIEnv *env);  

}; 

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) 

{    

register_android_server_GMyTestManagerService(env);  

 return JNI_VERSION_1_4;  

}  

11.將開發好的cpp的jni檔案在目錄下/frameworks/base/services/core/jni/Android.mk中進行編譯.

$(LOCAL_REL_DIR)/com_android_server_GMyTestManagerService.cpp \