Android 13添加自定义Java系统服务(二)


欢迎加入我的知识星球 Android系统开发指南
欢迎关注微信公众号 无限无羡
欢迎关注知乎账号 无限无羡

上一篇文章我们介绍了添加自定义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端

  1. 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.

  1. 定义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();
          }
      }
}
  1. 构造 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应用,这样可以确保我们的应用较早的启动成功。

  1. 创建自定义系统服务应用

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);
    }
}
  1. 添加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!!!

猜你喜欢

转载自blog.csdn.net/weixin_41678668/article/details/130045783