Android 6.0 如何添加完整的系统服务(app-framework-kernel)

来源:互联网 发布:淘宝客服认证考试 编辑:程序博客网 时间:2024/06/11 08:55

如何在Android 6.0上添加一个系统服务,APP如何通过新增的系统服务访问底层驱动。
在这学习过程中,收获颇多,并结合学习了《Embeded Android》--Karim Yaghmour 一书中的
Appendix B. Adding Support For New Hardware章节,受益匪浅,讲述了如何添加一个完整的系统
服务(app->framework->kernel)。尽管描述的非常详细,但是基于Android 2.3.7描述的。现在把
书中的opersys例子移植到Android 6.0上,虽然说不上复杂,但由于版本差异,难免会出现许多奇奇
怪怪的问题,甚至版本差异造成了bug出现。特以此移植记录分享学习过程。

    主要围绕以下几个步骤添加一个完整的系统服务:
(A) 添加circular-char驱动
(B) 添加opersyshw_qemu HAL
(C) 添加com_android_server_opersys_OpersysService JNI
(D) 添加IOpersysService接口
(E) 添加OpersysService
(F) 添加OpersysManager
(G) 添加系统服务
(H) 注册服务
(I) 更新API
(J) 设置权限
(K) 测试服务
(L) 添加测试APP


(A) 添加circular-char驱动
   

    circular-char是一个简单的字符设备驱动,其实现的功能就是一个简单的FIFO,APP可以通过
read、write来进行读写操作实验,即写数据到FIFO,可以从FIFO读出写入的数据。

kernel/drivers/circular-driver/circular-char.c

复制代码
  1 #include <linux/module.h>  2 #include <linux/miscdevice.h>  3 #include <linux/fs.h>  4 #include <asm/uaccess.h>  5   6 #define BUF_SIZE 200  7   8 static char buf[BUF_SIZE];  9 static char *read_ptr; 10 static char *write_ptr; 11  12 static int device_open(struct inode *inode, struct file *file) 13 { 14   printk("device_open called \n"); 15  16   return 0; 17 } 18  19 static int device_release(struct inode *inode, struct file *file) 20 { 21   printk("device_release called \n"); 22  23   return 0; 24 } 25  26 static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */ 27                char *buffer,    /* buffer to fill with data */ 28                size_t length,   /* length of the buffer     */ 29                loff_t * offset) 30 { 31   int chars_read = 0; 32  33   printk("device_read called \n"); 34  35   while(length && *read_ptr && (read_ptr != write_ptr)) { 36     put_user(*(read_ptr++), buffer++); 37  38     printk("Reading %c \n", *read_ptr); 39  40     if(read_ptr >= buf + BUF_SIZE) 41       read_ptr = buf; 42  43     chars_read++; 44     length--; 45   } 46  47   return chars_read; 48 } 49  50 static ssize_t 51 device_write(struct file *filp, const char *buff, size_t len, loff_t * off) 52 { 53   int i; 54  55   printk("device_write called \n"); 56  57   for(i = 0; i < len; i++) { 58     get_user(*write_ptr, buff++); 59     printk("Writing %c \n", *write_ptr); 60     write_ptr++; 61     if (write_ptr >= buf + BUF_SIZE) 62       write_ptr = buf; 63   } 64  65   return len; 66 } 67  68 static struct file_operations fops = { 69   .open = device_open, 70   .release = device_release, 71   .read = device_read, 72   .write = device_write, 73 }; 74  75 static struct miscdevice circ_char_misc = { 76   .minor = MISC_DYNAMIC_MINOR, 77   .name = "circchar", 78   .fops = &fops, 79 }; 80  81 int circ_char_enter(void) 82 { 83   int retval; 84  85   retval = misc_register(&circ_char_misc); 86   printk("CIRC Driver got retval %d\n", retval); 87   printk("mmap is %08X\n", (int) fops.mmap); 88  89   read_ptr = buf; 90   write_ptr = buf; 91  92   return 0; 93 } 94  95 void circ_char_exit(void) 96 { 97   misc_deregister(&circ_char_misc); 98 } 99 100 module_init(circ_char_enter);101 module_exit(circ_char_exit);
复制代码

 

kernel/drivers/circular-driver/Kconfig

