国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android 13添加自定義Java系統(tǒng)服務(wù)(一)

這篇具有很好參考價值的文章主要介紹了Android 13添加自定義Java系統(tǒng)服務(wù)(一)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

歡迎加入我的知識星球Android系統(tǒng)開發(fā)指南

歡迎關(guān)注微信公眾號 無限無羨
歡迎關(guān)注知乎賬號 無限無羨


在平時的業(yè)務(wù)開發(fā)中,我們往往需要開發(fā)自定義的系統(tǒng)服務(wù)來處理自己特殊的需求,我們這里提供兩種方式來實(shí)現(xiàn)。第一種是按照已有的系統(tǒng)服務(wù)的方法,運(yùn)行在system_server進(jìn)程中,由于這樣添加服務(wù)的話萬一因?yàn)樽远x的服務(wù)發(fā)生崩潰,將會導(dǎo)致system_server崩潰,從而引起系統(tǒng)重啟。所以我們這里還會介紹第二種方法,就是將自定義的服務(wù)放到一個獨(dú)立的進(jìn)程中,與system_server進(jìn)程隔離,這樣即便自定義服務(wù)發(fā)生崩潰,也不會影響到系統(tǒng)穩(wěn)定性。

本節(jié)先介紹第一種方法,下一節(jié)介紹第二種方法。

我們將自定義的服務(wù)取名為BeanManagerService。

定義aidl

Binder默認(rèn)可以傳輸基本類型的數(shù)據(jù),如果要傳遞類對象,則這個類需要實(shí)現(xiàn)序列化。我們先定義一個序列化的自定義類型,用于binder間參數(shù)傳遞。主要分為兩步:

  1. 創(chuàng)建自定義類型,實(shí)現(xiàn)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. 創(chuàng)建aidl文件,如下:
// frameworks/base/core/java/android/bean/Person.aidl
package android.bean;

parcelable Person;

這樣就定義好了一個自定義對象類型,該類型可以通過binder傳遞,下面我們會有例子說明。

接下來我們定義自定義服務(wù),首先要定義一個aidl文件來定義我們的接口,這個aidl文件編譯后會生成binder的客戶端服務(wù)端接口,我們需要實(shí)現(xiàn)客戶端和服務(wù)端。

// bean為新建的文件夾,用于存放自定義服務(wù)
// 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標(biāo)識符
    // in:    表示參數(shù)只能由客戶端傳遞到服務(wù)端,基本類型默認(rèn)只支持in修飾符
    // out:   表示參數(shù)只能由服務(wù)端傳遞到客戶端,服務(wù)端如果修改了參數(shù)對象的值
    //        那么客戶端的值也會改變,但是服務(wù)端無法讀取客戶端對象的值
    // inout: 表示參數(shù)可以雙向傳遞
    void sayHelloTo(in Person person, String words);
}

由于下面的Android.bp已經(jīng)包含了該目錄下幾乎所有aidl文件和java文件的編譯,所以我們不需要再將自定義的BeanManager.aidl添加到編譯環(huán)境。

// 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: ["http://frameworks/base"],
}

用以下命令編譯aidl
source build/envsetup.sh
lunch sdk_car_x86_64-userdebug// 這里選擇自己的項(xiàng)目
make update-api
make framework -j16
編譯完成后,可以看到out下已經(jīng)生成了binder相關(guān)的文件
android 自定義系統(tǒng)服務(wù),Android系統(tǒng)開發(fā),android,java,開發(fā)語言

Server端實(shí)現(xiàn)

cd frameworks/base
mkdir -p services/core/java/com/android/server/bean/
新建BeanManagerService.java
編譯配置同上,不需要再單獨(dú)加到編譯配置中。

// 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) { }
    }

	// 這里我們定義了一個內(nèi)部類繼承SystemService,這樣便于方便system_server統(tǒng)一管理啟動服務(wù)
	// 系統(tǒng)啟動時會回調(diào)所有繼承了SystemService的類的函數(shù),比如onStart,onBootPhase等等。
    public static final class Lifecycle extends SystemService {
        static final String TAG = "BeanManagerService.Lifecycle";

        private BeanManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            // 在這里構(gòu)造我們的BeanManagerService對象
            mService = new BeanManagerService(context);
        }

        @Override
        public void onStart() {
            Log.d(TAG, "onStart");
            // 這里最終調(diào)用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();
            }
        }
    }
}

添加服務(wù)名稱

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

開機(jī)啟動服務(wù):

// frameworks/base/services/java/com/android/server/SystemServer.java
// 系統(tǒng)啟動時將服務(wù)分為幾個類型,如下,我們可以根據(jù)自己的具體業(yè)務(wù)添加到對應(yīng)的函數(shù)里面

