android 系统从驱动到 app 添加一个系统服务

原文链接: https://blog.csdn.net/csdn1126274345/article/details/79549124

注:整理自某个pdf

android系统从下至上分层:

kernel → HAL -->routime(虚拟机和一些其他的库)-->framework-->app

我们要添加的服务为 LedService
app 中直接可以这样使用
LedManager ledManage = getSystemService(Context.LED_SERVICE);
ledManager.setOn();//
设置手机灯的开关
ledManager.setOff();
要达到这个上面的目的,需要在系统的 Context.java ContextImpl.java 里面做如下工

Context.java

public static final String LED_SERVICE = "led";//添加该行

contextImpl.java 里面添加如下代码:


   
   
  1. public Object getSystemService(String name) {
  2. if (WINDOW_SERVICE. equals(name)) {
  3. return WindowManagerImpl.getDefault();
  4. } else if (LAYOUT_INFLATER_SERVICE. equals(name)) {
  5. synchronized (mSync) {
  6. LayoutInflater inflater = mLayoutInflater;
  7. if (inflater != null) {
  8. return inflater;
  9. }
  10. mLayoutInflater = inflater =
  11. PolicyManager.makeNewLayoutInflater(getOuterContext());
  12. return inflater;
  13. }
  14. } else if (ACTIVITY_SERVICE. equals(name)) {
  15. return getActivityManager();
  16. } else if (INPUT_METHOD_SERVICE. equals(name)) {
  17. return InputMethodManager.getInstance( this);
  18. } else if (ALARM_SERVICE. equals(name)) {
  19. return getAlarmManager();
  20. } else if (ACCOUNT_SERVICE. equals(name)) {
  21. return getAccountManager();
  22. } else if (POWER_SERVICE. equals(name)) {
  23. return getPowerManager();
  24. } else if (CONNECTIVITY_SERVICE. equals(name)) {
  25. return getConnectivityManager();
  26. } else if (THROTTLE_SERVICE. equals(name)) {
  27. return getThrottleManager();
  28. } else if (WIFI_SERVICE. equals(name)) {
  29. return getWifiManager();
  30. } else if (NOTIFICATION_SERVICE. equals(name)) {
  31. return getNotificationManager();
  32. } else if (KEYGUARD_SERVICE. equals(name)) {
  33. return new KeyguardManager();
  34. } else if (ACCESSIBILITY_SERVICE. equals(name)) {
  35. return AccessibilityManager.getInstance( this);
  36. } else if (LOCATION_SERVICE. equals(name)) {
  37. return getLocationManager();
  38. } else if (SEARCH_SERVICE. equals(name)) {
  39. return getSearchManager();
  40. } else if (SENSOR_SERVICE. equals(name)) {
  41. return getSensorManager();} else if (STORAGE_SERVICE. equals(name)) {
  42. return getStorageManager();
  43. } else if (VIBRATOR_SERVICE. equals(name)) {
  44. return getVibrator();
  45. } else if (STATUS_BAR_SERVICE. equals(name)) {
  46. synchronized (mSync) {
  47. if (mStatusBarManager == null) {
  48. mStatusBarManager = new StatusBarManager(getOuterContext());
  49. }
  50. return mStatusBarManager;
  51. }
  52. } else if (AUDIO_SERVICE. equals(name)) {
  53. return getAudioManager();
  54. } else if (TELEPHONY_SERVICE. equals(name)) {
  55. return getTelephonyManager();
  56. } else if (CLIPBOARD_SERVICE. equals(name)) {
  57. return getClipboardManager();
  58. } else if (WALLPAPER_SERVICE. equals(name)) {
  59. return getWallpaperManager();
  60. } else if (DROPBOX_SERVICE. equals(name)) {
  61. return getDropBoxManager();
  62. } else if (DEVICE_POLICY_SERVICE. equals(name)) {
  63. return getDevicePolicyManager();
  64. } else if (UI_MODE_SERVICE. equals(name)) {
  65. return getUiModeManager();
  66. } else if (DOWNLOAD_SERVICE. equals(name)) {
  67. return getDownloadManager();
  68. } else if (NFC_SERVICE. equals(name)) {
  69. return getNfcManager();
  70. }else if(LED_SERVICE.equals(name))
  71. {
  72. Log.d("ContextImpl", "get LedManager success");
  73. return getLedManager();
  74. }
  75. return null;
  76. }
  77. private LedManager getLedManager()
  78. {
  79. synchronized (mSync) {
  80. if (mLedManager == null) {
  81. mLedManager = new LedManager();
  82. }
  83. }
  84. return mLedManager;
  85. }