复制代码
 1 menuconfig DRIVER_FOR_TEST 2     bool "Drivers for test" 3     help 4       Drivers for test. 5       If unsure, say no. 6  7 if DRIVER_FOR_TEST 8  9 config CIRCULAR_CHAR10     tristate "circular-char"11     help12       circular-char driver.13 14 endif
复制代码

 

kernel/drivers/circular-driver/Makefile

1 obj-$(CONFIG_CIRCULAR_CHAR)     += circular-char.o

 

kernel/drivers/Kconfig

1 ......2 source "drivers/circular-driver/Kconfig"3 ......

 

kernel/drivers/Makefile

1 ......2 obj-$(CONFIG_DRIVER_FOR_TEST) += circular-driver/3 ......

 

kernel/arch/arm/configs/xxx_defconfig

......CONFIG_DRIVER_FOR_TEST=yCONFIG_CIRCULAR_CHAR=y......

 

    驱动已添加到内核,编译烧录到目标板看是否加载成功:

复制代码
    # ls dev/circchar    ls dev/circchar    dev/circchar    #echo hello > dev/circchar    echo hello > dev/circchar    #cat dev/circchar    dev/circchar    hello
复制代码

   

    如果执行以上命令,输出对应得信息,则说明驱动加载成功。

 

 

(B) 添加opersyshw_qemu HAL
   

    这里添加一个opersys的HAL层,使应用和驱动分离,hal主要向应用提供open、read、write等几个
接口。

 

hardware/libhardware/tests/opersyshw/opersyshw_qemu.c

复制代码
  1 #define  LOG_TAG  "opersyshw_qemu"                                                                                   2 #include <cutils/log.h>  3 #include <cutils/sockets.h>                                                                                          4 #include <sys/types.h>                                                                                               5 #include <sys/stat.h>                                                                                                6 #include <fcntl.h>  7 #include <hardware/opersyshw.h>                                                                                      8 #include <malloc.h>                                                                                                  9  10 #define   OPERSYSHW_DEBUG   1                                                                                       11  12 #if OPERSYSHW_DEBUG 13 #  define D(...)   ALOGD(__VA_ARGS__)                                                                               14 #else 15 #  define D(...)   ((void)0)                                                                                        16 #endif                                                                                                              17  18 static int fd = 0;                                                                                                  19  20 static int opersyshw__read(char* buffer, int length)                                                                21 {    22     int retval;                                                                                                     23      24     D("OPERSYS HW - read()for %d bytes called", length);                                                            25      26     retval = read(fd, buffer, length);     27     D("read data from driver: %s", buffer); 28  29     return retval; 30 } 31     32 static int opersyshw__write(char* buffer, int length) 33 { 34     int retval; 35  36     D("OPERSYS HW - write()for %d bytes called", length); 37  38     retval = write(fd, buffer, length); 39     D("write data to driver: %s", buffer); 40  41     return retval; 42 } 43  44 static int opersyshw__close(void) 45 { 46     if (fd != -1) { 47         if (!close(fd)) { 48             return 0; 49         } 50     } 51  52     return -1; 53 } 54  55 static int opersyshw__test(int value) 56 { 57     return value; 58 } 59  60 static int open_opersyshw(const struct hw_module_t* module, char const* name, 61         struct hw_device_t** device) 62 { 63     struct opersyshw_device_t *dev = malloc(sizeof(struct opersyshw_device_t)); 64     if (!dev) { 65         D("OPERSYS HW failed to malloc memory !!!"); 66         return -1; 67     } 68  69     memset(dev, 0, sizeof(*dev)); 70  71     dev->common.tag = HARDWARE_DEVICE_TAG; 72     dev->common.version = 0; 73     dev->common.module = (struct hw_module_t*)module; 74     dev->read = opersyshw__read; 75     dev->write = opersyshw__write; 76     dev->close = opersyshw__close; 77     dev->test = opersyshw__test; 78  79     *device = (struct hw_device_t*) dev; 80  81     fd = open("/dev/circchar", O_RDWR); 82     if (fd < 0) { 83         D("failed to open /dev/circchar!"); 84         return 0; 85     } 86  87     D("OPERSYS HW has been initialized"); 88  89     return 0; 90 } 91  92 static struct hw_module_methods_t opersyshw_module_methods = { 93     .open = open_opersyshw, 94 }; 95  96 struct hw_module_t HAL_MODULE_INFO_SYM = { 97     .tag = HARDWARE_MODULE_TAG, 98     .version_major = 1, 99     .version_minor = 0,100     .id = OPERSYSHW_HARDWARE_MODULE_ID,101     .name = "Opersys HW Module",102     .author = "Opersys inc.",103     .methods = &opersyshw_module_methods,104 };
