Android 13 Java はネイティブ ローカル サービスを呼び出します


WeChatパブリックアカウント Wuxianをフォローすることを歓迎します

以前、ネイティブ サービスを追加する方法について記事を書きました ( Android 13 でカスタム ネイティブ サービスが追加されました) が、結局その記事では C++ でバインダーを介してネイティブ サービスを呼び出す例しか書きませんでした。 Java 言語クライアント バインダーはネイティブ サービスを呼び出します。

1. AIDL は Java インターフェースを生成します

前回のブログでは、コンパイル後、aidl ファイルはデフォルトで C++ 型の Binder クラス インターフェイスを生成しますが、これは次のように、aidl が C++ のコンパイル オプションに含まれているためです。

// vendor/zzh/native-service/bean-server/libbeanservice/Android.bp
// 这个标签是编译so库的
cc_library_shared {
    
    
    name: "libbeanservice_aidl",

    aidl: {
    
    
        export_aidl_headers: true,
        local_include_dirs: ["aidl"],
        include_dirs: [
        ],
    },
	
	// 编译的源文件 beanservice_aidl
    srcs: [
        ":beanservice_aidl",
    ],

    shared_libs: [
        "libbase",
        "libcutils",
        "libutils",
        "liblog",
        "libbinder",
        "libgui",
    ],


    cflags: [
        "-Werror",
        "-Wall",
        "-Wextra",
    ],
}

filegroup {
    
    
	// 该模块被上面引用
    name: "beanservice_aidl",
    // aidl接口文件,由于最后是编译c++时引用,所以只生成c++ binder类
    srcs: [
        "aidl/com/zzh/IBeanService.aidl",
    ],
    path: "aidl",
}

Java バインダー クラスを生成する場合は、次のように、Java でコンパイルされた Android.bp に beanservice_aidl を含める必要があります。

// android-13.0.0_r30/frameworks/base/Android.bp
// 这里是系统原生里将系统服务的aidl文件添加编译生成java binder类的地方,所以我们也加到这里,当然也可以自己写一个编译Java
// 的Android.bp,将beanservice_aidl添加进去
filegroup {
    
    
    name: "framework-non-updatable-sources",
    srcs: [
        // Java/AIDL sources under frameworks/base
        ":framework-annotations",
        ":framework-blobstore-sources",
        ":framework-core-sources",
        ":framework-drm-sources",
        ":framework-graphics-nonupdatable-sources",
        ":framework-jobscheduler-sources", // jobscheduler is not a module for R
        ":framework-keystore-sources",
        ":framework-identity-sources",
        ":framework-location-sources",
        ":framework-lowpan-sources",
        ":framework-mca-effect-sources",
        ":framework-mca-filterfw-sources",
        ":framework-mca-filterpacks-sources",
        ":framework-media-non-updatable-sources",
        ":framework-mms-sources",
        ":framework-omapi-sources",
        ":framework-opengl-sources",
        ":framework-rs-sources",
        ":framework-sax-sources",
        ":framework-telecomm-sources",
        ":framework-telephony-common-sources",
        ":framework-telephony-sources",
        ":framework-vcn-util-sources",
        ":framework-wifi-annotations",
        ":framework-wifi-non-updatable-sources",
        ":PacProcessor-aidl-sources",
        ":ProxyHandler-aidl-sources",
        ":net-utils-framework-common-srcs",

        // AIDL from frameworks/base/native/
        ":platform-compat-native-aidl",

        // AIDL sources from external directories
        ":android.hardware.gnss-V2-java-source",
        ":android.hardware.graphics.common-V3-java-source",
        ":android.hardware.security.keymint-V2-java-source",
        ":android.hardware.security.secureclock-V1-java-source",
        ":android.hardware.tv.tuner-V1-java-source",
        ":android.security.apc-java-source",
        ":android.security.authorization-java-source",
        ":android.security.legacykeystore-java-source",
        ":android.security.maintenance-java-source",
        ":android.security.metrics-java-source",
        ":android.system.keystore2-V1-java-source",
        ":credstore_aidl",
        ":dumpstate_aidl",
        ":framework_native_aidl",
        ":gatekeeper_aidl",
        ":gsiservice_aidl",
        ":guiconstants_aidl",
        ":idmap2_aidl",
        ":idmap2_core_aidl",
        ":incidentcompanion_aidl",
        ":inputconstants_aidl",
        ":installd_aidl",
        ":libaudioclient_aidl",
        ":libbinder_aidl",
        // 这里是CameraServer aidl文件编译添加的地方,CameraServer就是一个native服务,但是可以被App通过Java调用
        ":libcamera_client_aidl",
        // 这里是我们自定义的服务添加aidl编译的地方,这里加上后,镜像编译完成后就会生成java的binder类,java就可以通过
        // binder接口访问这个native服务了
        ":beanservice_aidl",
        ":libcamera_client_framework_aidl",
        ":libupdate_engine_aidl",
        ":logd_aidl",
        ":resourcemanager_aidl",
        ":storaged_aidl",
        ":vold_aidl",
        ":deviceproductinfoconstants_aidl",

        // For the generated R.java and Manifest.java
        ":framework-res{.aapt.srcjar}",

        // etc.
        ":framework-javastream-protos",
        ":statslog-framework-java-gen", // FrameworkStatsLog.java
        ":audio_policy_configuration_V7_0",
    ],
}

