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
- Android 6.0 如何添加完整的系统服务(app-framework-kernel)
- android framework添加系统服务
- android framework 添加系统服务
- Android驱动模型(kernel-hal-framework-app)
- 在android framework中添加自定义系统服务
- android framework增加新的系统服务
- 如何在Android中添加系统服务
- android—如何添加一个系统服务
- 如何在Android中添加系统服务
- android上如何添加系统服务
- 如何向android的framework里添加
- 如何给MIPS架构的kernel添加系统调用
- framework添加自己的服务
- [android]Framework新增系统服务
- Android Framework系统服务详解
- Android Framework系统服务详解
- Andrioid Framework中添加系统服务
- Android 添加系统服务
- iOS 正则处理 NSString,NSAttributedString
- AVL--平衡二叉树的一些操作,杂记
- 关闭NG-Bootstrap carousel 的箭头按钮和指示器
- 15 个开源的顶级人工智能工具
- 网络判断
- Android 6.0 如何添加完整的系统服务(app-framework-kernel)
- Ceph Crushmap新特性:class
- Qml上拉下拉刷新
- visual studio 2015安装 无法启动程序,因为计算机丢失D3DCOMPILER_47.dll 的解决方法
- Java 中的值传递
- Charles Proxy破解注册
- 花呗分期接入说明
- 数据结构(单源最短路径)
- linux zip/unzip命令