复制代码

 

hardware/libhardware/include/hardware/opersyshw.h

复制代码
 1 #ifndef ANDROID_OPERSYSHW_INTERFACE_H 2 #define ANDROID_OPERSYSHW_INTERFACE_H 3  4 #include <stdint.h> 5 #include <sys/cdefs.h> 6 #include <sys/types.h> 7  8 #include <hardware/hardware.h> 9     10 __BEGIN_DECLS11 12 #define OPERSYSHW_HARDWARE_MODULE_ID "opersyshw"13 14 struct opersyshw_device_t {15     struct hw_device_t common;16 17     int (*read)(char* buffer, int length);18     int (*write)(char* buffer, int length);19     int (*close)(void);20     int (*test)(int value);21 };22 23 __END_DECLS24 25 #endif // ANDROID_OPERSYSHW_INTERFACE_H
复制代码

 

hardware/libhardware/tests/opersyshw/Android.mk

复制代码
 1 LOCAL_PATH := $(call my-dir) 2      3 # HAL module implemenation, not prelinked and stored in 4 # hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.so 5 include $(CLEAR_VARS) 6 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw 7 LOCAL_CFLAGS += $(common_flags) 8 LOCAL_LDLIBS += -llog 9 LOCAL_C_INCLUDES := hardware/libhardware10 LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware11 LOCAL_SRC_FILES := opersyshw_qemu.c12 LOCAL_MODULE := opersyshw.$(TARGET_BOARD_PLATFORM)13 LOCAL_MODULE_TAGS := optional14 include $(BUILD_SHARED_LIBRARY)
复制代码

 

    编译之后看看是否错误,是否生成.so文件,在源码根目录下:

    # find ./out/ -name 'opersyshw.*.so'    ......    ./out/target/product/<project>/system/lib/hw/opersyshw.sc8830.so    ......

 

    注意Android.mk中的$(TARGET_BOARD_PLATFORM),这里是sc8830,不同的平台会有差异

 


(C) 添加com_android_server_opersys_OpersysService JNI
   

    JNI接口主要是为了Java(app)调用C/C++。


frameworks/base/services/core/jni/com_android_server_opersys_OpersysService.cpp

