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

欢迎加入我的知识星球Android系统开发指南

欢迎关注微信公众号 无限无羡
欢迎关注知乎账号 无限无羡


在平时的业务开发中,我们往往需要开发自定义的系统服务来处理自己特殊的需求,我们这里提供两种方式来实现。第一种是按照已有的系统服务的方法,运行在system_server进程中,由于这样添加服务的话万一因为自定义的服务发生崩溃,将会导致system_server崩溃,从而引起系统重启。所以我们这里还会介绍第二种方法,就是将自定义的服务放到一个独立的进程中,与system_server进程隔离,这样即便自定义服务发生崩溃,也不会影响到系统稳定性。

本节先介绍第一种方法,下一节介绍第二种方法。

我们将自定义的服务取名为BeanManagerService。

定义aidl

Binder默认可以传输基本类型的数据,如果要传递类对象,则这个类需要实现序列化。我们先定义一个序列化的自定义类型,用于binder间参数传递。主要分为两步:

  1. 创建自定义类型,实现Parcelable接口
// frameworks/base/core/java/android/bean/Person.java
package android.bean;

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];
        }
    };
}
  1. 创建aidl文件,如下:
// frameworks/base/core/java/android/bean/Person.aidl
package android.bean;

parcelable Person;

这样就定义好了一个自定义对象类型,该类型可以通过binder传递,下面我们会有例子说明。

接下来我们定义自定义服务,首先要定义一个aidl文件来定义我们的接口,这个aidl文件编译后会生成binder的客户端服务端接口,我们需要实现客户端和服务端。

// bean为新建的文件夹,用于存放自定义服务
// frameworks/base/core/java/android/bean/IBeanManager.aidl
package android.bean;

import android.bean.Person;

/**
 * {@hide}
 */
interface IBeanManager {
    
    
    void sayHello(String words);
    // 自定义类型前面必须加上in或者out或者inout标识符
    // in:    表示参数只能由客户端传递到服务端,基本类型默认只支持in修饰符
    // out:   表示参数只能由服务端传递到客户端,服务端如果修改了参数对象的值
    //        那么客户端的值也会改变,但是服务端无法读取客户端对象的值
    // inout: 表示参数可以双向传递
    void sayHelloTo(in Person person, String words);
}

由于下面的Android.bp已经包含了该目录下几乎所有aidl文件和java文件的编译,所以我们不需要再将自定义的BeanManager.aidl添加到编译环境。

// frameworks/base/core/java/Android.bp
filegroup {
    
    
    name: "framework-core-sources",
    srcs: [                                                                                                                                                                                                                     
        "**/*.java",
        "**/*.aidl",
    ],  
    exclude_srcs: [
        // Remove election toolbar code from build time
        "android/service/selectiontoolbar/*.aidl",
        "android/service/selectiontoolbar/*.java",
        "android/view/selectiontoolbar/*.aidl",
        "android/view/selectiontoolbar/*.java",
        "com/android/internal/widget/floatingtoolbar/RemoteFloatingToolbarPopup.java",
    ],
    visibility: ["//frameworks/base"],
}

用以下命令编译aidl
source build/envsetup.sh
lunch sdk_car_x86_64-userdebug// 这里选择自己的项目
make update-api
make framework -j16
编译完成后,可以看到out下已经生成了binder相关的文件

Server端实现

cd frameworks/base
mkdir -p services/core/java/com/android/server/bean/
新建BeanManagerService.java
编译配置同上,不需要再单独加到编译配置中。

// frameworks/base/services/core/java/com/android/server/bean/BeanManagerService.java
package com.android.server.bean;

import android.bean.IBeanManager;
import android.bean.Person;
import android.content.Context;
import android.util.Log;

import com.android.server.SystemService;
import com.android.server.Watchdog;