try {
    t.traceBegin("StartServices");
    // 引導(dǎo)服務(wù),必須
    startBootstrapServices(t);
    // 核心服務(wù),必須
    startCoreServices(t);
    // 其他服務(wù),一般放在這里面
    startOtherServices(t);
    // 定義在apexes中的服務(wù)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");
			 // 這里最終會通過反射的方法調(diào)用BeanManagerService.Lifecycle的構(gòu)造函數(shù)
+            mSystemServiceManager.startService(BeanManagerService.Lifecycle.class);
+            t.traceEnd();
+
             t.traceBegin("StartKeyAttestationApplicationIdProviderService");
             ServiceManager.addService("sec_key_att_app_id_provider",
                     new KeyAttestationApplicationIdProviderService(context));

mSystemServiceManager.startService的實(shí)現(xiàn):

	// 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 {
            	// 調(diào)用構(gòu)造函數(shù),對于我們的自定義服務(wù)就是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列表
		// 系統(tǒng)的啟動過程會遍歷mServices列表,回調(diào)每個服務(wù)的對應(yīng)函數(shù)
        // Register it.
        mServices.add(service);

        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
        	// 這里就是調(diào)用每個服務(wù)的onStart函數(shù)
            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");
    }

到此,服務(wù)的添加代碼已經(jīng)完成,我們編譯驗(yàn)證一下:
// 因?yàn)镃ontext.java中新增了BEAN_SERVICE的API,所以要先make update-api
source build/envsetup.sh
lunch sdk_car_x86_64-userdebug
make update-api -j16
make -j16
啟動模擬器
emulator

這時發(fā)現(xiàn)服務(wù)無法啟動,看日志有如下報(bào)錯:

android 自定義系統(tǒng)服務(wù),Android系統(tǒng)開發(fā),android,java,開發(fā)語言

Selinux權(quán)限問題,我們根據(jù)日志按規(guī)則添加:
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服務(wù),就能立馬明白這里該如何添加。
如果按照上面的提示應(yīng)該是在system_server.te里添加allow system_server default_android_service:service_manager add;
但是這樣會觸發(fā)neverallow,正確的方法是為自定義的服務(wù)添加一個新的標(biāo)簽:

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


上述修改的文件大家根據(jù)自己項(xiàng)目添加到具體的文件中,也可以參考Android 13添加自定義native服務(wù)。
修改后重新編譯啟動驗(yàn)證

android 自定義系統(tǒng)服務(wù),Android系統(tǒng)開發(fā),android,java,開發(fā)語言
可以看到服務(wù)已經(jīng)正常啟動。
如果遇到修改selinux后開機(jī)還是報(bào)錯的情況,手動kill掉模擬器進(jìn)程再啟動模擬器。

Client端調(diào)用

