天天看點

Android 擷取系統服務的源代碼分析

寫這篇部落格之前,我内心是有些猶豫的,因為不知道能不能對Android 裡面的源代碼進行細緻的分析,但由于最近幾天,一直在思考,之前學習Android 的路線,無外乎就是完成一些Android 的一些功能,以及Android UI上的一些改動。似乎好像,還沒有認真仔細的去研讀Android的源代碼,總是走馬觀花,不夠耐心。現在做一個小嘗試,開始細心研究Android源代碼,算是我Android 道路上的一個轉折點吧,從此篇部落格開始,以後陸陸續續更新我對Android 源代碼的一些細緻分析了解,并以此篇部落格為證!!!開始我的Android 新篇章!

話不多說,開始今天Android 源代碼的分析!

在Android系統中,我們會經常通過Context擷取系統級别的服務,如WindowsManagerService,ActivityManagerService等,更常用的是一個LayoutInflater的類,這些服務都是以單例的形式注冊在系統中,在我們需要的時候就會通過Context.getSystemService(String name)擷取,我們先就以LayoutInflater為例來說明。

View view = LayoutInflater.from(activity).inflate(layoutResId, guideLayout, false);
           

我們或多或少都寫過這一段代碼,在ListView的getView的方法中會經常用到,以及在别的地方,加載資源檔案給自定義的View上時,也會用到。

現在就開始一段一段分析:

1.LayoutInflater.from(activity)該方法進去一看Android 的源碼

/**
     * Obtains the LayoutInflater from the given context.
     */
    public static LayoutInflater from(Context context) {
        LayoutInflater LayoutInflater =
                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (LayoutInflater == null) {
            throw new AssertionError("LayoutInflater not found.");
        }
        return LayoutInflater;
    }
           

進入源碼中,我們就會看到LayoutInflater LayoutInflater =

(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 這樣一行代碼!

我們再來分析Context這個類中的getSystemService()方法,就得去Context該類中探探究竟了!

* up-calls for application-level operations such as launching activities,
 * broadcasting and receiving intents, etc.
 */
public abstract class Context {
    /**
     * File creation mode: the default mode, where the created file can only
     * be accessed by the calling application (or all applications sharing the
     * same user ID).
     */
    public static final int MODE_PRIVATE = ;

    /**
     * File creation mode: allow all other applications to have read access to
     * the created file.
     * <p>
     * As of {@link android.os.Build.VERSION_CODES#N} attempting to use this
     * mode will throw a {@link SecurityException}
           

進入Context中,我們首先會發現,這是個抽象類,記得曾經有人說過,抽象類就要去看抽象方法,一般隻有抽象方法需要子類去繼承實作的方法,會顯得很重要!

果然Context.getSystemService()是個抽象方法,以源代碼為例:

* @see android.app.usage.NetworkStatsManager
     * @see android.os.HardwarePropertiesManager
     * @see #HARDWARE_PROPERTIES_SERVICE
     */
    public abstract Object getSystemService(@ServiceName @NonNull String name);

    /**
     * Return the handle to a system-level service by class.
     * <p>
           

既然這個getSystemService()是個Context抽象類中的抽象方法,那麼我們就得去看Context的實作類去看看該方法是怎麼實作的,Let’s Go!

/**
 * Common implementation of Context API, which provides the base
 * context object for Activity and other application components.
 */
class ContextImpl extends Context {
    private final static String TAG = "ContextImpl";
    private final static boolean DEBUG = false;

    /**
     * Map from package name, to preference name, to cached preferences.
     */
    @GuardedBy("ContextImpl.class")
    private static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;

    /**
     * Map from preference name to generated path.
     */
    @GuardedBy("ContextImpl.class")
    private ArrayMap<String, File> mSharedPrefsPaths;

    final ActivityThread mMainThread;
    final LoadedApk mPackageInfo;
           

從這段代碼中,我們可以看出ContextImpl類是Context的實作類,那麼我們就去找找,他的getSystemService()的實作吧!

@Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

    @Override
    public String getSystemServiceName(Class<?> serviceClass) {
        return SystemServiceRegistry.getSystemServiceName(serviceClass);
    }
           

該類中有兩個方法,一個擷取系統服務對象,一個擷取系統服務對象的名稱,但這都不是重點,重點是又進入另一個類中的getSystemService()方法中!

return SystemServiceRegistry.getSystemService(this, name);
           

現在就去SystemServiceRegistry該類看看吧!

/**
 * Manages all of the system services that can be returned by {@link Context#getSystemService}.
 * Used by {@link ContextImpl}.
 */
final class SystemServiceRegistry {
    private final static String TAG = "SystemServiceRegistry";

    // Service registry information.
    // This information is never changed once static initialization has completed.
    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;

    // Not instantiable.
    private SystemServiceRegistry() { }
           

從Android 源代碼中發現該類是一個final 類,終于知道getSystemService()方法的具體實作肯定的在這個類中完成!

我們先看看該類的類結構:

Android 擷取系統服務的源代碼分析

看到該類中有getSystemService()的具體實作,不過我們先不急,先看看整個類的架構,發現其中有一個ServiceFetcher接口以及它的三個實作類,還有一個static 代碼塊,以及一些方法以及兩個HashMap的Field屬性。

先看看static 代碼塊吧:

// Not instantiable.
    private SystemServiceRegistry() { }

    static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});

        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
                new CachedServiceFetcher<CaptioningManager>() {
            @Override
            public CaptioningManager createService(ContextImpl ctx) {
                return new CaptioningManager(ctx);
            }});

        registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                new CachedServiceFetcher<AccountManager>() {
            @Override
            public AccountManager createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);
                IAccountManager service = IAccountManager.Stub.asInterface(b);
                return new AccountManager(ctx, service);
            }});
           