复制代码
  1 #define LOG_TAG "OpersysServiceJNI"  2   3 #include "jni.h"  4 #include "JNIHelp.h"  5 #include "android_runtime/AndroidRuntime.h"  6   7 #include <utils/misc.h>  8 #include <utils/Log.h>  9 #include <hardware/hardware.h> 10 #include <hardware/opersyshw.h> 11  12 #include <stdio.h> 13  14 namespace android 15 { 16  17 opersyshw_device_t* opersyshw_dev; 18  19 static jint init_native(JNIEnv *env, jobject /* clazz */) 20 { 21     int err; 22     hw_module_t* module; 23     opersyshw_device_t* dev = NULL; 24  25     //ALOGI("init_native()");  26  27     err = hw_get_module(OPERSYSHW_HARDWARE_MODULE_ID, (hw_module_t const**)&module); 28     if (err == 0) { 29         if (module->methods->open(module, "", ((hw_device_t**) &dev)) != 0) { 30             ALOGE("Can't open opersys module!!!"); 31             return 0; 32         } 33     } else { 34         ALOGE("Can't get opersys module!!!"); 35         return 0; 36     } 37  38     return (jint)dev; 39 } 40  41 static void finalize_native(JNIEnv *env, jobject /* clazz */, int ptr) 42 { 43     opersyshw_device_t* dev = (opersyshw_device_t*)ptr; 44  45     //ALOGI("finalize_native()"); 46  47     if (dev == NULL) { 48         return; 49     } 50  51     dev->close(); 52  53     free(dev); 54 } 55  56 static int read_native(JNIEnv *env, jobject /* clazz */, int ptr, jbyteArray buffer) 57 { 58     opersyshw_device_t* dev = (opersyshw_device_t*)ptr; 59     jbyte* real_byte_array; 60     int length; 61  62     //ALOGI("read_native()"); 63  64     real_byte_array = env->GetByteArrayElements(buffer, NULL); 65  66     if (dev == NULL) { 67         return 0; 68     } 69  70     length = dev->read((char*) real_byte_array, env->GetArrayLength(buffer)); 71  72     ALOGI("read data from hal: %s", (char *)real_byte_array); 73  74     env->ReleaseByteArrayElements(buffer, real_byte_array, 0); 75  76     return length; 77 } 78  79 static int write_native(JNIEnv *env, jobject /* clazz */, int ptr, jbyteArray buffer) 80 { 81     opersyshw_device_t* dev = (opersyshw_device_t*)ptr; 82     jbyte* real_byte_array; 83     int length; 84  85     //ALOGI("write_native()"); 86  87     real_byte_array = env->GetByteArrayElements(buffer, NULL); 88  89     if (dev == NULL) { 90         return 0; 91     } 92  93     length = dev->write((char*) real_byte_array, env->GetArrayLength(buffer)); 94  95     ALOGI("write data to hal: %s", (char *)real_byte_array); 96  97     env->ReleaseByteArrayElements(buffer, real_byte_array, 0); 98  99     return length;100 }101 102 103 static int test_native(JNIEnv *env, jobject /* clazz */, int ptr, int value)104 {105     opersyshw_device_t* dev = (opersyshw_device_t*)ptr;106 107     if (dev == NULL) {108         return 0;109     }110 111     ALOGI("test_native()");112 113     return dev->test(value);114 }115 116 static JNINativeMethod method_table[] = {117     { "init_native", "()I", (void*)init_native },118     { "finalize_native", "(I)V", (void*)finalize_native },119     { "read_native", "(I[B)I", (void*)read_native },120     { "write_native", "(I[B)I", (void*)write_native },121     { "test_native", "(II)I", (void*)test_native}122 };123 124 int register_android_server_opersys_OpersysService(JNIEnv *env)125 {126     return jniRegisterNativeMethods(env, "com/android/server/opersys/OpersysService",127             method_table, NELEM(method_table));128 129 };
复制代码

 

frameworks/base/services/core/jni/onload.cpp

复制代码
 1 ...... 2 namespace android { 3 ...... 4 int register_android_server_opersys_OpersysService(JNIEnv* env); 5 ...... 6 }; 7  8 .... 9 10 extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)11 {12 ......13 register_android_server_opersys_OpersysService(env);14 ......15 }
复制代码

 

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

1 ......2 LOCAL_SRC_FILES += \3 ......4 $(LOCAL_REL_DIR)/com_android_server_opersys_OpersysService.cpp \5 ......

 

 

(D) 添加IOpersysService接口
   

    IOpersysService主要用于实现一个进程间通信的接口,其内部机制就是通过Binder实现进程间通信的,
即客户端与服务端(OpersysService)分别处于不同的进程中,客户端和服务端之间不能够直接相互访问,
之间必须通过Binder传递。

 

frameworks/base/core/java/android/opersys/IOpersysService.aidl

复制代码
1 interface IOpersysService {2 /**3 * {@hide}4 */5 String read(int maxLength);6 int write(String mString);7 }
复制代码

 

frameworks/base/Android.mk

1 ......2 LOCAL_SRC_FILES += \3 ......4 core/java/android/opersys/IOpersysService.aidl \5 ......

 

    其中,aidl文件主要用于生成同名的.java文件IOpersysService.java,IOpersysService.java主要实现
了一些Binder相关的设置和相关接口。
    编译后,会在out目录下生成:

out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/opersys/IOpersysService.java

 


(E) 添加OpersysService
   

     OpersysService主要充当一个服务端(server),直接调用native如:

private static native int init_native();private static native void finalize_native(int ptr);private static native int read_native(int ptr, byte[] buffer);private static native int write_native(int ptr, byte[] buffer);private static native int test_native(int ptr, int value);

    这些方法对应的是frameworks/base/services/core/jni/com_android_server_opersys_OpersysService.cpp
对应的同名函数,视觉上就像Java直接调用了C/C++一样。

 

frameworks/base/services/core/java/com/android/server/opersys/OpersysService.java