public class BeanManagerService extends IBeanManager.Stub
        implements Watchdog.Monitor {
    
    
    
    static final String TAG = "BeanManagerService";

    final Context mContext;

    public BeanManagerService(Context systemContext) {
    
    
        Log.d(TAG, "BeanManagerService");
        mContext = systemContext;
        Watchdog.getInstance().addMonitor(this);
    }

    @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);
    }

    public void systemReady() {
    
    
        Log.d(TAG, " systemReady ");
    }

    /** In this method we try to acquire our lock to make sure that we have not deadlocked */
    public void monitor() {
    
    
        synchronized (this) {
    
     }
    }

	// 这里我们定义了一个内部类继承SystemService,这样便于方便system_server统一管理启动服务
	// 系统启动时会回调所有继承了SystemService的类的函数,比如onStart,onBootPhase等等。
    public static final class Lifecycle extends SystemService {
    
    
        static final String TAG = "BeanManagerService.Lifecycle";

        private BeanManagerService mService;

        public Lifecycle(Context context) {
    
    
            super(context);
            // 在这里构造我们的BeanManagerService对象
            mService = new BeanManagerService(context);
        }

        @Override
        public void onStart() {
    
    
            Log.d(TAG, "onStart");
            // 这里最终调用ServiceManager.addService
            publishBinderService(Context.BEAN_SERVICE, mService);
        }

        @Override
        public void onBootPhase(int phase) {
    
    
            Log.d(TAG, "onBootPhase");
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
    
    
                mService.systemReady();
            }
        }
    }
}

添加服务名称

// 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 77ca48a8ed1d..6ad91d26daf7 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,
@@ -4248,6 +4249,16 @@ public abstract class Context {
    
    
      */
     public static final String ACTIVITY_SERVICE = "activity";
 
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.bean.BeanManager} for interacting with the global
+     * system state.
+     *
+     * @see #getSystemService(String)
+     * @see android.bean.BeanManager
+     */
+    public static final String BEAN_SERVICE = "bean";
+

开机启动服务:

// frameworks/base/services/java/com/android/server/SystemServer.java
// 系统启动时将服务分为几个类型,如下,我们可以根据自己的具体业务添加到对应的函数里面

try {
    
    
    t.traceBegin("StartServices");
    // 引导服务,必须
    startBootstrapServices(t);
    // 核心服务,必须
    startCoreServices(t);
    // 其他服务,一般放在这里面
    startOtherServices(t);
    // 定义在apexes中的服务apexes,有兴趣的可以看下源码
    startApexServices(t);
} catch (Throwable ex) {
    
    
    Slog.e("System", "******************************************");
    Slog.e("System", "************ Failure starting system services", ex);
    throw ex;
} finally {
    
    
    t.traceEnd(); // StartServices
}
        
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -110,6 +110,7 @@ import com.android.server.appbinding.AppBindingService;
 import com.android.server.art.ArtManagerLocal;
 import com.android.server.attention.AttentionManagerService;
 import com.android.server.audio.AudioService;
+import com.android.server.bean.BeanManagerService;
 import com.android.server.biometrics.AuthService;
 import com.android.server.biometrics.BiometricService;
 import com.android.server.biometrics.sensors.face.FaceService;
@@ -1466,6 +1467,10 @@ public final class SystemServer implements Dumpable {
    
    
                 }
             }, SECONDARY_ZYGOTE_PRELOAD);
 
+            t.traceBegin("BeanManagerService");
			 // 这里最终会通过反射的方法调用BeanManagerService.Lifecycle的构造函数
+            mSystemServiceManager.startService(BeanManagerService.Lifecycle.class);
+            t.traceEnd();
+
             t.traceBegin("StartKeyAttestationApplicationIdProviderService");
             ServiceManager.addService("sec_key_att_app_id_provider",
                     new KeyAttestationApplicationIdProviderService(context));