其中 LedManager 类的定义如下:

   
   
  1. package android.app;
  2. import android.os.RemoteException;
  3. import android.os.ServiceManager;
  4. import android.util.Log;
  5. public class LedManager
  6. {
  7. private static final String TAG = "LedManager";
  8. private ILedManager mLedService; public LedManager() {
  9. mLedService =
  10. ILedManager.Stub.asInterface(ServiceManager.getService( "led"));
  11. if (mLedService != null) {
  12. Log.i(TAG, "The LedManager object is ready.");
  13. }
  14. }
  15. public boolean setOn(int n) {
  16. boolean result = false;
  17. try {
  18. result = mLedService.setOn(n);
  19. } catch (RemoteException e) {
  20. Log.e(TAG, "RemoteException in LedManager.LedOn:", e);
  21. }
  22. return result;
  23. }
  24. public boolean setOff(int n) {
  25. boolean result = false;
  26. try {
  27. result = mLedService.setOff(n);
  28. } catch (RemoteException e) {
  29. Log.e(TAG, "RemoteException in LedManager.LedOff:", e);
  30. }
  31. return result;
  32. }
  33. }
由于我们用用 LedManager 取得一个系统服务 LedService ,所以此处就用到了一个 IPC 机制,通过 aidl
两个进程之间进行通信,这样当操作
LedManager 的时候就如同操作 LedService 了,在这里这个 aidl 文件
如下:




   
   
  1. IledManager.aidl
  2. package android.app;
  3. interface ILedManager
  4. {
  5. boolean setOn(int led);
  6. boolean setOff(int led);
  7. }

frameworks/base/Android.mk 文件增加:


   
   
  1. LOCAL_SRC_FILES += \
  2. core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
  3. core/java/android/accessibilityservice/IEventListener.aidl \
  4. core/java/android/accounts/IAccountManager.aidl \
  5. core/java/android/accounts/IAccountManagerResponse.aidl \
  6. core/java/android/accounts/IAccountAuthenticator.aidl \
  7. core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
  8. core/java/android/app/IActivityController.aidl \
  9. core/java/android/app/IActivityPendingResult.aidl \
  10. core/java/android/app/IActivityWatcher.aidl \
  11. core/java/android/app/ILedManager.aidl \
  12. core/java/android/app/IAlarmManager.aidl \
  13. core/java/android/app/IBackupAgent.aidl \
  14. core/java/android/app/IInstrumentationWatcher.aidl \
  15. core/java/android/app/INotificationManager.aidl \
  16. core/java/android/app/ISearchManager.aidl \core/java/android/app/ISearchManagerCallback.aidl \
  17. core/java/android/app/IServiceConnection.aidl \
  18. core/java/android/app/IThumbnailReceiver.aidl \
  19. core/java/android/app/ITransientNotification.aidl \
  20. core/java/android/app/IUiModeManager.aidl \
frameworks/base/services/java/com/android/server/ LedService.java 的内容如下



   
   
  1. import android.content.Context;
  2. import android.os.ServiceManager;
  3. import android.util.Log;
  4. import android.os.IBinder;
  5. import android.app.ILedManager;
  6. public final class LedService extends ILedManager.Stub {
  7. public LedService(Context context) {
  8. Log.i( "LedService", "Go to get LED Stub...");
  9. ServiceManager.addService( "led", LedService. this);
  10. _init();
  11. }
  12. /*
  13. * Mokoid LED native methods.
  14. */
  15. public boolean setOn(int led) {
  16. Log.i( "MokoidPlatform", "LED On");
  17. return _setOn(led);
  18. }
  19. public boolean setOff(int led) {
  20. Log.i( "MokoidPlatform", "LED Off");
  21. return _setOff(led);
  22. } private static native boolean _init();
  23. private static native boolean _setOn(int led);
  24. private static native boolean _setOff(int led);
  25. }