复制代码
 1 package com.android.server.opersys; 2  3 import android.content.Context; 4 import android.os.Handler; 5 import android.opersys.IOpersysService; 6 import android.os.Looper; 7 import android.os.Message; 8 import android.os.Process; 9 import android.util.Slog;10 import android.os.RemoteException;11 12 public class OpersysService extends IOpersysService.Stub {13     private static final String TAG = "OpersysService";14     private Context mContext;15     private int mNativePointer;16 17     public OpersysService(Context context) {18         super();19         mContext = context;20         Slog.i(TAG, "Opersys Service started");21 22         mNativePointer = init_native();23 24         Slog.i(TAG, "test() returns " + test_native(mNativePointer, 20));25     }26 27     protected void finalize() throws Throwable {28         finalize_native(mNativePointer);29         super.finalize();30     }    31     32     public String read(int maxLength) throws RemoteException33     {34         int length;35         byte[] buffer = new byte[maxLength];36 37         length = read_native(mNativePointer, buffer);38 39         try {40             return new String(buffer, 0, length, "UTF-8");41         } catch (Exception e) {42             Slog.e(TAG, "read buffer error!");43             return null;44         }45     }46 47     public int write(String mString) throws RemoteException48     {49         byte[] buffer = mString.getBytes();50 51         return write_native(mNativePointer, buffer);52     }53 54     private static native int init_native();55     private static native void finalize_native(int ptr);56     private static native int read_native(int ptr, byte[] buffer);57     private static native int write_native(int ptr, byte[] buffer);58     private static native int test_native(int ptr, int value);59 }
复制代码

 

 

(F) 添加OpersysManager
   

    OpersysManager主要用于管理OpersysService,实例化了IOpersysService,在注册服务的
时候就是实例化了一个OpersysManager,APP(客户端)获取服务getService时也是获得这个对象,通过这个对象,APP就

可以调用该服务的相关接口(API)了

frameworks/base/core/java/android/opersys/OpersysManager.java

复制代码
 1 package android.opersys; 2  3 import android.content.Context; 4 import android.os.RemoteException; 5 import android.opersys.IOpersysService; 6 import android.util.Slog; 7  8 public class OpersysManager 9 {10     private static final String TAG = "OpersysManager";11 12     public String read(int maxLength) {13         try {14             return mService.read(maxLength);15         } catch (RemoteException e) {16             Slog.e(TAG, "read error!");17             return null;18         }19     }20 21     public int write(String mString) {22         try {23             return mService.write(mString);24         } catch (RemoteException e) {25             Slog.e(TAG, "write error!");26             return 0;27         }    28     }29 30     public OpersysManager(Context context, IOpersysService service) {31         mService = service;32     }33 34     IOpersysService mService;35 }    
复制代码

 

 

(G) 添加系统服务addService
   

    实现了OpersysService的各种接口之后,需要向SystemServer添加服务

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

复制代码
 1 ...... 2 import com.android.server.opersys.OpersysService; 3     ...... 4 private void startOtherServices() { 5     ...... 6     OpersysService opersys = null; 7     ...... 8     if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {  9         ......10         try {11             Slog.i(TAG, "Opersys Service");12             opersys = new OpersysService(context);                                                             13             Slog.i(TAG, "Add Opersys Service");14             ServiceManager.addService(Context.OPERSYS_SERVICE, opersys);                                       15             Slog.i(TAG, "Opersys Service Succeed!");                                                           16         } catch (Throwable e) {17             Slog.e(TAG, "Failure starting OpersysService Service", e);                                         18         }19         ......20     }21 }
复制代码

 

frameworks/base/core/java/android/content/Context.java

复制代码
 1 ...... 2     @StringDef({ 3         ...... 4         OPERSYS_SERVICE, 5         ...... 6     }) 7     ...... 8     /** 9      * Use with {@link #getSystemService} to retrieve a10      * {@link android.opersys.OpersysManager} for using Opersys Service.11      *12      * @see #getSystemService13      */14     public static final String OPERSYS_SERVICE = "opersys";15     ......
复制代码

 

 

(H) 注册服务

 

frameworks/base/core/java/android/app/SystemServiceRegistry.java