mSystemServiceManager.startService的实现:

	// frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
    public <T extends SystemService> T startService(Class<T> serviceClass) {
    
    
        try {
    
    
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);

            // Create the service.
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
    
    
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
            try {
    
    
            	// 调用构造函数,对于我们的自定义服务就是BeanManagerService.Lifecycle
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
    
    
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            } catch (IllegalAccessException ex) {
    
    
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (NoSuchMethodException ex) {
    
    
                throw new RuntimeException("Failed to create service " + name
                        + ": service must have a public constructor with a Context argument", ex);
            } catch (InvocationTargetException ex) {
    
    
                throw new RuntimeException("Failed to create service " + name
                        + ": service constructor threw an exception", ex);
            }

            startService(service);
            return service;
        } finally {
    
    
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
    public void startService(@NonNull final SystemService service) {
    
    
        // Check if already started
        String className = service.getClass().getName();
        if (mServiceClassnames.contains(className)) {
    
    
            Slog.i(TAG, "Not starting an already started service " + className);
            return;
        }
        mServiceClassnames.add(className);

		// 将BeanManagerService.Lifecycle加入mServices列表
		// 系统的启动过程会遍历mServices列表,回调每个服务的对应函数
        // Register it.
        mServices.add(service);

        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
    
    
        	// 这里就是调用每个服务的onStart函数
            service.onStart();
        } catch (RuntimeException ex) {
    
    
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

到此,服务的添加代码已经完成,我们编译验证一下:
// 因为Context.java中新增了BEAN_SERVICE的API,所以要先make update-api
source build/envsetup.sh
lunch sdk_car_x86_64-userdebug
make update-api -j16
make -j16
启动模拟器
emulator

这时发现服务无法启动,看日志有如下报错:

Selinux权限问题,我们根据日志按规则添加:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
输出信息如下:

#============= system_server ==============
allow system_server default_android_service:service_manager add;

大家如果看过我的另一篇文章Android 13添加自定义native服务,就能立马明白这里该如何添加。
如果按照上面的提示应该是在system_server.te里添加allow system_server default_android_service:service_manager add;
但是这样会触发neverallow,正确的方法是为自定义的服务添加一个新的标签:

// vendor/zzh/sepolicy/private/service_contexts
bean                                  u:object_r:bean_service:s0

// vendor/zzh/sepolicy/public/service.te
type bean_service,       service_manager_type;

// vendor/zzh/sepolicy/public/system_server.te

allow system_server bean_service:service_manager add;


上述修改的文件大家根据自己项目添加到具体的文件中,也可以参考Android 13添加自定义native服务
修改后重新编译启动验证


可以看到服务已经正常启动。
如果遇到修改selinux后开机还是报错的情况,手动kill掉模拟器进程再启动模拟器。

Client端调用

Client调用实际上就是获取binder的代理对象,然后通过代理对象调用服务端的方法。在Android系统中,为了方便App使用系统服务的功能,一般都会给每个服务定义一个XXXManager,App可以通过Context.getSystemService(serviceName)来获取到经过包装的服务端的代理XXXManager。Context.getSystemService最终会调用到SystemServiceRegistry中的getSystemService。

	// frameworks/base/core/java/android/app/SystemServiceRegistry.java
    /**
     * Gets a system service from a given context.
     * @hide
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
    
    
        if (name == null) {
    
    
            return null;
        }
        // SYSTEM_SERVICE_FETCHERS是一个map,保存了每个服务的名称和Manager的映射关系
        // ServiceFetcher是一个接口,有一个抽象方法T getService(ContextImpl ctx);
        // 这个getService返回的便是服务的代理包装类XXXManager
        final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        if (fetcher == null) {
    
    
            if (sEnableServiceNotFoundWtf) {
    
    
                Slog.wtf(TAG, "Unknown manager requested: " + name);
            }
            return null;
        }

        final Object ret = fetcher.getService(ctx);
        if (sEnableServiceNotFoundWtf && ret == null) {
    
    
            // Some services do return null in certain situations, so don't do WTF for them.
            switch (name) {
    
    
                case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
                case Context.APP_PREDICTION_SERVICE:
                case Context.INCREMENTAL_SERVICE:
                case Context.ETHERNET_SERVICE:
                    return null;
            }
            Slog.wtf(TAG, "Manager wrapper not available: " + name);
            return null;
        }
        return ret;
    }

ServiceFetcher接口的定义

	// frameworks/base/core/java/android/app/SystemServiceRegistry.java
    /**
     * Base interface for classes that fetch services.
     * These objects must only be created during static initialization.
     */
    static abstract interface ServiceFetcher<T> {
    
    
        T getService(ContextImpl ctx);
    }

ServiceFetcher接口的实现有两个,CachedServiceFetcher和StaticServiceFetcher,这两个其实是两个抽象类,都有一个抽象方法createService,而这个createService正式获取服务端代理的真正实现。CachedServiceFetcher顾名思义就是将每个服务的代理对象都进行缓存,下一次获取的时候直接使用缓存的对象就可以了。

	// frameworks/base/core/java/android/app/SystemServiceRegistry.java
    /**
     * Override this class when the system service constructor needs a
     * ContextImpl and should be cached and retained by that context.
     */
    static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
    
    
        private final int mCacheIndex;

        CachedServiceFetcher() {
    
    
            // Note this class must be instantiated only by the static initializer of the
            // outer class (SystemServiceRegistry), which already does the synchronization,
            // so bare access to sServiceCacheSize is okay here.
            // 每一个Context对象包含了一个保存服务代理的数组,每添加一个代理,也就是每创建一个CachedServiceFetcher,
            // sServiceCacheSize便会递增,而每个CachedServiceFetcher中的mCacheIndex则是自己在整个数组中的index。
            // 后续获取服务代理时,如果cache中有数据,则直接根据mCacheIndex获取即可。
            mCacheIndex = sServiceCacheSize++;
        }

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
    
    
        	//获取Context中的保存服务代理的数组mServiceCache
            final Object[] cache = ctx.mServiceCache;
            // final int[] mServiceInitializationStateArray = new int[mServiceCache.length];
            // mServiceInitializationStateArray是一个以mServiceCache.length为size的int数组,用于
            // 保存每个服务代理的状态,目前有四种状态:
            // static final int STATE_UNINITIALIZED = 0;
    		// static final int STATE_INITIALIZING = 1;
    		// static final int STATE_READY = 2;
    		// static final int STATE_NOT_FOUND = 3;
            final int[] gates = ctx.mServiceInitializationStateArray;
            boolean interrupted = false;

            T ret = null;

            for (;;) {
    
    
                boolean doInitialize = false;
                synchronized (cache) {
    
    
                    // Return it if we already have a cached instance.
                    // 先根据mCacheIndex获取,如果不为null,说明之前已经保存过,直接返回。
                    T service = (T) cache[mCacheIndex];
                    if (service != null) {
    
    
                        ret = service;
                        break; // exit the for (;;)
                    }

                    // If we get here, there's no cached instance.

                    // Grr... if gate is STATE_READY, then this means we initialized the service
                    // once but someone cleared it.
                    // We start over from STATE_UNINITIALIZED.
                    // Similarly, if the previous attempt returned null, we'll retry again.
                    // 走到这里说明缓存中没有保存代理对象
                    // 但是状态却是(STATE_READY),说明之前是添加过的,但是现在找不到了,说明被谁从数组中移除了
                    // 或者状态是找不到(STATE_NOT_FOUND)
                    // 那么就将状态重置为STATE_UNINITIALIZED,重新再往cache数组添加一次
                    if (gates[mCacheIndex] == ContextImpl.STATE_READY
                            || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
    
    
                        gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
                    }

                    // It's possible for multiple threads to get here at the same time, so
                    // use the "gate" to make sure only the first thread will call createService().

                    // At this point, the gate must be either UNINITIALIZED or INITIALIZING.
                    // 这里在往代理服务数组中添加新数据之前,先把状态设置为STATE_INITIALIZING
                    if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
    
    
                        doInitialize = true;
                        gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
                    }
                }

                if (doInitialize) {
    
    
                    // Only the first thread gets here.
					// 接下来就要真正的保存服务代理到数组中了
                    T service = null;
                    @ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
                    try {
    
    
                        // This thread is the first one to get here. Instantiate the service
                        // *without* the cache lock held.
                        // 这里通过createService获取到服务代理对象,前面说过createService是一个抽象方法,
                    	// 说明有子类实现的地方,后面会讲到
                        service = createService(ctx);
                        newState = ContextImpl.STATE_READY;

                    } catch (ServiceNotFoundException e) {
    
    
                        onServiceNotFound(e);

                    } finally {
    
    
                        synchronized (cache) {
    
    
                        	//如果createService没有异常的话,将代理服务保存到cache数组
                        	// 将状态设置为newState, newState在前面设置为了STATE_READY
                            cache[mCacheIndex] = service;
                            gates[mCacheIndex] = newState;
                            cache.notifyAll();
                        }
                    }
                    ret = service;
                    break; // exit the for (;;)
                }
                // The other threads will wait for the first thread to call notifyAll(),
                // and go back to the top and retry.
                synchronized (cache) {
    
    
                    // Repeat until the state becomes STATE_READY or STATE_NOT_FOUND.
                    // We can't respond to interrupts here; just like we can't in the "doInitialize"
                    // path, so we remember the interrupt state here and re-interrupt later.
                    // 如果服务代理正在添加过程中,还没有添加完成时,又有一个新的线程来getSystemService,则会
                    // 进去wait状态,等待服务代理对象添加完成后执行notifyAll来唤醒当前线程
                    while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
    
    
                        try {
    
    
                            // Clear the interrupt state.
                            interrupted |= Thread.interrupted();
                            cache.wait();
                        } catch (InterruptedException e) {
    
    
                            // This shouldn't normally happen, but if someone interrupts the
                            // thread, it will.
                            Slog.w(TAG, "getService() interrupted");
                            interrupted = true;
                        }
                    }
                }
            }
            if (interrupted) {
    
    
                Thread.currentThread().interrupt();
            }
            return ret;
        }

		// 抽象方法createService
        public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
    }

	// StaticServiceFetcher则是服务代理中不需要Context对象的一种实现,也就是创建XXXManager对象时不需要
	// 传入Context参数
    /**
     * Override this class when the system service does not need a ContextImpl
     * and should be cached and retained process-wide.
     */
    static abstract class StaticServiceFetcher<T> implements ServiceFetcher<T> {
    
    
        private T mCachedInstance;

        @Override
        public final T getService(ContextImpl ctx) {
    
    
            synchronized (StaticServiceFetcher.this) {
    
    
                if (mCachedInstance == null) {
    
    
                    try {
    
    
                        mCachedInstance = createService();
                    } catch (ServiceNotFoundException e) {
    
    
                        onServiceNotFound(e);
                    }
                }
                return mCachedInstance;
            }
        }

        public abstract T createService() throws ServiceNotFoundException;
    }

