说明 参考闹钟服务编写一个HelloWorldService服务,功能为打印字符串”Hello, World!”,然后基于编译后的系统,编写APP使用该服务。
1 2 3 4 5 6 7 闹钟服务相关接口和类 - /frameworks/base/core/java/android/app/IAlarmManager.aidl 接口定义 - out/soong/.intermediates/frameworks/base/framemwork/android_common/ gen/aidl/frameworks/base/core/java/android/app/IAlarmManager.java 自动生成的接口以及Stub、Proxy - /frameworks/base/services/core/java/com/android/server/AlarmManagerService.java 服务实现 - /frameworks/base/core/java/android/app/AlarmManager.java 客户端使用的服务代理
编写Framwork代码 编写和配置 IHelloWorld.aidl 编写接口 。目录:/frameworks/base/core/java/android/app
1 2 3 4 5 6 7 8 9 package android.appinterface IHelloWorld { void printHello () ; }
待编译时,会自动生成对应的java接口和Stub、Proxy类,不用手动处理,生成的代码位于:out/soong/.intermediates/frameworks/base/framemwork/android_common/gen/aidl/frameworks/base/core/java/android/app
配置接口 。在 /framwork/base/Android.bp
中配置接口,在srcs
数组里增加HelloWorld.aidl
的路径地址即可:
1 2 3 4 5 6 7 8 9 10 11 java_defaults { name: "framework-defaults" , installable: true , srcs: [ ... "core/java/android/app/IAlarmManager.aidl" , "core/java/android/app/HelloWorld.aidl" , ... ], }
编写和注册HelloWorldService 配置常量 。在编写服务之前需要在Context.java里配置常量,参照ALARM_SERVICE,进行如下配置。
1 2 3 4 5 6 7 8 9 10 public static final String HELLO_WORLD_SERVICE = "hello_world" ;@StringDef(suffix = { "_SERVICE" }, value = { ... HELLO_WORLD_SERVICE, }) @Retention(RetentionPolicy.SOURCE) public @interface ServiceName {}
编写服务 。参考AlarmManagerService ,目录: /frameworks/base/services/core/java/com/android/server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package com.android.server;import android.app.IHelloWorld;import android.content.Context;import android.os.IBinder;import android.os.RemoteException;import android.util.Slog;public class HelloWorldService extends SystemService { public HelloWorldService (Context context) { super (context); } @Override public void onStart () { publishBinderService(Context.HELLO_WORLD, mService); } private final IBinder mService = new IHelloWorld.Stub() { private static final String TAG = "HelloWorldService" ; @Override public void printHello () throws RemoteException { Slog.i(TAG, "Hello, World!" ); } }; }
注册HelloWorldService服务 。在SystemServer.java里向服务管理者注册服务。
目录: /frameworks/base/services/java/com/android/server/SystemServer.java
1 2 3 4 5 6 7 8 9 10 11 12 private void startOtherServices () { ... traceBeginAndSlog("StartAlarmManagerService" ); mSystemServiceManager.startService(new AlarmManagerService(context)); traceEnd(); traceBeginAndSlog("StartHelloWorldService" ); mSystemServiceManager.startService(new HelloWorldService(context)); traceEnd(); ... }
编写和注册HelloWorldManager 编写HelloWorldManager 。参考AlarmManager编写客户端的HelloWorldManager,基于此应用开发者可以使用HelloWorldService。
目录:/frameworks/base/core/java/android/app
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package android.app;import android.annotation.SystemService;import android.content.Context;@SystemService(Context.HELLO_WORLD) public class HelloWorldManager { private static final String TAG = "HelloWorldManager" ; private final IHelloWorld mService; HelloWorldManager(IHelloWorld mService) { this .mService = mService; } public void printHello () { try { mService.printHello(); } catch (Exception e) { e.printStackTrace(); } } }
注册ServiceFetcher 。要利用ContextImpl.getSystemService(String name)
获取服务的Manager,需要首先在SystemServiceRegistry
里注册相应的ServiceFetcher
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 final class SystemServiceRegistry { static { ... registerService(Context.HELLO_WORLD, HelloWorldManager.class, new CachedServiceFetcher<HelloWorldManager>() { @Override public HelloWorldManager createService (ContextImpl ctx) throws ServiceNotFoundException { IBinder b = ServiceManager.getServiceOrThrow(Context.HELLO_WORLD); IHelloWorld service = IHelloWorld.Stub.asInterface(b); return new HelloWorldManager(service); }}); ... } }
配置SELinux权限 在system/sepolicy 目录下的service.te 和 service_contexts 中配置 HelloWorldService的权限。TODO,待详细了解
编译和烧录 编译Android系统,并烧录到实机设备或虚拟设备中:
编写APP并验证 将系统编译出的class.jar导入到工程中,编写APP,获取服务并调用服务的方法。
在主Activity的onCreate()里加入如下两代码:
1 2 3 4 5 protected void onCreate (Bundle savedInstanceState) { ... HelloWorldManager hwm = (HelloWorldManager)getSystemService(Context.HELLO_WORLD); hwm.printHW(); }
运行APP并查看Log
参考