Android Native Service

A native binder service demo

Posted by LXG on January 21, 2019

Demo实现要点

  1. 核心服务通常在特定进程执行(一般为守护进程)

  2. 需要提供IBinder接口,以便应用程序可以进行跨进程的绑定和调用

  3. 因为共用,所以必须确保多线程安全

  4. 加入到ServiceManager进程管理

  5. 实现JNI, 以便应用程序方便调用

native进程实现(实现平方运算)

SQRService.h

#ifndef ANDROID_MISOO_SQRSERVICE_H

#define ANDROID_MISOO_SQRSERVICE_H

#include <stdint.h>

#include <sys/types.h>

#include <binder/Parcel.h>

#include <binder/IInterface.h>

#include <utils/RefBase.h>


namespace android {

class SQRService : public BBinder
    {
      public:
          static int instantiate();

          virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);

          SQRService();

          virtual ~SQRService();
    };

} // namespace android

#endif

SQRService.cpp

#include <binder/IServiceManager.h>

#include <cutils/log.h>

#include "SQRService.h"

namespace android {

enum {
        SQUARE = IBinder::FIRST_CALL_TRANSACTION,
};

int SQRService::instantiate() {
    ALOGE("SQRService instantiate");
    int r = defaultServiceManager()->addService(String16("misoo.sqr"), new SQRService());//add service to servicemanager
    ALOGE("SQRService r= %d\n", r);
    return r;
}

SQRService::SQRService() {
    ALOGV("SQRService created");
}

SQRService::~SQRService() {
    ALOGV("SQRService destroyed");
}

status_t SQRService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {

    switch(code) {
        case SQUARE:
        {
            int num = data.readInt32();
            reply->writeInt32(num * num);
            ALOGE("onTransact::CREATE_NUM..n=%d\n", num);
            return NO_ERROR;
        }
        break;
        default:
            ALOGE("onTransact::default\n");

        return BBinder::onTransact(code, data, reply, flags);
    }

}


} // namespace android

addserver.cpp

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

#include <grp.h>

#include <binder/IPCThreadState.h>

#include <binder/ProcessState.h>

#include <binder/IServiceManager.h>

#include <cutils/log.h>

#include "SQRService.h"

using namespace android;

int main(int argc, char** argv) {

    sp<ProcessState> proc(ProcessState::self());

    sp<IServiceManager> sm = defaultServiceManager();

    ALOGI("ServiceManager: %p", sm.get());

    SQRService::instantiate();

    ProcessState::self()->startThreadPool();

    IPCThreadState::self()->joinThreadPool();

    return 0;

}

Android.mk—生成native守护进程

#libSQRS01.so

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= SQRService.cpp

LOCAL_SHARED_LIBRARIES:= libutils libbinder liblog

LOCAL_PRELINK_MODULE:= false

LOCAL_MODULE_TAGS:= optional

LOCAL_MODULE:= libSQRS01

include $(BUILD_SHARED_LIBRARY)

# squareserver.bin

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= addserver.cpp

LOCAL_SHARED_LIBRARIES:= libutils libbinder libSQRS01 liblog

LOCAL_MODULE_TAGS:= optional

LOCAL_MODULE:= squareserver

include $(BUILD_EXECUTABLE)

提供通用性API:即IBinder接口

SQR.h

#ifndef ANDROID_MISOO_SQR_H

#define ANDROID_MISOO_SQR_H

namespace android {

class SQR {
    private:
        const void getSQRService();
    public:
        SQR();
        int execute(int n);

    };

}; //namespace

#endif

SQR.cpp


#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>

#include <cutils/log.h>

#include "SQR.h"

namespace android {

    sp<IBinder> m_ib;

    SQR::SQR() {
        getSQRService();
    }

const void SQR::getSQRService() {

    sp<IServiceManager> sm = defaultServiceManager();

    m_ib = sm->getService(String16("misoo.sqr"));

    ALOGE("SQR:getSQRService %p\n", sm.get());

    if (m_ib == 0) {
        ALOGW("SQRService not published, waiting...");
    }

}

int SQR::execute(int n) {

    Parcel data, reply;

    data.writeInt32(n);

    ALOGE("SQR::execute");

    m_ib->transact(0, data, &reply); //BpBinder

    int num = reply.readInt32();

    return num;

}

}

JNI

com_misoo_service_Sqr01.h

  1. javac com/misoo/service/Sqr01.java

  2. javah -classpath . -jni com.misoo.service.Sqr01

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_misoo_service_Sqr01 */

#ifndef _Included_com_misoo_service_Sqr01

#define _Included_com_misoo_service_Sqr01

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_misoo_service_Sqr01
 * Method:    execute
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_misoo_service_Sqr01_execute
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif

#endif

com_misoo_service_Sqr01.cpp

#include "com_misoo_service_Sqr01.h"

#include <cutils/log.h>

#include <binder/IPCThreadState.h>

#include <binder/ProcessState.h>

#include <binder/IServiceManager.h>

#include "../../SQRService.h"

#include "../../SQR.h"

using namespace android;

JNIEXPORT jint JNICALL Java_com_misoo_service_Sqr01_execute(JNIEnv *env, jobject thiz, jint x) {

    ALOGE("Java_com_misoo_service_Sqr01_execute... X=%d\n", x);

    SQR* sqrObj = new SQR();

    int num = sqrObj->execute(x);
    return num;
}

Sqr01.java

package com.misoo.service;

public class Sqr01 {

    static {
        System.loadLibrary("libSQRS01_jni");
    }

    public static native int execute(int x);

}

Android.mk—生成上层Apk使用so库

# libSQRS01_jni.so

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= com_misoo_service_Sqr01.cpp ../../SQR.cpp

LOCAL_SHARED_LIBRARIES:= libutils libbinder liblog libSQRS01

LOCAL_PRELINK_MODULE:= false

LOCAL_MODULE_TAGS:= optional

LOCAL_MODULE:= libSQRS01_jni

include $(BUILD_SHARED_LIBRARY)

添加到android系统编译环境

build/target/product/base.mk

PRODUCT_PACKAGES += \
libSQRS01 \
libSQRS01_jni \
squareserver

system/core/rootdir/init.rc

service squareserver /system/bin/squareserver
    class core
    user root
    group root
    critical
    seclabel u:r:squareserver:s0

总结

native_service

源码地址

源码地址