android学习之ECService的实现过程

本文章以实际项目为基础,只供自己阅读(代码路径均来自A10项目4.4版本)。

首先 从上层应用开始:


import android.os.IECService; 
import android.os.ServiceManager; 
import android.os.RemoteException;
public void getECService(){
		
IECService ecService = IECService.Stub.asInterface(ServiceManager.getService("ECServiceinfo"));	
if(ecService==null){Log.e(TAG,"Unable to create the ECService instance!");return ;}try { oldEcVersion=ecService.getVersion(); newEcVersion=ecService.get_ECFW_Version(); } catch (RemoteException e) { e.printStackTrace(); } vvold[0]= (byte)(oldEcVersion & 0x000000FF); vvold[1]= (byte)((oldEcVersion>>8) & 0x000000FF); oldEC=String.format("%02x %02x", vvold[1], vvold[0]); vvfw[0]= (byte)(newEcVersion & 0x000000FF); vvfw[1]= (byte)((newEcVersion>>8) & 0x000000FF); fwEC=String.format("%02x %02x", vvfw[1], vvfw[0]);}



这里我们看到:要使用ECService首先要申请相对应的服务ecService=IECService.Stub.asInterface(ServiceManager.getService("ECServiceinfo"));

我们来研究下这个服务如何实现:

先看ServiceManager

/frameworks/base/services/java/com/android/server/SystemServer.java 

  try {
                  Slog.i(TAG, "Input Method Service");
                  imm = new InputMethodManagerService(context, wm);
                  ServiceManager.addService("ECServiceinfo", new ECService());
                  ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
              } catch (Throwable e) {
                  reportWtf("starting Input Manager Service", e);
              }
ServiceManager
在ServiceManager中添加名为“ECServiceinfo”的ECService

ServiceManager.addService("ECServiceinfo", new ECService());这句就将new ECService()服务加入到ServiceManager并命名为ECServiceinfo,

在应用层使用时就调用该名字。


至于ECService()服务怎么实现的,我们进一步看看

/frameworks/base/services/java/com/android/server$ vi ECService.java

public class ECService  extends IECService.Stub{//
      private static final String TAG = "ECService-JAVA";
  
      public static final int EC_MODE_USER = 0;
  
      ECService() {
      Log.w(TAG, "init\n");
          mNativePointer = init_native();
      //ServiceManager.addService("ECServiceinfo", this);
  
      }

ECService 类 extends IECService.Stub这就涉及到android引入一个aidl通信接口机制

先看上层函数的实现

public int getVersion() {
       Log.w(TAG, "framework:getVersion\n");
       return get_version(mNativePointer);
      }
    private static native int init_native();
    private static native void finalize_native(int ptr);
    private static native int   get_version(int ptr);
再看aidl,其实它就是一个bind,负责java层和native层的通信:

注意:需要在android.mk中编译该接口文件:

 

/frameworks/base$ vim Android.mk

LOCAL_SRC_FILES += \
        packages/services/PacProcessor/com/android/net/IProxyService.aidl \
        packages/services/Proxy/com/android/net/IProxyCallback.aidl \
        packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
+       core/java/android/os/IECService.aidl \


现在就要进入到native层看看native int get_version(int ptr);函数的实现:

/frameworks/base/services/jni/com_android_server_ECService.cpp

static JNINativeMethod method_table[] = {
261     { "init_native", "()I", (void*)init_native },
262     { "get_version","(I)I",  (void*)get_version },
263     { "get_ecfw_version","(I)I",  (void*)get_ecfw_version },
264     { "ec_fw_upgrade","(I)I",  (void*)ec_fw_upgrade },
265     { "ctrl_request", "(II[B)I", (void*)ctrl_request},
266     { "device_ctrl", "(III)I", (void*)device_ctrl},
267     { "read_firmware", "(I[BI)I", (void*)read_firmware },
268     { "write_firmware", "(I[BI)I", (void*)write_firmware },
269     { "finalize_native", "(I)V",   (void*)finalize_native },
270     { "native_writeVendorFlags", "(II)I",   (void*)native_writeVendorFlags },
271     { "native_readVendorFlags", "(I)I", (void*)native_readVendorFlags },
272     { "native_resetImageCheckFlags", "(I)I",   (void*)native_resetImageCheckFlags },
273     { "native_readImageCheckFlags", "(I[BI)I", (void*)native_readImageCheckFlags },
274     { "native_readGSensorAngle", "(I)I", (void*)native_readGSensorAngle },
275 };
276 
277 int register_android_server_ECService(JNIEnv *env)
278 {
279     return jniRegisterNativeMethods(env, "com/android/server/ECService",
280             method_table, NELEM(method_table));
281 }
注册及配对函数
{ "get_version","(I)I",  (void*)get_version },前面是Java层函数,后者是jni层函数
static ec_device_t* get_device(hw_module_t* module, char const* name)
 43 {
 44     int err;
 45     hw_device_t* device;
 46     err = module->methods->open(module, name, &device);
 47     if (err == 0) {
 48         return (ec_device_t*)device;
 49     } else {
 50         ALOGI("Jget_device failed\n");
 51         return NULL;
 52     }
 53 }


获取虚拟驱动设备,并获取hw层

static jint init_native(JNIEnv *env, jobject clazz)
 56 {
 57     int err;
 58     hw_module_t* module;
 59     Devices* devices;
 60     ALOGI("JInitializing HAL stub for ec......");
 61     devices = (Devices*)malloc(sizeof(Devices));
 62     ALOGI("ecservice jni init_native\n");
 63     err = hw_get_module(EC_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
 64     if (err == 0) {
 65     } else {
 66         memset(devices, 0, sizeof(Devices));
 67     }
 68     ALOGI("ec init\n");
 69     devices->ec = get_device(module, "ec_module");
 70 
 71     return (jint)devices;
 72 }

我们关注的功能函数的在jni中的实现:

static jint get_version(JNIEnv *env, jobject clazz, int ptr)
164 {
165     Devices* devices = (Devices*)ptr;
166     if (devices == NULL) {
167         return -1;
168     }
169     ALOGI("jget_version\n");
170 
171    return devices->ec->ops->ec_get_version(devices->ec);
172 }


注意:同样要加入android.mk

/frameworks/base/services/jni/Android.mk

@@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \
     com_android_server_input_InputManagerService.cpp \
     com_android_server_input_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
+    com_android_server_ECService.cpp \
     com_android_server_power_PowerManagerService.cpp \
     com_android_server_SerialService.cpp \
     com_android_server_SystemServer.cpp \

还有
/frameworks/base/services/jni/onload.cpp

@@ -57,6 +58,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
+    register_android_server_ECService(env);
     register_android_server_AlarmManagerService(env);
     register_android_server_UsbDeviceManager(env);


现在就要去hardware

/hardware/libhardware/hardware.c

int hw_get_module(const char *id, const struct hw_module_t **module) { return hw_get_module_by_class(id, NULL, module); }
jni层中函数的实现调用
 devices->ec->ops->ec_get_version(devices->ec);
这个实现在

/hardware/libhardware/include/hardware$ vi ec.h

struct ec_device; 
typedef struct ec_device_ops 
   int (*ec_init)(struct ec_device *); 
   int (*ec_get_version)(struct ec_device *); 
   int (*ec_get_fw_version)(struct ec_device *); 
   int (*ec_fw_upgrade)(struct ec_device *); 
   int (*ec_ctrl_request)(struct ec_device *, int,unsigned char*); 
   int (*ec_device_control)(struct ec_device *, int, int);
}
typedef struct ec_device { hw_device_t common; ec_device_ops_t *ops; void *priv; } ec_device_t;
找到头文件后再寻找具体实现的cpp

limi@git-server:~/android_4.4_A10/hardware/rk29/libec$ ls
Android_bak.mk  Android.mk  ECHal.cpp  ECHal.h  ECHal_Module.cpp  ECHal_Module.h

以上文件需要添加

/hardware/rk29/libec$ vi ECHal_Module.cpp 

int ec_get_version(struct ec_device * device) 
    int ver; ite_ec_device_t* ite_dev = NULL; LOGV("%s", __FUNCTION__); 
    if(!device) return -1; 
    ite_dev = (ite_ec_device_t*) device; return gECHal->getECVersion(); 
}

 gECHal->getECVersion();继续追踪到 ECHal.cpp 