Client調(diào)用實(shí)際上就是獲取binder的代理對象,然后通過代理對象調(diào)用服務(wù)端的方法。在Android系統(tǒng)中,為了方便App使用系統(tǒng)服務(wù)的功能,一般都會給每個服務(wù)定義一個XXXManager,App可以通過Context.getSystemService(serviceName)來獲取到經(jīng)過包裝的服務(wù)端的代理XXXManager。Context.getSystemService最終會調(diào)用到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,保存了每個服務(wù)的名稱和Manager的映射關(guān)系
        // ServiceFetcher是一個接口,有一個抽象方法T getService(ContextImpl ctx);
        // 這個getService返回的便是服務(wù)的代理包裝類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接口的實(shí)現(xiàn)有兩個,CachedServiceFetcher和StaticServiceFetcher,這兩個其實(shí)是兩個抽象類,都有一個抽象方法createService,而這個createService正式獲取服務(wù)端代理的真正實(shí)現(xiàn)。CachedServiceFetcher顧名思義就是將每個服務(wù)的代理對象都進(jìn)行緩存,下一次獲取的時候直接使用緩存的對象就可以了。

	// 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對象包含了一個保存服務(wù)代理的數(shù)組,每添加一個代理,也就是每創(chuàng)建一個CachedServiceFetcher,
            // sServiceCacheSize便會遞增,而每個CachedServiceFetcher中的mCacheIndex則是自己在整個數(shù)組中的index。
            // 后續(xù)獲取服務(wù)代理時,如果cache中有數(shù)據(jù),則直接根據(jù)mCacheIndex獲取即可。
            mCacheIndex = sServiceCacheSize++;
        }

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
        	//獲取Context中的保存服務(wù)代理的數(shù)組mServiceCache
            final Object[] cache = ctx.mServiceCache;
            // final int[] mServiceInitializationStateArray = new int[mServiceCache.length];
            // mServiceInitializationStateArray是一個以mServiceCache.length為size的int數(shù)組,用于
            // 保存每個服務(wù)代理的狀態(tài),目前有四種狀態(tài):
            // 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.
                    // 先根據(jù)mCacheIndex獲取,如果不為null,說明之前已經(jīng)保存過,直接返回。
                    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.
                    // 走到這里說明緩存中沒有保存代理對象
                    // 但是狀態(tài)卻是(STATE_READY),說明之前是添加過的,但是現(xiàn)在找不到了,說明被誰從數(shù)組中移除了
                    // 或者狀態(tài)是找不到(STATE_NOT_FOUND)
                    // 那么就將狀態(tài)重置為STATE_UNINITIALIZED,重新再往cache數(shù)組添加一次
                    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.
                    // 這里在往代理服務(wù)數(shù)組中添加新數(shù)據(jù)之前,先把狀態(tài)設(shè)置為STATE_INITIALIZING
                    if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
                        doInitialize = true;
                        gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
                    }
                }

                if (doInitialize) {
                    // Only the first thread gets here.
					// 接下來就要真正的保存服務(wù)代理到數(shù)組中了
                    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獲取到服務(wù)代理對象,前面說過createService是一個抽象方法,
                    	// 說明有子類實(shí)現(xiàn)的地方,后面會講到
                        service = createService(ctx);
                        newState = ContextImpl.STATE_READY;

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

                    } finally {
                        synchronized (cache) {
                        	//如果createService沒有異常的話,將代理服務(wù)保存到cache數(shù)組
                        	// 將狀態(tài)設(shè)置為newState, newState在前面設(shè)置為了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.
                    // 如果服務(wù)代理正在添加過程中,還沒有添加完成時,又有一個新的線程來getSystemService,則會
                    // 進(jìn)去wait狀態(tài),等待服務(wù)代理對象添加完成后執(zhí)行notifyAll來喚醒當(dāng)前線程
                    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則是服務(wù)代理中不需要Context對象的一種實(shí)現(xiàn),也就是創(chuàng)建XXXManager對象時不需要
	// 傳入Context參數(shù)
    /**
     * 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都需要實(shí)現(xiàn)createService的抽象方法,我們的自定義服務(wù)代理對象BeanManager假設(shè)需要傳入Context對象,則需要使用CachedServiceFetcher。

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

registerService(Context.BEAN_SERVICE, BeanManager.class,
	// 這里是CachedServiceFetcher抽象類的實(shí)現(xiàn)
    new CachedServiceFetcher<BeanManager>() {
    // 抽象方法createService的實(shí)現(xiàn),我們看到其實(shí)很簡單,就是通過ServiceManager獲取服務(wù)的binder代理對象
	@Override
	public BeanManager createService(ContextImpl ctx) throws ServiceNotFoundException {
	    IBinder b = ServiceManager.getServiceOrThrow(Context.BEAN_SERVICE);
	    IBeanManager service = IBeanManager.Stub.asInterface(b);
	    // 以IBeanManager和Context為參數(shù)構(gòu)造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();
          }
      }
}

到此,我們的服務(wù)代理就添加完成了。我們調(diào)用BeanManager測試一下,我們添加到Launcher里,開機(jī)加載
Launcher時就會調(diào)用。

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

編譯后重啟服務(wù)器,看到如下日志說明調(diào)用成功:文章來源地址http://www.zghlxwxcb.cn/news/detail-691083.html

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!

到了這里,關(guān)于Android 13添加自定義Java系統(tǒng)服務(wù)(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android13系統(tǒng)導(dǎo)航欄添加隱藏導(dǎo)航欄功能按鈕

    Android13系統(tǒng)導(dǎo)航欄添加隱藏導(dǎo)航欄功能按鈕

    最近有個項(xiàng)目,客戶要求在底部導(dǎo)航欄中添加一個可以隱藏整個導(dǎo)航欄的功能按鈕,效果如下圖: 具體方法如下: 1. 在frameworks/base做如下修改: 2. 上面修改中有一行代碼android:src=\\\"@drawable/ic_sysbar_hide\\\"引用了一個ic_sysbar_hide.xml文件,該文件內(nèi)容如下:其實(shí)就是那個隱藏按鈕的

    2024年04月23日
    瀏覽(99)
  • android 13.0 添加系統(tǒng)字體并且設(shè)置為默認(rèn)字體

    在13.0系統(tǒng)定制化開發(fā)中,在產(chǎn)品定制中,有產(chǎn)品需求對于系統(tǒng)字體風(fēng)格不太滿意,所以想要更換系統(tǒng)的默認(rèn)字體,對于系統(tǒng)字體的修改也是常有的功能,而系統(tǒng)默認(rèn)也支持增加字體,所以就來添加楷體字體為系統(tǒng)字體,并替換為系統(tǒng)默認(rèn)字體, 接下來就來分析下替換默認(rèn)字

    2024年02月22日
    瀏覽(130)
  • 【Android13開發(fā)WIFI添加頻段設(shè)置項(xiàng)(2.4G/5G/automatic)更改筆記】

    【Android13開發(fā)WIFI添加頻段設(shè)置項(xiàng)(2.4G/5G/automatic)更改筆記】

    提示:這里簡述項(xiàng)目相關(guān)背景: Android13中客戶需求添加WIFI頻段選項(xiàng): 2.4G only,只顯示鏈接2.4G的AP。 5G only,只能顯示和鏈接5G的AP。 Automatic:自動顯示,即全部正常顯示。 提示:這里描述項(xiàng)目中遇到的問題: 作為初學(xué)者的我,剛開始接到這個bug,還是比較懵的,多虧了CSDN的前輩

    2024年02月05日
    瀏覽(21)
  • Android 14.0 添加自定義服務(wù),并生成jar給第三方app調(diào)用

    在14.0系統(tǒng)ROM產(chǎn)品定制化開發(fā)中,由于需要新增加自定義的功能,所以要增加自定義服務(wù),而app上層通過調(diào)用自定義服務(wù),來調(diào)用相應(yīng)的功能,所以系統(tǒng)需要先生成jar,然后生成jar 給上層app調(diào)用,接下來就來分析實(shí)現(xiàn)的步驟,然后來實(shí)現(xiàn)相關(guān)的功能 從而來實(shí)現(xiàn)所需要的功能 在

    2024年04月10日
    瀏覽(105)
  • Android java項(xiàng)目添加kotlin混合開發(fā)環(huán)境配置

    Android Studio java代碼中添加kotlin混合開發(fā) 1.項(xiàng)目的build.gradle中添加kotlin-gradle-plugin buildscript { ? ? repositories { ? ? ? ? google() ? ? ? ? jcenter() ? ? ? ?? ? ? } ? ? dependencies { ? ? ? ? classpath \\\'com.android.tools.build:gradle:7.3.1\\\' ? ? ? ? classpath \\\"org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20\\\"

    2023年04月19日
    瀏覽(24)
  • android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer

    android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer

    官方注釋: 給可以直接持有窗口的自己或它的孩子定義了一些公共的方法和屬性,像RootWindowContainer、DisplayContent、DisplayArea、DisplayArea.Tokens、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState都是直接或間接的繼承該類。 這里面主要的重要要成員變量就是mParent和mChildren,一

    2024年02月16日
    瀏覽(24)
  • android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié)

    android 13 WMS/AMS系統(tǒng)開發(fā)-窗口層級相關(guān)DisplayArea,WindowContainer第二節(jié)

    接著上一節(jié)課學(xué)習(xí),我們已經(jīng)清楚的知道了層級結(jié)構(gòu)應(yīng)該怎么看,根據(jù)dumpsys的輸出可以完美復(fù)原出層級結(jié)構(gòu)樹,也理解了結(jié)構(gòu)樹對于層級結(jié)構(gòu)的控制作用。但還沒有從源碼部分對這個結(jié)構(gòu)樹進(jìn)行一個分析,即分析生成這個結(jié)構(gòu)樹的源碼部分。 結(jié)下來調(diào)用是實(shí)現(xiàn)類DefaultProvid

    2024年02月15日
    瀏覽(20)
  • android h5 宿舍報(bào)修管理系統(tǒng)myeclipse開發(fā)mysql數(shù)據(jù)庫編程服務(wù)端java計(jì)算機(jī)程序設(shè)計(jì)

    android h5 宿舍報(bào)修管理系統(tǒng)myeclipse開發(fā)mysql數(shù)據(jù)庫編程服務(wù)端java計(jì)算機(jī)程序設(shè)計(jì)

    一、源碼特點(diǎn) ? android h5 宿舍報(bào)修管理系統(tǒng)是一套完善的WEB+android設(shè)計(jì)系統(tǒng),對理解JSP java,安卓app編程開發(fā)語言有幫助(系統(tǒng)采用web服務(wù)端+APP端 綜合模式進(jìn)行設(shè)計(jì)開發(fā)),系統(tǒng)具有完整的 源代碼和數(shù)據(jù)庫,系統(tǒng)主要采用B/S模式開發(fā)。 二、功能介紹 本系統(tǒng)的最終用戶為學(xué)生

    2024年02月12日
    瀏覽(28)
  • android 13.0 SystemUI狀態(tài)欄下拉快捷添加截圖快捷開關(guān)

    在13.0的系統(tǒng)產(chǎn)品rom定制化開發(fā)中,對SystemUI的定制需求也是挺多的,在下拉狀態(tài)欄中 添加截圖快捷開關(guān),也是常有的開發(fā)功能,下面就以添加 截圖功能為例功能的實(shí)現(xiàn) 在Systemui的下拉狀態(tài)欄的相關(guān)源碼中,在快捷設(shè)置區(qū)域QSPanel及點(diǎn)擊事件流程 分析 SystemUI下拉之后的那些快捷

    2024年02月03日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包