Android 13添加自定义Java系统服务(二)
上一篇文章我们介绍了添加自定义Java系统服务(一)的第一种方法(建议先阅读),这种方法我们的服务运行在系统关键进程system_server中,如果我们的代码出现崩溃就会导致系统重启。本节我们介绍另一种方法,即将自定义服务运行在独立的进程当中,出现问题时不会影响系统的稳定性。
这种方法的关键在于将服务的实现放在自定义进程中,这样当Client通过binder调用的时候,就会运行在自定义进程当中。本节的例子我们取一个新的名字melon,以确保形成一个完整的例子。
定义aidl
// frameworks/base/core/java/android/melon/IMelonManager.aidl
package android.melon;
import android.melon.Person;
/**
* {@hide}
*/
interface IMelonManager {
void sayHello(String words);
// 自定义类型前面必须加上in或者out或者inout标识符
// in: 表示参数只能由客户端传递到服务端,基本类型默认只支持in修饰符
// out: 表示参数只能由服务端传递到客户端,服务端如果修改了参数对象的值
// 那么客户端的值也会改变,但是服务端无法读取客户端对象的值
// inout: 表示参数可以双向传递
void sayHelloTo(in Person person, String words);
}
自定义类Person的定义,用于Client和Server端传递对象数据。
// frameworks/base/core/java/android/melon/Person.java
package android.melon;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
public final class Person implements Parcelable {
private String mName;
private int mAge;
public Person() {
}
public Person(@NonNull String name, int age) {
this.mName = name;
this.mAge = age;
}
private Person(@NonNull Parcel in) {
this.mName = in.readString();
this.mAge = in.readInt();
}
@NonNull
public String getName() {
return mName;
}
public int getAge() {
return mAge;
}
public void setName(@NonNull String name) {
mName = name;
}
public void setAge(int age) {
mAge = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(this.mName);
dest.writeInt(this.mAge);
}
public void readFromParcel(@NonNull Parcel source) {
this.mName = source.readString();
this.mAge = source.readInt();
}
@NonNull
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
@Override
public Person createFromParcel(@NonNull Parcel source) {
return new Person(source);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
}
// frameworks/base/core/java/android/melon/Person.aidl
package android.melon;
parcelable Person;
定义Client端
- Context.java中定义服务名称
// frameworks/base/core/java/android/content/Context.java
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6ad91d26daf7..6e7ba7795e09 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3810,6 +3810,7 @@ public abstract class Context {
ACTIVITY_SERVICE,
ALARM_SERVICE,
BEAN_SERVICE,
+ MELON_SERVICE,
NOTIFICATION_SERVICE,
ACCESSIBILITY_SERVICE,
CAPTIONING_SERVICE,
@@ -4259,6 +4260,16 @@ public abstract class Context {
*/
public static final String BEAN_SERVICE = "bean";
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.melon.MelonManager} for interacting with the global
+ * system state.
+ *
+ * @see #getSystemService(String)
+ * @see android.melon.MelonManager
+ */
+ public static final String MELON_SERVICE = "melon";
+
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.ActivityTaskManager} for interacting with the global system state.
- 定义MelonManager.java,封装binder client。
// frameworks/base/core/java/android/melon/MelonManager.java
package android.melon;
import android.annotation.NonNull;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
/**
* {@hide}
*/
public class MelonManager {
private static final String TAG = "MelonManager";
private Context mContext;
private IMelonManager mService;
public MelonManager(IMelonManager service, Context ctx) {
Log.d(TAG, "new MelonManager");
mService = service;
mContext = ctx;
}
public void sayHello(@NonNull String words) {
Log.d(TAG, "sayHello words: " + words);
if (mService == null) {
Log.d(TAG, "sayHello mService is null!!!");
return;
}
try {
mService.sayHello(words);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public void sayHelloTo(@NonNull Person person, @NonNull String words) {
Log.d(TAG, "sayHelloTo " + person.getName() + ": " + words);
if (mService == null) {
Log.d(TAG, "sayHello mService is null!!!");
return;
}
try {
mService.sayHelloTo(person, words);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
- 构造 MelonManager.java,这样就可以通过Context.getSystemService(Context.MELON_SERVICE)获取的服务的代理封装类MelonManager了。
// frameworks/base/core/java/android/app/SystemServiceRegistry.java
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 8947e19dd0a6..4b71a0e015ba 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -136,6 +136,8 @@ import android.media.tv.interactive.ITvInteractiveAppManager;
import android.media.tv.interactive.TvInteractiveAppManager;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
+import android.melon.IMelonManager;
+import android.melon.MelonManager;
import android.nearby.NearbyFrameworkInitializer;
import android.net.ConnectivityFrameworkInitializer;
import android.net.ConnectivityFrameworkInitializerTiramisu;
@@ -344,6 +346,16 @@ public final class SystemServiceRegistry {
return new BeanManager(service, ctx);
}});
+ registerService(Context.MELON_SERVICE, MelonManager.class,
+ new CachedServiceFetcher<MelonManager>() {
+ @Override
+ public MelonManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.MELON_SERVICE);
+ IMelonManager service = IMelonManager.Stub.asInterface(b);
+ return new MelonManager(service, ctx);
+ }});
+
+
registerService(Context.AUDIO_SERVICE, AudioManager.class,
new CachedServiceFetcher<AudioManager>() {
@Override
定义服务端
服务端需要创建一个新的进程,既然是java层服务,则需要自定义一个系统App进程,并且该进程会在开机时启动。系统应用开机自启动的方案有很多种,比如添加persistent属性,接收开机广播等等。这里我使用添加persistent属性的方式,因为是一个app,则必须在PMS解析完成App后才能启动,而系统会优先启动persistent应用,这样可以确保我们的应用较早的启动成功。
- 创建自定义系统服务应用
Android.bp编译文件
// vendor/zzh/apps/MelonService/Android.bp
android_app {
name: "MelonService",
srcs: [
"app/src/main/java/**/*.java",
],
resource_dirs: [
"app/src/main/res",
],
privileged: true,
manifest: "app/src/main/AndroidManifest.xml",
platform_apis: true,
certificate: "platform",
libs: [
"framework",
],
static_libs: [
"androidx.annotation_annotation",
],
}
AndroidManifest.xml文件,请注意以下几个属性必须添加:
android:sharedUserId="android.uid.system"
coreApp="true"
android:directBootAware="true"
android:persistent="true"
// vendor/zzh/apps/MelonService/app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:sharedUserId="android.uid.system"
package="com.zzh.melonservice"
coreApp="true">
<application
android:name=".MelonApplication"
android:label="@string/app_name"
android:supportsRtl="true"
android:directBootAware="true"
android:persistent="true"
tools:targetApi="31" >
</application>
</manifest>
// vendor/zzh/apps/MelonService/app/src/main/java/com/zzh/melonservice/MelonApplication.java
package com.zzh.melonservice;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
import android.app.Application;
import android.content.Context;
import android.os.ServiceManager;
import android.util.Log;
public class MelonApplication extends Application {
private static final String TAG = "MelonApplication";
private MelonManagerService mService;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
// 调用ServiceManager.addService注册服务
mService = new MelonManagerService(getApplicationContext());
ServiceManager.addService(Context.MELON_SERVICE, mService, false, DUMP_FLAG_PRIORITY_DEFAULT);
}
@Override
public void onTerminate() {
super.onTerminate();
Log.d(TAG, "onTerminate");
}
@Override
public void onLowMemory() {
super.onLowMemory();
Log.d(TAG, "onLowMemory");
}
}
// vendor/zzh/apps/MelonService/app/src/main/java/com/zzh/melonservice/MelonManagerService.java
package com.zzh.melonservice;
import android.content.Context;
import android.melon.IMelonManager;
import android.melon.Person;
import android.util.Log;
public class MelonManagerService extends IMelonManager.Stub {
private static final String TAG = "MelonManagerService";
private Context mContext;
public MelonManagerService(Context context) {
Log.d(TAG, "MelonManagerService");
mContext = context;
}
@Override
public void sayHello(String words) {
Log.d(TAG, " sayHello : " + words);
}
@Override
public void sayHelloTo(Person person, String words) {
Log.d(TAG, " sayHello " + person.getName() + ": " + words);
}
}
- 添加selinux权限,添加到自己项目的配置文件中
// vendor/zzh/sepolicy/private/service_contexts
melon u:object_r:melonserver_service:s0
// vendor/zzh/sepolicy/public/service.te
type melonserver_service, service_manager_type;
// vendor/zzh/sepolicy/public/system_app.te
allow system_app melonserver_service:service_manager add;
案例
我们在Launcher启动的时候调用一下自定义的服务
// packages/apps/Car/Launcher/src/com/android/car/carlauncher/CarLauncher.java
--- a/src/com/android/car/carlauncher/CarLauncher.java
+++ b/src/com/android/car/carlauncher/CarLauncher.java
@@ -21,7 +21,10 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
import android.app.ActivityManager;
import android.app.TaskStackListener;
+import android.melon.MelonManager;
+import android.melon.Person;
import android.car.user.CarUserManager;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -108,6 +111,13 @@ public class CarLauncher extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ MelonManager melonManager = (MelonManager) getSystemService(Context.MELON_SERVICE);
+ melonManager.sayHello("Hello world !");
+ Person person = new Person();
+ person.setName("Rick");
+ person.setAge(32);
+ melonManager.sayHelloTo(person, " Good Night!!!");
+
if (CarLauncherUtils.isCustomDisplayPolicyDefined(this)) {
Intent controlBarIntent = new Intent(this, ControlBarActivity.class);
controlBarIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
这里调用的时候需要再加入一个selinux权限,不同的Client可能需要添加不同的规则,这里根据实际业务需要添加即可。
这里由于CarLauncher属于platform_app,所以添加如下:
// vendor/zzh/sepolicy/public/platform_app.te
allow platform_app melonserver_service:service_manager find;
正常运行的日志如下:
04-12 22:24:19.342 641 670 I ActivityManager: Start proc 993:com.zzh.melonservice/1000 for added application com.zzh.melonservice
04-12 22:24:19.343 641 641 D SystemServerTiming: StartMelonManagerService
04-12 22:24:19.343 641 641 V SystemServerTiming: StartMelonManagerService took to complete: 0ms
04-12 22:24:19.602 993 993 D MelonApplication: onCreate
04-12 22:24:19.602 993 993 D MelonManagerService: MelonManagerService
04-12 22:24:19.725 641 1086 V StorageManagerService: Package com.zzh.melonservice has legacy storage
04-12 22:24:28.645 1960 1960 D MelonManager: new MelonManager
04-12 22:24:28.645 1960 1960 D MelonManager: sayHello words: Hello world !
04-12 22:24:28.646 993 1046 D MelonManagerService: sayHello : Hello world !
04-12 22:24:28.646 1960 1960 D MelonManager: sayHelloTo Rick: Good Night!!!
04-12 22:24:28.648 993 1024 D MelonManagerService: sayHello Rick: Good Night!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库