复制代码
 1 ...... 2 import android.opersys.OpersysManager; 3 import android.opersys.IOpersysService; 4 ...... 5 final class SystemServiceRegistry { 6     ...... 7     static { 8         ...... 9         registerService(Context.OPERSYS_SERVICE, OpersysManager.class,10                 new CachedServiceFetcher<OpersysManager>() {11             @Override12             public OpersysManager createService(ContextImpl ctx) {13                 IBinder b = ServiceManager.getService(Context.OPERSYS_SERVICE);14                 IOpersysService service = IOpersysService.Stub.asInterface(b);15                 if (service == null) {16                     return null;17                 }18                 return new OpersysManager(ctx, service);19             }});20         ......21     }22     ......23 }24 ......
复制代码

 

    到这里,主要工作都要完成了,貌似可以直接可以编译进行测试了。但是实际上还有些东西需要
设置,如编译设置,SeLinux安全设置等。


(I) 更新API
   

    在前面添加和注册了服务之后,需要更新一下API才能正常编译。

frameworks/data-binding/compiler/src/main/resources/api-versions.xml

1 ......2 <field name="OPERSYS_SERVICE" />3 ...... 

 

    在源码目录下:

 # make update-api -j16

 

    编译通过后,会自动更新以下两个文件
frameworks/base/api/current.txt

复制代码
......field public static final java.lang.String OPERSYS_SERVICE = "opersys";......package android.opersys {  public abstract interface IOpersysService implements android.os.IInterface {    method public abstract int write(java.lang.String) throws android.os.RemoteException;  }  public static abstract class IOpersysService.Stub extends android.os.Binder implements android.opersys.IOpersysService {    ctor public IOpersysService.Stub();    method public android.os.IBinder asBinder();    method public static android.opersys.IOpersysService asInterface(android.os.IBinder);    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;  }  public class OpersysManager {    ctor public OpersysManager(android.content.Context, android.opersys.IOpersysService);    method public java.lang.String read(int);    method public int write(java.lang.String);  }}...... 
复制代码

 

    frameworks/base/api/system-current.txt更新同上

 

(J) 设置权限

 

external/sepolicy/service.te

1 ......2 type opersys_service, app_api_service, system_server_service, service_manager_type;3 ......

 

external/sepolicy/service_contexts

1 ......2 opersys                                   u:object_r:opersys_service:s03 ......

 

device/<manufacturer>/<chip>/common/sepolicy/device.te

1 ......2 type circchar_device, dev_type;3 ......

 

device/<manufacturer>/<chip>/common/sepolicy/file_contexts

1 ......2 /dev/circchar        u:object_r:circchar_device:s03 ......

 

device/<manufacturer>/<chip>/common/sepolicy/system_server.te  

1 ......2 allow system_server circchar_device:chr_file { open read write ioctl };3 ......

 

system/core/rootdir/ueventd.rc

1 ......2 /dev/circchar         0660   system     system3 ......

 

 

(K) 测试服务

   

    完成以上步骤后,全编译一次,烧录后,可先通过命令测试一下服务是否正常启动:

复制代码
    # service check opersys    service check opersys    Service opersys:found    # service list     service list    ......    24      opersys: [android.opersys.IOpersysService]    ......    # service call opersys 2 s16 "Hello, World!"    service call opersys 2 s16 "Hello, World!"    Result: Parcel(00000000 0000000d    '........')    # service call opersys 1 i32 20    service call opersys 1 i32 20    Result: Parcel(    0x00000000: 00000000 0000000d 00650048 006c006c '........H.e.l.l.'    0x00000010: 002c006f 00570020 0072006f 0064006c 'o.,. .W.o.r.l.d.'    0x00000020: 00000021                            '!...            ')
复制代码

    执行以上命令得到对应的结果后,说明服务启动正常。接下来就可以在APP上使用了。


(L) 添加测试APP
   

    这个APP的功能是,当用户打开APP时,APP会获得OpersysService服务,然后向这个服务发送
“Hello Opersys”,然后从这个服务读回。

packages/apps/HelloOpersysInternal/src/com/opersys/hellointernal/HelloOpersysInternalActivity.java