hardware/rk29/libec$ vi ECHal.cpp 

int ECHal::getECVersion(void) 
{   
  int ret; 
  int flag =0; 
  LOGI("H:getECVersion"); 
  if (ite_init() < 0) {
     LOGI("H:failed to open ec device\n"); 
     return -1; 
  } 
   if (ioctl(m_fd,CMD_GET_VERSION , &flag)) {
        LOGE("get ver=%0x\n",flag); return -1; 
   } 
   release(); 
   return flag; 
 }
if (ioctl(m_fd,CMD_GET_VERSION , &flag))这里将设备节点和cmd传给底层驱动

到此,基本流程就分析完了。但是还有几个需要注意的地方:

因为/hardware/rk29/libec是我们自己添加的,全工程make编译的时候无法将其编译得到的库文件加载到系统中,解决方法:

先进入到/hardware/rk29/libec/Android.mk 看看输入的结果:

LOCAL_CFLAGS := -fno-short-enums -DCOPY_IMAGE_BUFFER
 ifeq ($(strip $(TARGET_BOARD_HARDWARE)),rk30board)
 LOCAL_CFLAGS += -DTARGET_RK30
 endif

..........

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_MODULE:=ec.$(TARGET_BOARD_HARDWARE)

 

 LOCAL_MODULE_TAGS:= optional
 include $(BUILD_SHARED_LIBRARY)

在将其添加到系统中:

/device/rockchip/rksdk$ vi device.mk

 @@ -201,6 +201,7 @@ PRODUCT_PACKAGES += \
     power.$(TARGET_BOARD_PLATFORM) \
     sensors.$(TARGET_BOARD_HARDWARE) \
     gralloc.$(TARGET_BOARD_HARDWARE) \
+    ec.$(TARGET_BOARD_HARDWARE) \
     hwcomposer.$(TARGET_BOARD_HARDWARE) \
最后,赋予其权限相应的权限:

/device/rockchip/rksdk$ vi ueventd.rk30board.rc

+#for ec
+/dev/ec                     0660   system     system     
+/dev/ite8561             0660   system     system  

其中/dev/ite8561   为EC的驱动设备节点,在/hardware/rk29/libec/ECHal.cpp中定义的:

#define EC_DEVICE_PATH  "/dev/ite8561"
#define EC_CTRL_DEVICE_PATH "/dev/ec"










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值