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;
}

results matching ""

    No results matching ""