rfid service完整添加
1.添加aidl
frameworks/base/Android.mk
LOCAL_SRC_FILES += \
... \
core/java/android/os/INrfCallback.aidl \
core/java/android/os/INrfService.aidl \
frameworks/base/core/java/android/os/INrfCallback.aidl
// INrfCallback.aidl
package android.os;
// Declare any non-default types here with import statements
interface INrfCallback {
void showResult(String result);
void onStateChanged(int state);
}
frameworks/base/core/java/android/os/INrfService.aidl
// INrfService.aidl
package android.os;
import android.os.INrfCallback;
// Declare any non-default types here with import statements
interface INrfService {
boolean enable();
boolean disable();
void registerCallback(String packageName, INrfCallback cb);
void unregisterCallback(String packageName, INrfCallback cb);
}
2.添加service
frameworks/base/services/core/java/com/android/server/NrfService.java
package com.android.server;
import android.content.Context;
import android.os.INrfService;
import android.os.INrfCallback;
import android.util.Slog;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
/**
* NrfService
* implementing the INrfService interface.
* @hide
*/
public class NrfService extends INrfService.Stub {
private static final String TAG = "NrfService";
private Looper mServiceLooper;
private NrfServiceHandler mServiceHandler;
private RemoteCallbackList<INrfCallback> mCallbacks = new RemoteCallbackList<INrfCallback>();
private HashMap<String, INrfCallback> mCallbacksMap = new HashMap<String, INrfCallback>();
private String mSlot = "";
private String mPackageName = "";
private boolean isModuleInited = true;
private static final int INIT_REQUEST = 0;
private static final int ENABLE_REQUEST = 1;
private static final int DISABLE_REQUEST = 2;
private static final int RELEASE_REQUEST = 3;
private static final int STATE_ERROR = -1;
private static final int STATE_UNKNOWN = 0;
private static final int STATE_OPENED = 1;
private static final int STATE_ENABLED = 2;
private static final int STATE_DISABLED = 3;
private static final int STATE_RELEASED = 4;
private int mCurrentState = STATE_UNKNOWN;
private Context mContext;
private HashSet<String> mRFIDSerials = new HashSet<>();
NrfService(Context context) {
mContext = context;
//init();
HandlerThread thread = new HandlerThread("NrfService",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new NrfServiceHandler(mServiceLooper);
//nativeInit();
//nativeSetup();
}
// Handler that receives messages from the thread
private final class NrfServiceHandler extends Handler {
public NrfServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
int action = msg.what;
Slog.d(TAG, "action="+action);
switch (action)
{
case INIT_REQUEST:
mCurrentState = init();
break;
case ENABLE_REQUEST:
mCurrentState = startScan();
break;
case DISABLE_REQUEST:
//mCurrentState = scanStop();
break;
case RELEASE_REQUEST:
mCurrentState = closeDevice();
break;
}
dispatchCurrentState(mCurrentState);
}
}
Thread mReadThread = new Thread() {
@Override
public void run() {
for (;;) {
if (mCurrentState != STATE_ENABLED &&
mCurrentState != STATE_OPENED) {
break;
}
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
byte[] data = new byte[140];
int result = nativeGetResult(data);
if (result == 0) {
String value = formatCode(bytesToHexString(data));
dispatchCurrentState(mCurrentState);
dispatchProcessingCompletedCallback(value);
} else {
mCurrentState = STATE_ERROR;
dispatchCurrentState(mCurrentState);
break;
}
//break;//TODO: maybe need
}
}
};
private int startScan() {
Slog.d(TAG, "startScan() ");
mReadThread.run();
return mCurrentState;
}
private String formatCode(String numbers) {
String value="";
mRFIDSerials.clear();
for (int i =0; i<20; i++) {
String device = numbers.substring(14*i, 14*(i+1));
if (device.startsWith("C2")) {
if (!mRFIDSerials.contains(device)) {
mRFIDSerials.add(device);
value += numbers.substring(14*i, 14*(i+1));
value += ";";
}
}
}
return value;
}
public static final String bytesToHexString(byte[] bArray) {
StringBuffer sb = new StringBuffer(bArray.length);
String sTemp;
for (int i = 0; i < bArray.length; i++) {
sTemp = Integer.toHexString(0xFF & bArray[i]);
if (sTemp.length() < 2)
sb.append(0);
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
private int init() {
Slog.d(TAG, "init()");
int result = nativeOpen();
if (result == 0) {
mCurrentState = STATE_OPENED;
} else {
mCurrentState = STATE_ERROR;
}
result = nativeScan();
if (result != 0) {
mCurrentState = STATE_ERROR;
} else {
mCurrentState = STATE_OPENED;
}
return mCurrentState;
}
private int scanStop() {
Slog.d(TAG, "scanStop()");
int result = nativeStop();
if (result == 0) {
mCurrentState = STATE_DISABLED;
} else {
mCurrentState = STATE_ERROR;
}
return mCurrentState;
}
private void reportScanCode(byte[] code) {
Slog.i(TAG, "service notify. code="+code);
}
private int closeDevice() {
Slog.d(TAG, "closeDevice()");
int result = nativeClose();
if (result == 0) {
mCurrentState = STATE_RELEASED;
} else {
mCurrentState = STATE_ERROR;
}
return mCurrentState;
}
private void dispatchCurrentState(int state) {
final int n = mCallbacks.beginBroadcast();
Slog.d(TAG, "dispatchCurrentState state="+state+"callbacks count="+n);
for (int i = 0; i < n; i++) {
INrfCallback cb = mCallbacks.getBroadcastItem(i);
if (cb != null) {
try {
Slog.d(TAG, "dispatchCurrentState state="+state);
cb.onStateChanged(state);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
mCallbacks.finishBroadcast();
}
private void dispatchProcessingCompletedCallback(String info) {
final int n = mCallbacks.beginBroadcast();
Slog.d(TAG, "dispatchProcessingCompletedCallback info="+info+"callbacks count="+n);
for (int i = 0; i < n; i++) {
INrfCallback cb = mCallbacks.getBroadcastItem(i);
if (cb != null) {
try {
cb.showResult(info);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
mCallbacks.finishBroadcast();
}
@Override
public void registerCallback(String packageName, INrfCallback cb) {
Slog.d(TAG, "registerCallback() packageName="+packageName);
if (cb != null) {
mCallbacks.register(cb);
//mCallbacksMap.put(packageName, cb);
}
if (mCallbacks.getRegisteredCallbackCount() > 0) {
mServiceHandler.sendEmptyMessage(INIT_REQUEST);
//init();
}
}
@Override
public void unregisterCallback(String packageName, INrfCallback cb) {
Slog.d(TAG, "unregisterCallback() packageName="+packageName);
if (cb != null) {
mCallbacks.unregister(cb);
//mCallbacksMap.remove(packageName);
}
if (mCallbacks.getRegisteredCallbackCount() < 1) {
scanStop();
closeDevice();
}
}
@Override
public boolean enable() throws RemoteException {
Slog.d(TAG, "enable");
if (mCurrentState == STATE_OPENED || mCurrentState == STATE_DISABLED)
{
mCurrentState = STATE_ENABLED;
mServiceHandler.sendEmptyMessage(ENABLE_REQUEST);
return true;
}
return false;
}
@Override
public boolean disable() throws RemoteException {
Slog.d(TAG, "disable mCurrentState ="+mCurrentState);
if (mCurrentState == STATE_ENABLED || mCurrentState == STATE_OPENED) {
mCurrentState = STATE_DISABLED;
mServiceHandler.sendEmptyMessage(DISABLE_REQUEST);
return true;
}
return false;
}
private static native final void nativeInit();
private native final void nativeSetup();
private static native int nativeOpen();
private static native int nativeScan();
private static native int nativeStop();
private static native int nativeGetResult(byte[] values);
private static native int nativeClose();
};
frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
try {
Slog.i(TAG, "NrfService add ");
ServiceManager.addService("nrfservice", new NrfService(context));
} catch (Throwable e) {
reportWtf("starting Nrf Service", e);
}
...
}
3.添加权限
1>添加service权限
device/qcom/sepolicy/common/service_contexts
nrfservice u:object_r:nrf_service:s0
device/qcom/sepolicy/common/service.te
type nrf_service, system_server_service, service_manager_type;
device/qcom/sepolicy/common/service_contexts
nrfservice u:object_r:nrf_service:s0
device/qcom/sepolicy/common/untrusted_app.te
allow untrusted_app nrf_service:service_manager find;
如果不填加此权限,就会报错 permission错误。
2>添加device权限
device/qcom/sepolicy/common/file_contexts
/dev/nrf u:object_r:nrf_device:s0
sepolicy/common/device.te
type nrf_device, dev_type;
device/qcom/sepolicy/common/untrusted_app.te
allow untrusted_app nrf_device:chr_file { read write open ioctl getattr};
sepolicy/common/system_server.te
allow system_server nrf_device:chr_file rw_file_perms;
4.添加jni
frameworks/base/services/core/jni/Android.mk
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_NrfService.cpp \
$(LOCAL_REL_DIR)/onload.cpp
frameworks/base/services/core/jni/com_android_server_NrfService.cpp
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include "android_runtime/AndroidRuntime.h"
#include "android/log.h"
#include "JNIHelp.h"
#include "jni.h"
namespace android
{
static const char *LOGTAG="nrf_jni";
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOGTAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOGTAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOGTAG, __VA_ARGS__)
static const char* s_device_path = "/dev/nrf";
static int s_fd = -1;
static const int NRF_MAX_COUNT = 140;
#define NRF24LE1_MAGIC 0xEA
#define NRF_IOCTL_START _IO(NRF24LE1_MAGIC, 0x1)
#define NRF_IOCTL_STOP _IO(NRF24LE1_MAGIC, 0x2)
JNIEXPORT jint JNICALL android_server_NrfService_open
(JNIEnv *env, jclass thiz)
{
LOGD("android_server_NrfService_open");
int ret;
if (s_fd >= 0) {
LOGE("Nrf is already opened.");
return 0;
}
s_fd = open(s_device_path, O_RDWR);
if (s_fd < 0) {
LOGE("open %s error %d.", s_device_path, errno);
return -1;
}
return 0;
}
JNIEXPORT jint JNICALL android_server_NrfService_scan
(JNIEnv *env, jclass thiz)
{
int ret = -1;
//usleep(10 * 1000);
LOGI("start Nrf scanner.");
ret = ioctl(s_fd, NRF_IOCTL_START);
if (ret < 0) {
LOGE("ioctl start error %d.", errno);
}
return ret;
}
JNIEXPORT jint JNICALL android_server_NrfService_getResult
(JNIEnv *env, jclass thiz, jbyteArray values)
{
int32_t count = 0;
char code[NRF_MAX_COUNT]={0};
LOGI("android_server_NrfService_getResult");
count = read(s_fd, code, NRF_MAX_COUNT);
env->SetByteArrayRegion(values, 0, NRF_MAX_COUNT, (jbyte*)code);
return count;
}
JNIEXPORT jint JNICALL
android_server_NrfService_stop(JNIEnv *env, jclass type) {
int ret;
if (s_fd <0) {
LOGE("scanner is not opened.");
return -1;
}
// usleep(10 * 1000);
LOGI("stop scanner.");
ret = ioctl(s_fd, NRF_IOCTL_STOP);
if (ret < 0) {
LOGE("ioctl stop error %d.", errno);
}
return ret;
}
JNIEXPORT jint JNICALL android_server_NrfService_close
(JNIEnv *env, jclass thiz)
{
LOGE("android_server_NrfService_close");
close(s_fd);
s_fd = -1;
return 0;
}
static JNINativeMethod method_table[] = {
{ "nativeOpen", "()I", (void*)android_server_NrfService_open },
{ "nativeScan", "()I", (void*)android_server_NrfService_scan },
{ "nativeStop", "()I", (void*)android_server_NrfService_stop },
{ "nativeGetResult", "([B)I", (void*)android_server_NrfService_getResult },
{ "nativeClose", "()I", (void*)android_server_NrfService_close },
};
int register_android_server_NrfService(JNIEnv *env)
{
return jniRegisterNativeMethods(
env, "com/android/server/NrfService",
method_table, NELEM(method_table));
}
};
frameworks/base/services/core/jni/onload.cpp
namespace android {
....
int register_android_server_NrfService(JNIEnv* env);
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
...
register_android_server_NrfService(env);
return JNI_VERSION_1_4;
}