通过上面可以看到,CachedServiceFetcher和StaticServiceFetcher都需要实现createService的抽象方法,我们的自定义服务代理对象BeanManager假设需要传入Context对象,则需要使用CachedServiceFetcher。

// frameworks/base/core/java/android/app/SystemServiceRegistry.java

registerService(Context.BEAN_SERVICE, BeanManager.class,
	// 这里是CachedServiceFetcher抽象类的实现
    new CachedServiceFetcher<BeanManager>() {
    
    
    // 抽象方法createService的实现,我们看到其实很简单,就是通过ServiceManager获取服务的binder代理对象
	@Override
	public BeanManager createService(ContextImpl ctx) throws ServiceNotFoundException {
    
    
	    IBinder b = ServiceManager.getServiceOrThrow(Context.BEAN_SERVICE);
	    IBeanManager service = IBeanManager.Stub.asInterface(b);
	    // 以IBeanManager和Context为参数构造BeanManager,这样我们通过Context.getSysetemService(Context.BEAN_SERVICE)
	    // 返回的对象就是BeanManager
	    return new BeanManager(service, ctx);
}});

/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
// registerService只是保存为全局的对象
private static <T> void registerService(@NonNull String serviceName,
       @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
    
    
   SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
   SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
   SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}

接下来就是该定义BeanManager了