复制代码
 1 package com.opersys.hellointernal;                                                                                  2                                                                                                                     3 import android.app.Activity;                                                                                        4 import android.os.Bundle;                                                                                           5 import android.util.Log;                                                                                            6 import android.os.ServiceManager;   // Will only work in AOSP                                                       7 //import android.opersys.IOpersysService;  // Interface "hidden" in SDK                                             8 import android.opersys.OpersysManager;                                                                              9 import android.content.Context;                                                                                    10                                                                                                                    11 public class HelloOpersysInternalActivity extends Activity {                                                       12     private static final String DTAG = "HelloOpersysInternal";                                                     13                                                                                                                    14     /** Called when the activity is first created. */                                                              15     @Override                                                                                                      16     public void onCreate(Bundle savedInstanceState) {                                                              17         super.onCreate(savedInstanceState);                                                                        18         setContentView(R.layout.main);                                                                             19                                                                                                                    20         //IOpersysService om = IOpersysService.Stub.asInterface(ServiceManager.getService("opersys"));             21                                                                                                                    22         OpersysManager om = (OpersysManager)getSystemService(Context.OPERSYS_SERVICE);                             23         try {                                                                                                      24             Log.d(DTAG, "Going to write to the \"opersys\" service");                                              25             om.write("Hello Opersys");                                                                             26             Log.d(DTAG, "Service returned: " + om.read(20));                                                       27         }                                                                                                          28         catch (Exception e) {                                                                                      29             Log.d(DTAG, "FAILED to call service");                                                                 30             e.printStackTrace();31         }32     }33 }
复制代码

 

packages/apps/HelloOpersysInternal/res/layout/main.xml

复制代码
 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3     android:layout_width="fill_parent" 4     android:layout_height="fill_parent" 5     android:orientation="vertical" > 6  7     <TextView 8         android:layout_width="fill_parent" 9         android:layout_height="wrap_content"10         android:text="@string/hello" />11 12 </LinearLayout>
复制代码

 

packages/apps/HelloOpersysInternal/res/values/strings.xml

复制代码
1 <?xml version="1.0" encoding="utf-8"?>2 <resources>3 4     <string name="hello">Hello World, HelloOpersysInternalActivity!</string>5     <string name="app_name">HelloOpersysInternal</string>6 7 </resources>
复制代码

 

packages/apps/HelloOpersysInternal/AndroidManifest.xml

复制代码
 1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3     package="com.opersys.hellointernal" 4     android:versionCode="1" 5     android:versionName="1.0" > 6  7     <uses-sdk android:minSdkVersion="10" /> 8  9     <application10         android:icon="@drawable/ic_launcher"11         android:label="@string/app_name" >12         <activity13             android:label="@string/app_name"14             android:name=".HelloOpersysInternalActivity" >15             <intent-filter >16                 <action android:name="android.intent.action.MAIN" />17 18                 <category android:name="android.intent.category.LAUNCHER" />19             </intent-filter>20         </activity>21     </application>22 23 </manifest> 
复制代码

 

packages/apps/HelloOpersysInternal/Android.mk

复制代码
 1 LOCAL_PATH:= $(call my-dir) 2 include $(CLEAR_VARS) 3  4 LOCAL_MODULE_TAGS := optional 5      6 LOCAL_SRC_FILES := $(call all-java-files-under, src) 7  8 LOCAL_PACKAGE_NAME := HelloOpersysInternal 9 10 include $(BUILD_PACKAGE)
复制代码

 

vendor/sprd/open-source/common_packages.mk

1 PRODUCT_PACKAGES += \2 ......3 HelloOpersysInternal4 ......

 

    到这里,已经完成了所有步骤,全编译烧录之后,打开HelloOpersysInternalAPP,再打开
logcat,可以看到以下信息:

复制代码
01-01 08:07:56.137  3729  3729 D HelloOpersysInternal: Going to write to the "opersys" service01-01 08:07:56.140  1272  3082 D opersyshw_qemu: OPERSYS HW - write()for 13 bytes called01-01 08:07:56.140  1272  3082 D opersyshw_qemu: write data to driver: Hello Opersys01-01 08:07:56.140  1272  3082 I OpersysServiceJNI: write data to hal: Hello Opersys01-01 08:07:56.142  1272  3032 D opersyshw_qemu: OPERSYS HW - read()for 20 bytes called01-01 08:07:56.142  1272  3032 D opersyshw_qemu: read data from driver: Hello Opersys01-01 08:07:56.142  1272  3032 I OpersysServiceJNI: read data from hal: Hello Opersys01-01 08:07:56.143  3729  3729 D HelloOpersysInternal: Service returned: Hello Opersys
原创粉丝点击