Android 13 はカスタム Java システム サービスを追加します (2)


私のナレッジ プラネットAndroid システム開発ガイド へようこそ 。WeChat パブリック アカウントWuxian
のフォローへようこそ 。Zhihuアカウント Wuxian のフォローへようこそ。

前の記事では、カスタム Java システム サービスを追加する最初の方法を紹介しました (最初に読むことをお勧めします)。この方法では、サービスはシステムのキー プロセス system_server で実行されます。コードがクラッシュすると、システムを再起動します。このセクションでは、問題が発生したときにシステムの安定性に影響を与えないように、カスタム サービスを独立したプロセスで実行する別の方法を紹介します。

このメソッドの重要な点は、サービス実装をカスタム プロセスに配置し、クライアントがバインダーを通じてサービス実装を呼び出すと、カスタム プロセスで実行されるようにすることです。このセクションの例では、完全な例を確実にするために、それに新しい名前 melon を付けます。

エイドルを定義する

// 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 の定義は、クライアントとサーバーの間でオブジェクト データを転送するために使用されます。

// 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;

クライアントを定義する

  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を定義し、バインダークライアントをカプセル化します。
// 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. Context.getSystemService(Context.MELON_SERVICE)で取得したサービスのプロキシカプセル化クラスMelonManagerを取得できるようにMelonManager.javaを構築します。
// 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 レイヤー サービスであるため、システム アプリ プロセスをカスタマイズする必要があり、コンピューターの電源が入ったときにプロセスが開始されます。永続属性の追加、ブート ブロードキャストの受信など、システム アプリケーションが起動時に自動的に起動するためのソリューションは数多くあります。ここでは、永続属性を追加する方法を使用します。これはアプリであるため、PMS がアプリを解析した後にのみ開始できます。システムは最初に永続アプリケーションを開始します。これにより、アプリケーションがより早く正常に開始されることが保証されます。

  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 権限を追加する必要があります。クライアントごとに異なるルールを追加する必要がある場合があります。実際のビジネス ニーズに応じてここにルールを追加できます。
ここでは 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