// frameworks/base/core/java/android/bean/BeanManager.java
package android.bean;

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

/**
* {@hide}
*/
public class BeanManager {
    
    

    private static final String TAG = "BeanManager";
    private Context mContext;
    private IBeanManager mService;

    public BeanManager(IBeanManager service, Context ctx) {
    
    
        Log.d(TAG, "new BeanManager");
        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, "sayHelloTo mService is null!!!");
              return;
          }
  
          try {
    
    
              mService.sayHelloTo(person, words);
          } catch (RemoteException e) {
    
    
              throw e.rethrowFromSystemServer();
          }
      }
}

到此,我们的服务代理就添加完成了。我们调用BeanManager测试一下,我们添加到Launcher里,开机加载
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.bean.BeanManager;
+import android.bean.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);
 
+        BeanManager beanManager = (BeanManager) getSystemService(Context.BEAN_SERVICE);
+        beanManager.sayHello("Hello world !");
+        Person person = new Person();
+        person.setName("Rick");
+        person.setAge(32);
+        beanManager.sayHelloTo(person, " Good Night!!!");
+
         if (CarLauncherUtils.isCustomDisplayPolicyDefined(this)) {
    
    
             Intent controlBarIntent = new Intent(this, ControlBarActivity.class);
             controlBarIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

编译后重启服务器,看到如下日志说明调用成功:

04-05 21:08:24.623   638   638 I SystemServiceManager: Starting com.android.server.bean.BeanManagerService$Lifecycle
04-05 21:08:24.624   638   638 D BeanManagerService: BeanManagerService
04-05 21:08:24.624   638   638 D BeanManagerService.Lifecycle: onStart
04-05 21:08:25.592   638   638 D BeanManagerService.Lifecycle: onBootPhase
04-05 21:08:25.650   638   638 D BeanManagerService.Lifecycle: onBootPhase
04-05 21:08:25.650   638   638 D BeanManagerService:  systemReady 
04-05 21:08:26.020   638   638 D BeanManagerService.Lifecycle: onBootPhase
04-05 21:08:36.513  1933  1933 D BeanManager: new BeanManager
04-05 21:08:36.513  1933  1933 D BeanManager: sayHello words: Hello world !
04-05 21:08:36.515   638   805 D BeanManagerService:  sayHello : Hello world !
04-05 21:08:36.517  1933  1933 D BeanManager: sayHello to Rick: Good Night !
04-05 21:08:36.519   638   805 D BeanManagerService: sayHello to Rick: Good Night!

猜你喜欢

转载自blog.csdn.net/weixin_41678668/article/details/129916032
今日推荐