檢視該靜态代碼塊,是因為靜态代碼塊,第一次加載該類時執行(而且隻會執行一次,保證了執行個體的唯一性),其次就是我們會發現static 代碼塊中有很多個這樣的方法:

registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});
           

隻是參數不同,第一個參數 就是服務的String值,第二個參數,該服務牽扯到的類名,第三個參數為ServiceFetcher 接口的實作類。

registerService(…)方法的實作

/**
     * Statically registers a system service with the context.
     * This method must be called during static initialization only.
     */
    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
           

裡面主要是利用HashMap (SYSTEM_SERVICE_NAMES和SYSTEM_SERVICE_FETCHERS)将該系統服務的服務名和serviceFetcher保留到HashMap中。

registerService方法有兩個參數,第一個參數就是服務的名稱,第二個參數就是建立的一個ServiceFetcher對象。這個過程可以這麼了解,為了生産服務,我建立了一個工廠(ServiceFetcher),然後我告訴了工廠怎麼生産這個對象(重載createService()方法)。這樣,當我需要服務的時候,工廠就能夠生産我需要的服務(通過createService()方法)。

registerService方法的引用:

Android 擷取系統服務的源代碼分析
Android 擷取系統服務的源代碼分析

看到這兩張圖,聰明的同學大概一下就猜到registerService()方法的意圖了吧,沒錯就是注冊所有的系統服務,将所有系統提供的XXXManager()注冊之後,然後以供調用!

好,現在去看該類的getSystemService()方法

/**
     * Gets a system service from a given context.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    /**
     * Gets the name of the system-level service that is represented by the specified class.
     */
    public static String getSystemServiceName(Class<?> serviceClass) {
        return SYSTEM_SERVICE_NAMES.get(serviceClass);
    }
           

擷取系統服務的方法中的代碼主要就是,通過SYSTEM_SERVICE_FETCHERS(該HashMap)根據之前儲存進來的系統服務名(name) ,通過該key來擷取之前儲存的ServiceFetcher對象。

return fetcher != null ? fetcher.getService(ctx) : null;
           

進去fecther.getService(ctx)方法中可以看到

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

這是一個interface ServiceFetcher該接口中的方法,得去看子類的實作比如

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

        public CachedServiceFetcher() {
            mCacheIndex = sServiceCacheSize++;
        }

        @Override
        @SuppressWarnings("unchecked")
        public final T getService(ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized (cache) {
                // Fetch or create the service.
                Object service = cache[mCacheIndex];
                if (service == null) {
                    service = createService(ctx);
                    cache[mCacheIndex] = service;
                }
                return (T)service;
            }
        }

        public abstract T createService(ContextImpl ctx);
    }
           

因為

if (service == null) {

service = createService(ctx);

cache[mCacheIndex] = service;

}

return (T)service;

是以我們又得去看該類中的一個抽象方法 public abstract T createService(ContextImpl ctx);

而createService恰好該方法的實作在registerService()方法中,進行了初始化,舉個例子

registerService(Context.MEDIA_PROJECTION_SERVICE, MediaProjectionManager.class,
                new CachedServiceFetcher<MediaProjectionManager>() {
            @Override
            public MediaProjectionManager createService(ContextImpl ctx) {
                return new MediaProjectionManager(ctx);
            }});
           

因為在這裡實作了ServiceFetcher該接口,是以也就重寫了createService()該方法,是以也就擷取了系統服務,并且具體的怎樣的系統服務,就得看你傳哪個系統服務名(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);),然後在SystemServiceRegistry類中hashMap進行緩存了,并且最終在注冊服務(registerService)中實作ServiceFetcher接口,并且重寫createService()方法,進而就可以擷取系統服務了!

由于部落客第一次寫Android 的源代碼分析,寫的不好的地方,以及排版不好的地方,還請多多見諒,以後一定會優化的!