到此为止 我们就可以使用 LedManager 来使用 LedService 的方法了
由于
LedManager 是在我们的 app 里面,是属于我们程序的进程的,但是 LedService 是系统启动的时候就启
动的服务程序,是属于
systemServer 进程,不同的进程是不能通信的, android 采用了 aidl 的方式,底层
是采用
binder 驱动,通过共享内存来达到通信目的的。
ledService.java 里面有几个 native 方法,这几个方法在 java 层调用,但是实现是在 c++ 层的,这里是
通过
jni 调用来达到 java 代码调用 c++ 代码的
这里的
jni 文件如下
frameworks/base/services/jni/com_android_server_LedServic
e.cpp
这个文件名不能随便命名,要遵循 包名 _ 类名 .cpp 的原则

   
   
  1. #define LOG_TAG "Dragon"
  2. #include "jni.h"
  3. #include "JNIHelp.h"
  4. #include "android_runtime/AndroidRuntime.h"
  5. #include <utils/misc.h>
  6. #include <utils/Log.h>
  7. #include <hardware/hardware.h>
  8. #include <hardware/led.h>
  9. #define LOG_NDDEBUG 0 // 定义后,LOGD能够输出
  10. #define LOG_NIDEBUG 0 // 定义后,LOGI能够输出
  11. #define LOG_NDEBUG 0 // 定义后,LOGV能够输出
  12. namespace android
  13. {
  14. struct led_control_device_t *sLedDevice = NULL;
  15. static jboolean setOn(JNIEnv * env ,jobject clazz,jint led)
  16. {
  17. LOGI( "LedService JNI: setOn() is invoked");
  18. if(sLedDevice == NULL)
  19. {
  20. return -1;
  21. } else
  22. {
  23. return sLedDevice->set_led_on(sLedDevice,led);
  24. }
  25. }
  26. static jboolean setOff(JNIEnv * env ,jobject clazz,jint led)
  27. {
  28. LOGI( "LedService JNI: setOff() is invoked.");
  29. if (sLedDevice == NULL) {LOGI( "LedService JNI: sLedDevice was not fetched correctly.");
  30. return -1;
  31. } else {
  32. return sLedDevice->set_led_off(sLedDevice, led);
  33. }
  34. }
  35. /** helper APIs */
  36. static inline int led_control_open(const struct hw_module_t* module,
  37. struct led_control_device_t** device) {
  38. return module->methods->open( module,
  39. LED_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
  40. }
  41. static jboolean init(JNIEnv * evn ,jclass clazz)
  42. {
  43. led_module_t * module;
  44. if(hw_get_module(LED_HARDWARE_MODULE_ID,( const hw_module_t **)& module) == 0)
  45. {
  46. LOGI( "LedService JNI: LED Stub found.");
  47. if (led_control_open(& module->common, &sLedDevice) == 0) {
  48. LOGI( "LedService JNI: Got Stub operations.");
  49. return 0;
  50. }
  51. }
  52. LOGE( "LedService JNI: Get Stub operations failed.");
  53. return -1;
  54. }
// 传统的 jni 调用,函数名也是有一定规则的,但是 android 改变了这种方式,通过一下这种方式就可以把
java 层和 c++ 层的代码映射起来
// 第一个参数是 java 层要调用的方法,第二个参数是第一个参数 ( 也就是 java 层调用的函数 ) 的参数和返回
, 第三个参数是 c++ 层要调用的函数

   
   
  1. static const JNINativeMethod gMethods[] = {
  2. { "_init", "()Z", ( void *)init },
  3. { "_setOn", "(I)Z", ( void *)setOn },
  4. { "_setOff", "(I)Z", ( void *)setOff },
  5. };
// 这个函数很重要,这里是注册我们上面定义的那些方法的

   
   
  1. int register_android_server_LedService(JNIEnv *env)
  2. {
  3. return jniRegisterNativeMethods(env, "com/android/server/LedService",
  4. gMethods, NELEM(gMethods));
  5. }}
这里要注意的是,
必须在下面这个函数里面调用我们上面的那个注册函数,不然编译能过,最后手机也跑不起来

frameworks/base/services/jni/onload.cpp

   
   
  1. using namespace android;
  2. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){
  3. JNIEnv* env = NULL;
  4. jint result = -1;
  5. if (vm->GetEnv(( void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  6. LOGE( "GetEnv failed!");
  7. return result;
  8. }
  9. LOG_ASSERT(env, "Could not retrieve the env!");
  10. register_android_server_PowerManagerService(env);
  11. register_android_server_InputManager(env);
  12. register_android_server_LightsService(env);
  13. register_android_server_AlarmManagerService(env);
  14. register_android_server_BatteryService(env);
  15. register_android_server_VibratorService(env);
  16. register_android_server_SystemServer(env);
  17. register_android_server_location_GpsLocationProvider(env);
  18. register_android_server_LedService(env);
  19. //加上这句就好了
  20. return JNI_VERSION_1_4;
  21. }
到这里我们就从 java 层彻底到了 c/c++ 层了,在上面那个 cpp 文件里面的头文件有个叫做
hardware/led.h 的文件,这个文件的路径是
hardware/libhardware/include/hardware/led.h
对应的 led.c 路径是
hardware/msm7k/libdragon-led/led.c 文件
这两个文件就是属于
android HAL 层了
HAL 层主要是为了让硬件厂商不许要公开起驱动源代码
led.c 文件的内容如下:

   
   
  1. #define LOG_TAG "LedStub"
  2. #include <hardware/hardware.h>
  3. #include <fcntl.h>
  4. #include <errno.h>
  5. #include <cutils/log.h>
  6. #include <cutils/atomic.h>
  7. #include <hardware/led.h>
  8. #define GPG3DAT2_ON 0x4800;
  9. #define GPG3DAT2_OFF 0x4801;
  10. #define LOG_NDDEBUG 0 // 定义后,LOGD 能够输出
  11. #define LOG_NIDEBUG 0 // 定义后,LOGI 能够输出
  12. #define LOG_NDEBUG 0 // 定义后,LOGV 能够输出
  13. int fd;
  14. int led_device_close(struct hw_device_t * device)
  15. {
  16. struct led_control_device_t * ctx = (struct led_control_device_t *)device;
  17. if(ctx)
  18. {
  19. free(ctx);
  20. }
  21. close(fd);
  22. return 0;
  23. }
  24. int led_on(struct led_control_device_t *dev ,int32_t led)
  25. {
  26. LOGI( "LED Stub: set *d off.",led);
  27. return 0;
  28. }
  29. int led_off(struct led_control_device_t *dev ,int32_t led)
  30. {
  31. char buf[ 32] ;
  32. int n ;
  33. LOGI( "LED Stub: set %d off.",led);
  34. //这里就调用了led驱动程序
  35. if((fd = open( "/dev/led",O_RDWR))== -1)
  36. {
  37. LOGI( "LED open error");
  38. }
  39. else
  40. {
  41. LOGI( "LED open ok");
  42. n = read(fd,buf, 32);
  43. LOGI( "LED Stub: read %s data from led driver",buf);
  44. close(fd);
  45. }
  46. return 0;
  47. }
  48. static int led_device_open(const struct hw_module_t * module,const char*
  49. name ,struct hw_device_t ** device)
  50. {
  51. //下面是填充 led_control_device_t 结构体
  52. struct led_control_device_t *dev;
  53. dev = (struct led_control_device_t *) malloc( sizeof(*dev));
  54. memset(dev, 0, sizeof(*dev));
  55. dev->common.tag = HARDWARE_DEVICE_TAG;
  56. dev->common.version = 0;
  57. dev->common. module = module;
  58. dev->common.close = led_device_close;
  59. dev->set_led_on = led_on;
  60. dev->set_led_off = led_off;
  61. *device = &dev->common;
  62. success:
  63. return 0;
  64. }
  65. static struct hw_module_methods_t led_module_methods =
  66. {
  67. open: led_device_open
  68. };
  69. const struct led_module_t HAL_MODULE_INFO_SYM =
  70. {
  71. common:
  72. {
  73. tag:HARDWARE_MODULE_TAG,
  74. version_major: 1,
  75. version_minor: 0,
  76. id:LED_HARDWARE_MODULE_ID,
  77. name: "Sample LED Stud",
  78. author: "Open Source Project",
  79. methods:&led_module_methods,
  80. }
  81. };
下面是 led 驱动程序的实现代码 led_driver.c

   
   
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/device.h>
  4. #include <linux/kernel.h> /* printk() */
  5. #include <linux/slab.h> /* kmalloc() */
  6. #include <linux/fs.h> /* everything... */
  7. #include <linux/errno.h> /* error codes */
  8. #include <linux/types.h> /* size_t */
  9. #include <linux/proc_fs.h>
  10. #include <linux/fcntl.h> /* O_ACCMODE */
  11. #include <asm/system.h> /* cli(), *_flags */
  12. #include <asm/uaccess.h> /* copy_from/to_user */
  13. #define DRIVER_AUTHOR "xxxxx"
  14. #define DRIVER_DESC "HELLO WORLD DRIVER"
  15. #define DEVICE_NAME "led"
  16. MODULE_LICENSE( "Dual BSD/GPL");
  17. MODULE_AUTHOR(DRIVER_AUTHOR);
  18. MODULE_DESCRIPTION(DRIVER_DESC);
  19. int led_open(struct inode *inode, struct file *filp);
  20. int led_release(struct inode *inode, struct file*filp);
  21. ssize_t led_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
  22. ssize_t led_write(struct file *filp, __user char *buf, size_t count, loff_t *f_pos);
  23. void led_exit(void);
  24. int led_init(void);
  25. struct file_operations led_fops = {
  26. read: led_read,
  27. write: led_write,
  28. open: led_open,
  29. release: led_release
  30. };
  31. module_init(led_init);
  32. module_exit(led_exit);
  33. int led_major = 60;
  34. char * led_buffer;
  35. static struct class *led_class;
  36. int led_init()
  37. {
  38. int result;
  39. result = register_chrdev(led_major,DEVICE_NAME,&led_fops);
  40. if(result< 0)
  41. {
  42. printk( "<1> : LED cannot obtain major number %d \n",led_major);
  43. return result;
  44. }
  45. led_buffer = kmalloc( 2,GFP_KERNEL);
  46. if(!led_buffer)
  47. {
  48. result = -ENOMEM;
  49. goto fail;
  50. }
  51. memset(led_buffer, 0, 2);
  52. printk( "<1>Inserting module\n");
  53. //注册一个类,使 mdev 可以在"/dev/"目录下面建立设备节点
  54. led_class = class_create(THIS_MODULE, DEVICE_NAME);
  55. if(IS_ERR(led_class))
  56. {
  57. printk( "Err: failed in EmbedSky-leds class. \n");
  58. return -1;
  59. }
  60. //创建一个设备节点,节点名为 DEVICE_NAME
  61. device_create(led_class, NULL, MKDEV(led_major, 0), NULL,
  62. DEVICE_NAME);
  63. //官方文档为 class_device_create(led_class, NULL, MKDEV(LED_MAJOR, 0),
  64. NULL, DEVICE_NAME);
  65. printk(DEVICE_NAME " initialized\n");
  66. return result;
  67. }
  68. void led_exit()
  69. {
  70. unregister_chrdev(led_major, "");
  71. if(led_buffer)
  72. {
  73. kfree(led_buffer);
  74. }
  75. printk( "<1>LED Removing module \n");
  76. }
  77. //在 HAL 层调用 open()函数就相当与调用下面这个 led_open 函数
  78. int led_open(struct inode *inode,struct file *filp)
  79. {
  80. printk( "<1>Open device successfully\n");
  81. return 0;
  82. }
  83. int led_release(struct inode * inode,struct file * filp)
  84. {
  85. printk( "<1>Release device successfully\n");
  86. return 0;
  87. }
  88. //在 HAL 层调用 read()函数就相当与调用下面这个 led_read 函数
  89. ssize_t led_read(struct file *filp, char * buf, size_t count, loff_t * f_pos)
  90. {
  91. int n = 0;
  92. n = copy_to_user(buf,led_buffer, sizeof(led_buffer)/ sizeof( char);
  93. printk( "<1>read from user char is %s\n",led_buffer);
  94. if(*f_pos == 0)
  95. {
  96. *f_pos += n;
  97. return n;
  98. }
  99. else
  100. {
  101. return *f_pos + n;
  102. }
  103. }
  104. ssize_t led_write(struct file *filp, char * buf, size_t count, loff_t * f_pos)
  105. {
  106. int n = 0;
  107. n = copy_from_user(led_buffer,buf, sizeof(buf)/ sizeof( char));
  108. printk( "<1>write from user char is %s\n",led_buffer);
  109. return 1;
  110. }
通过以上步骤就完成了从 kernel 层到 app 层添加一个服务的功能,对于上面的驱动模块的
话,是通过单独编译成
.ko 文件,然后 push 到手机里面通过 insmod 动态加载到内核里面
, 要看内核 log 信息可以通过 adb shell dmesg 查看,上层 log 信息通过 adb shell
logcat
查看 , 当然驱动程序也可以放在 kernel/driver/ 新建 led 文件夹 /led.c 下面直接编译
kernel 里面,这样就可以每次启动系统的时候自动运行驱动了,不过这样的话需要修改
源代码的配置文件
 。


猜你喜欢

转载自blog.csdn.net/ChaoLi_Chen/article/details/101771410
今日推荐