2. マネージャーの追加

システム サービスは、XXXManager クラス (ActivityManager、PackageManager など) を介してアプリからアクセスされることがわかっています。XXXManager は、Binder サービス エージェントのカプセル化です。ここでは、BeanManager という名前を付けて定義します。

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 fce23cf6819a..4d83a6a2ebe6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3809,6 +3809,7 @@ public abstract class Context {
    
    
             ACCOUNT_SERVICE,
             ACTIVITY_SERVICE,
             ALARM_SERVICE,
+            BEAN_SERVICE,
             NOTIFICATION_SERVICE,
             ACCESSIBILITY_SERVICE,
             CAPTIONING_SERVICE,
@@ -4277,6 +4278,16 @@ public abstract class Context {
    
    
      */
     public static final String ALARM_SERVICE = "alarm";
 
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.app.AlarmManager} for receiving intents at a
+     * time of your choosing.
+     *
+     * @see #getSystemService(String)
+     * @see android.app.BeanManager
+     */
+    public static final String BEAN_SERVICE = "bean";
+
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.app.NotificationManager} for informing the user of

これを SystemServiceRegistry の管理に追加すると、
Context の getSystemService(Context.BEAN_SERVICE) を通じて BeanManager オブジェクトを取得できるようになります。

// 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 b6189692107e..60ae23beab4c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -245,6 +245,8 @@ import com.android.internal.os.IDropBoxManagerService;
 import com.android.internal.policy.PhoneLayoutInflater;
 import com.android.internal.util.Preconditions;
 
+import android.bean.BeanManager;
+
 import java.util.Map;
 import java.util.Objects;
 
@@ -808,6 +810,13 @@ public final class SystemServiceRegistry {
    
    
                 return new AppOpsManager(ctx, service);
             }});
 
+               registerService(Context.BEAN_SERVICE, BeanManager.class,
+                               new CachedServiceFetcher<BeanManager>() {
    
    
+                       @Override
+                       public BeanManager createService(ContextImpl ctx) {
    
    
+                               return new BeanManager(ctx);
+                       }});
+
         registerService(Context.CAMERA_SERVICE, CameraManager.class,
                 new CachedServiceFetcher<CameraManager>() {
    
    
             @Override

XXXManager クラスを定義する

// frameworks/base/core/java/android/bean/BeanManager.java
// 我们新建了一个bean目录用来保存我们的BeanManager类,对应的包名为
// android.bean
package android.bean;

import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import com.zzh.IBeanService;

@SystemService(Context.BEAN_SERVICE)
public class BeanManager {
    
    

    private static final String TAG = "BeanManager";

	// 这个名称是Native服务注册到ServiceManager中的名称,这个代理类将会调用
	// Java的ServiceManager的getService得到binder代理
	private static final String BEAN_SERVICE_BINDER_NAME = "bean.like";

    private Context mContext;

    /**
     * @hide
     */
    public BeanManager(Context ctx) {
    
    
        Log.d(TAG, "new BeanManager");
        mContext = ctx;
    }
  
    public void sayHello() {
    
    
        Log.d(TAG, "sayHello ");
        // 通过内部类BeanManagerGlobal获取代理对象
        IBeanService beanService = BeanManagerGlobal.get().getBeanService();
        if (beanService == null) {
    
    
            Log.d(TAG, "sayHello beanService is null!!!");
            return;
        }

        try {
    
    
        	// 通过代理对象调用服务函数
            beanService.sayHello();
        } catch (RemoteException e) {
    
    
            throw e.rethrowFromSystemServer();
        }
    }

	// 内部类,获取服务端binder代理,封装对native服务的调用,是一个单利
    private static final class BeanManagerGlobal implements IBinder.DeathRecipient {
    
    

        private IBeanService mBeanService;

        private static final BeanManagerGlobal gBeanManager =
            new BeanManagerGlobal();

        private BeanManagerGlobal() {
    
     }

        public static BeanManagerGlobal get() {
    
    
            return gBeanManager;
        }

        public void binderDied() {
    
    
            mBeanService = null;
        }

		// 获取服务binder代理
        public IBeanService getBeanService() {
    
    
            connectBeanServiceLocked();
            if (mBeanService == null) {
    
    
                Log.e(TAG, "Bean service is unavailable");
            }
            return mBeanService;
        }

        private void connectBeanServiceLocked() {
    
    
            // Only reconnect if necessary
            if (mBeanService != null)
                return;

            Log.i(TAG, "Connecting to bean service");
			// 通过ServiceManager对象拿到服务代理
            IBinder beanServiceBinder = ServiceManager.getService(BEAN_SERVICE_BINDER_NAME);
            if (beanServiceBinder == null) {
    
    
                // Bean service is now down, leave mService as null
                return;
            }
            try {
    
    
                beanServiceBinder.linkToDeath(this, /* flags */ 0);
            } catch (RemoteException e) {
    
    
                // Bamera service is now down, leave mService as null
                return;
            }
			// 拿到代理对象,后续对服务收到操作都是通过这里拿到的mBeanService代理对象
            mBeanService = IBeanService.Stub.asInterface(beanServiceBinder);
        }
    }

}

上記の追加が完了すると、Java インターフェースのカプセル化は基本的に完了しますが、コンパイル中に次の問題が発生します。

352 Error: out/soong/.intermediates/frameworks/base/framework-minus-apex/android_common/aligned/framework-minus-apex.jar contains class file com.zzh.IBeanService, whose package name "com.zzh    " is empty or not in the allow list build/soong/scripts/check_boot_jars/package_allowed_list.txt of packages allowed on the bootclasspath.

プロンプトに従って、次のファイルを com.zzh に追加するだけです。

// build/soong/scripts/check_boot_jars/package_allowed_list.txt
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index a02c19560..d5e61d763 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -91,6 +91,7 @@ sun\.reflect.*
 sun\.nio.*
 sun\.net.*
 com\.sun\..*
+com\.zzh.*
 
 # TODO: Move these internal org.apache.harmony classes to libcore.*
 org\.apache\.harmony\.crypto\.internal

3. Java クライアントが Nativie サービスにアクセスする

便宜上、新しい Java プログラムを作成するのではなく、CarLauncher の起動時に BeanManager オブジェクトを取得し、sayHello インターフェイスを呼び出します。

クライアントコール

// packages/apps/Car/Launcher/src/com/android/car/carlauncher/CarLauncher.java
diff --git a/src/com/android/car/carlauncher/CarLauncher.java b/src/com/android/car/carlauncher/CarLauncher.java
index aa799ef..14a7651 100644
--- a/src/com/android/car/carlauncher/CarLauncher.java
+++ b/src/com/android/car/carlauncher/CarLauncher.java
@@ -21,9 +21,11 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERL
 
 import android.app.ActivityManager;
 import android.app.TaskStackListener;
+import android.bean.BeanManager;
 import android.car.user.CarUserManager;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.Context;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.ViewGroup;
@@ -108,6 +110,8 @@ public class CarLauncher extends FragmentActivity {
    
    
     protected void onCreate(Bundle savedInstanceState) {
    
    
         super.onCreate(savedInstanceState);
 
+        BeanManager beanManager = (BeanManager) getSystemService(Context.BEAN_SERVICE);
+        beanManager.sayHello();
         if (CarLauncherUtils.isCustomDisplayPolicyDefined(this)) {
    
    
             Intent controlBarIntent = new Intent(this, ControlBarActivity.class);
             controlBarIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

Selinux の構成

直接コンパイルして実行すると、Selinuxの権限が報告されるので、対応する権限を設定する必要があります。CarLauncherがplatform_appなので、このタイプを追加します。権限を追加するディレクトリについては、前回の記事(Android 13でカスタムネイティブが追加されました)を参照してくださいservices)、以前の内容に基づいて、変更する場所が 2 か所あります。

// 新建vendor/zzh/sepolicy/public/beanserver.te文件
type beanserver, domain, coredomain;
type beanserver_exec, exec_type, file_type, system_file_type;
// 上面两行的内容原来在vendor/beanserver.te中,将这段内容从vendor/beanserver.te删除,
// 因为后面会用到type beanserver和type beanserver_exec,必须放在public目录。

// 下面这一行是新加的,必须添加,否则Client无法通过binder调用服务端aidl里的接口函数
binder_service(beanserver)
// 添加vendor/zzh/sepolicy/vendor/platform_app.te文件
allow platform_app beanserver_service:service_manager find;

コンパイル検証

新しい API が追加されたため、最初に API を更新する必要があります

source  build/envsetup.sh
lunch sdk_car_x86_64-userdebug
make update-api -j16
make -j16
编译完成后启动模拟器
emulator
另起动一个窗口查看日志:
adb logcat|grep -i bean

ここに画像の説明を挿入します
すべてが正常に実行され、完了しました。

おすすめ

転載: blog.csdn.net/weixin_41678668/article/details/131484748