Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中的系統服務(代理模式)

Android中的系統服務(代理模式)

編輯:關於Android編程

一,系統啟動

Android設備的開機流程總得來分可以分為三部分:
這裡寫圖片描述

加載引導程序

引導程序bootloader是開機運行的第一個小程序,因此它是針對特定的主板與芯片的。bootloader有很多種,可以使用比較流行的如redboot、uboot、ARMBoot等,也可以開發自己的引導程序,它不是Android操作系統的一部分。引導程序也是OEM廠商或者運營商加鎖和限制的地方。

引導程序初始化硬件設備、創建存儲器空間的映射等軟件運行時所需要的最小環境;加載Linux內核鏡像文件(本文只針對Android、Linux)到RAM中某個地址處執行,此時引導程序的控制權就交給了內核。這些對於運行內核是必要的,為了達到特殊的目標,引導程序可以根據配置參數或者輸入數據設置內核。

說明:加電後,CPU將先執行bootloader程序,此處有三種選擇:
a) 啟動到fastboot,即命令或SD卡燒寫模式,不加載內核及文件系統,此處可以進行工廠模式的燒寫
b) 啟動到recovery模式,加載recovery.img,recovery.img包含內核,基本的文件系統,用於工程模式的燒寫
c) 開機按Power,正常啟動系統,加載boot.img,boot.img包含內核,基本文件系統,用於正常啟動手機(以下只分析正常啟動的情況)

推薦閱讀:[Android系統啟動流程 – bootloader]

啟動Linux內核(kernel)

內核啟動時,設置緩存、被保護存儲器、計劃列表,加載驅動等系統內部初始化工作。然後內核會尋找並執行”init”文件,創建init進程作為系統的第一個進程。推薦閱讀:[Android系統啟動流程 – linux kernel]

Android啟動

init進程是Linux內核啟動之後啟動的第一個用戶級進程,Android的啟動也是在這個進程的基礎上開始的,進程號為1。如果是正常啟動init會讀取並解析init.rc文件,對於init.rc文件,Android中有特定的格式以及規則。在Android中,叫做Android初始化語言。讀取解析文件的時,是以行為最小可執行單位解析。解析之後並不會馬上執行,而是在init進入服務循環之前統一根據其命令本身所帶的條件來執行。
推薦閱讀:[Android的init過程詳解 ]

二,啟動系統服務

啟動守護進程

init進程會讀取init.rc中的service並按照順序啟動它們,它們是Android的守護進程,比如:
log守護進程(log Daemon):

service logd /system/bin/logd
    class core
    socket logd stream 0666 logd logd
    socket logdr seqpacket 0666 logd logd
    socket logdw dgram 0222 logd logd
    seclabel u:r:logd:s0

adb守護進程:

service adbd /sbin/adbd --root_seclabel=u:r:su:s0
    class core
    socket adbd stream 660 system system
    disabled
    seclabel u:r:adbd:s0

servicemanager:

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

Network守護進程:

service netd /system/bin/netd
    class main
    socket netd stream 0660 root system
    socket dnsproxyd stream 0660 root inet
    socket mdns stream 0660 root system
    socket fwmarkd stream 0660 root inet

surfaceflinger:

service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc
    onrestart restart zygote

media:

service media /system/bin/mediaserver
    class main
    user media
    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm qcom_diag
    ioprio rt 4

開機動畫:

service bootanim /system/bin/bootanimation
    class main
    user root
    group graphics audio
    disabled
    oneshot

關機動畫:

service shutdownanim /system/bin/shutdownanimation
    class main
    user root
    group graphics audio
    disabled
    oneshot

安裝程序:

service installd /system/bin/installd
    class main
    socket installd stream 600 system system

flash恢復:

service flash_recovery /system/bin/install-recovery.sh
    class main
    seclabel u:r:install_recovery:s0
    oneshot

守護進程是最底層的服務,他們的通信方式是socket。ServiceManager用來管理系統中所有的binder service,不管是本地的c++實現的還是java語言實現的都需要這個進程來統一管理,最主要的管理就是,注冊添加服務,獲取服務。所有的Service使用前都必須先在servicemanager中進行注冊。
當啟動servicemanager時,會啟動 zygote,surfaceflinger等。Zygote這個進程是非常重要的一個進程,注冊Zygote Socket服務端套接字;加載虛擬機;預加載Android核心類;預加載系統資源:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
    onrestart setprop sys.android.reboot 1

啟動系統服務

zygote中會啟動Xzygote和system-server,從SystemServer開始就是啟動系統服務了:
啟動SystemServer:

namespace android {

static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // 啟動傳感器服務
        SensorService::instantiate();
    }
}

/*
 * JNI registration.
 */
static const JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
};

int register_android_server_SystemServer(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/server/SystemServer",
            gMethods, NELEM(gMethods));
}

}; // namespace android

com/android/server/SystemServer:

/**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitBeforeStartServices");//跟蹤器開始跟蹤
            // 如果設備的時鐘是 1970以前 (在 0以前), 很多API會發生異常, 
            // 特別是java.io.File#setLastModified, 
            // 所以我們假冒一個並且希望會很快獲取時間.
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }

            // 如果系統有 "persist.sys.language" 和好友設置, 用"persist.sys.locale"代替它。
            // 使用"-Duser.locale"命令記住默認的本地適當的時候 . 
            // 這個命令在AndroidRuntime 也用在設置系統屬性, 
            // 但只有系統服務器和系統apps 呗允許設置他們.
            //
            // 注意: Most changes made here will need an equivalent change to
            // core/jni/AndroidRuntime.cpp
            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();

                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            }

            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

            // In case the runtime switched since last boot (such as when
            // the old runtime was removed in an OTA), set the system
            // property so that it is in sync. We can't do this in
            // libnativehelper's JniInvocation::Init code where we already
            // had to fallback to a different runtime because it is
            // running as root and we need to be the system user to set
            // the property. http://b/11463182
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

            // 啟用采樣分析器.
            if (SamplingProfilerIntegration.isEnabled()) {
                SamplingProfilerIntegration.start();
                mProfilerSnapshotTimer = new Timer();
                mProfilerSnapshotTimer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            SamplingProfilerIntegration.writeSnapshot("system_server", null);
                        }
                    }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
            }

            // Mmmmmm... more memory!好多內存
            VMRuntime.getRuntime().clearGrowthLimit();

            // 系統服務會一直運行,所以需要他的內存也一直有效.
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            //一些設備依賴 runtime 指紋生成, 所以在啟動前確保我們已經聲明了它.
            Build.ensureFingerprintProperty();

            //在系統服務器中,沒有明確指定用戶的訪問環境路徑是一個錯誤.
            Environment.setUserRequired(true);

            // 確保傳進系統的binder總是以前台優先權運行.
            BinderInternal.disableBackgroundScheduling(true);

            // 准備 main looper thread (這個 thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();

            // //加載android_servers.so庫.
            System.loadLibrary("android_servers");

            // 檢查上一次關機是否失敗.
            // 可以沒有返回值.
            performPendingShutdown();

            // 初始化系統context.
            createSystemContext();

            // 創建 system service manager對象,添加到本地服務中
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);跟蹤器結束跟蹤
        }

        // 啟動 services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");//跟蹤器開始跟蹤
            startBootstrapServices();//啟動引導服務
            startCoreServices();//啟動核心服務
            startOtherServices();//啟動其他服務
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

        // 一直Loop .
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

從上面可以看出,先是初始化系統context,然後啟動SystemServiceManager,再然後就是啟動BootstrapServices,CoreServices,OtherServices。BootstrapServices是讓系統啟動的並且會相互影響的關鍵服務,第一個就是ActivityManagerService:

/**啟動引導服務
     * 啟動相互影響的關鍵服務 that 讓系統開始啟動
     * 這些服務有復雜的相互依賴關系,這就是為什麼我們把它們都放在這一個地方
     *  除非你的服務也和這些依賴關系有纏繞,它應該是在另一個功能裡的進行初始化.
     */
    private void startBootstrapServices() {
        // 等待installd to 完成啟動 ,所以它有一次機會去創建關鍵目錄,和相關權限。比如/data/user
        // 我們需要這個來完成之前我們初始化的其他服務。
        Installer installer = mSystemServiceManager.startService(Installer.class);//安裝程序,程序安裝器

        // 這個由Activity manager 運行.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);//設置系統服務管理器
        mActivityManagerService.setInstaller(installer);//設置安裝程序

        // Power manager需要很早啟動,因為其他服務需要他.
        // 本地守護進程可以監聽到他被注冊,所以他必須時刻准備著處理傳進的binder。
        // (包括能夠驗證這些調用的權限).
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 現在這個power manager 已經啟動了,讓activity manager初始化power management功能.
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitPowerManagement");
        mActivityManagerService.initPowerManagement();
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

        // 管理LEDs 和 display backlight 所以我們需要他 to bring up the display.
        mSystemServiceManager.startService(LightsService.class);

        // Display manager需要用來提供顯示度量值 在package manager啟動前。
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        //我們需要默認的display,在我們可以初始化package manager之前.
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        //如果我們加密了設備,只運行"core" apps.   decrypt:加密
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }

        // 啟動package manager.
        traceBeginAndSlog("StartPackageManagerService");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);//啟動PackageManagerService
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();//獲取PackageManager
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

        //用戶服務添加到服務管理器中
        traceBeginAndSlog("StartUserManagerService");
        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

        // 初始化用於緩存包中資源的緩存屬性.
        AttributeCache.init(mSystemContext);

        // 為系統進程構建應用實例並且啟動.
        mActivityManagerService.setSystemProcess();

        //傳感器服務需要訪問包管理器服務、應用程序ops服務和權限服務,因此,我們在他們之後啟動它。
        startSensorService();
    }

接著啟動一些必要的相對獨立的系統服務:

/**
     * 啟動一些必要的,沒和bootstrap 過程中的糾纏 ,的服務.
     */
    private void startCoreServices() {
        // 跟蹤電池電量.  要求LightService.
        mSystemServiceManager.startService(BatteryService.class);

        //跟蹤應用程序使用統計.
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        //  UsageStatsService有效後更新, 需要在performBootDexOpt之前.
        mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

        //跟蹤可更新的WebView 是否處於就緒狀態 並且監視更新安裝
        mSystemServiceManager.startService(WebViewUpdateService.class);
    }

最後啟動其他所有的服務:

/**啟動其他五花八門還沒有重構和組織的服務
     * .
     */
    private void startOtherServices() {
        final Context context = mSystemContext;
        AccountManagerService accountManager = null;
        ContentService contentService = null;
        VibratorService vibrator = null;
        IAlarmManager alarm = null;
        IMountService mountService = null;
        NetworkManagementService networkManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        NetworkScoreService networkScore = null;
        NsdService serviceDiscovery= null;
        WindowManagerService wm = null;
        UsbService usb = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        CommonTimeManagementService commonTimeMgmtService = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        AudioService audioService = null;
        MmsServiceBroker mmsService = null;
        EntropyMixer entropyMixer = null;
        CameraService cameraService = null;

        boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
        boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
        boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
        boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
        boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
        boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
        boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
        boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");

        try {
            Slog.i(TAG, "Reading configuration...");//打印“讀取配置。。。”
            SystemConfig.getInstance();//獲取SystemConfig對象

            traceBeginAndSlog("StartSchedulingPolicyService");
            ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());//調度策略
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

         ...略

        StatusBarManagerService statusBar = null;//狀態條
        INotificationManager notification = null;//通知
        InputMethodManagerService imm = null;//輸入工具
        WallpaperManagerService wallpaper = null;//壁紙
        LocationManagerService location = null;//位置
        CountryDetectorService countryDetector = null;//國家
        TextServicesManagerService tsms = null;//text
        LockSettingsService lockSettings = null;//鎖屏設置
        AssetAtlasService atlas = null;//資產阿特拉斯
        MediaRouterService mediaRouter = null;//媒體路由

        // Bring up services needed for UI.
        if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            traceBeginAndSlog("StartInputMethodManagerService");
            try {
                imm = new InputMethodManagerService(context, wm);
                ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
            } catch (Throwable e) {
                reportWtf("starting Input Manager Service", e);
            }
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

            traceBeginAndSlog("StartAccessibilityManagerService");
            try {
                ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
                        new AccessibilityManagerService(context));
            } catch (Throwable e) {
                reportWtf("starting Accessibility Manager", e);
            }
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        try {
            wm.displayReady();
        } catch (Throwable e) {
            reportWtf("making display ready", e);
        }

        ...略

        // These are needed to propagate to the runnable below.
        final NetworkManagementService networkManagementF = networkManagement;
        final NetworkStatsService networkStatsF = networkStats;
        final NetworkPolicyManagerService networkPolicyF = networkPolicy;
        final ConnectivityService connectivityF = connectivity;
        final NetworkScoreService networkScoreF = networkScore;
        final WallpaperManagerService wallpaperF = wallpaper;
        final InputMethodManagerService immF = imm;
        final LocationManagerService locationF = location;
        final CountryDetectorService countryDetectorF = countryDetector;
        final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
        final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
        final TextServicesManagerService textServiceManagerServiceF = tsms;
        final StatusBarManagerService statusBarF = statusBar;
        final AssetAtlasService atlasF = atlas;
        final InputManagerService inputManagerF = inputManager;
        final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
        final MediaRouterService mediaRouterF = mediaRouter;
        final AudioService audioServiceF = audioService;
        final MmsServiceBroker mmsServiceF = mmsService;

        // We now tell the activity manager it is okay to run third party
        // code.  It will call back into us once it has gotten to the state
        // where third party code can really run (but before it has actually
        // started launching the initial applications), for us to complete our
        // initialization.
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PhaseActivityManagerReady");

                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartObservingNativeCrashes");
                try {
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

                Slog.i(TAG, "WebViewFactory preparation");
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WebViewFactoryPreparation");
                WebViewFactory.prepareWebViewInSystemServer();
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartSystemUI");
                try {
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeMountServiceReady");
                try {
                    if (networkScoreF != null) networkScoreF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Score Service ready", e);
                }
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

                。。。略

                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        });
    }
//啟動系統UI
    static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
    }

在不同的進程中運行的系統服務之間的通信方式為Binder。

系統服務啟動的方式

觀察上面的啟動服務的代碼,最普遍的有三種方式啟動系統服務,比如:

//通過SystemServiceManager.startService進行啟動:
mSystemServiceManager.startService(TelecomLoaderService.class);//傳入類名

private static final String WIFI_SERVICE_CLASS =
            "com.android.server.wifi.WifiService";
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);//傳入字符串

//通過ServiceManager.addService啟動:

networkManagement = NetworkManagementService.create(context);
                    ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);//傳入Context中定義的變量名,服務

vibrator = new VibratorService(context);
            ServiceManager.addService("vibrator", vibrator);//傳入字符串,服務
//其他:
 if (audioServiceF != null) audioServiceF.systemReady();
 if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();

SystemServiceManager.startService()

SystemServiceManager是一個管理com.android.server.SystemService 系統服務創建,啟動,和一些生命周期事件的類。

先看SystemServiceManager.startService方法,此方法名有兩個個方法體,一個出入參數為字符串,一個傳入參數為Class類名,方法分別如下:

/**
     * 通過類名啟動一個服務.
     *
     * @return 服務對象.
     */
    @SuppressWarnings("unchecked")
    public SystemService startService(String className) {
        final Class serviceClass;//SystemService子類
        try {
            serviceClass = (Class)Class.forName(className);//返回的是一個類,作用是要求JVM查找並加載指定的類
        } catch (ClassNotFoundException ex) {
            Slog.i(TAG, "Starting " + className);
            throw new RuntimeException("Failed to create service " + className
                    + ": service class not found, usually indicates that the caller should "
                    + "have called PackageManager.hasSystemFeature() to check whether the "
                    + "feature is available on this device before trying to start the "
                    + "services that implement it", ex);
        }
        return startService(serviceClass);//再執行下面的startService方法,並返回值
    }
    // Services that 應該接受生命周期事件.
    private final ArrayList mServices = new ArrayList();

    /**
     * 創建和啟動一個系統服務. 
     * 這個類必須是{@link com.android.server.SystemService}的子類.
     *
     * @param serviceClass 實現SystemService接口的java類.
     * @return 返回服務對象,不可以為null.
     * @throws RuntimeException 啟動失敗拋出異常.
     */
    @SuppressWarnings("unchecked")
    public  T startService(Class serviceClass) {
        try {
            final String name = serviceClass.getName();//獲得類的名字
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);

            // 創建service對象.
            //isAssignableFrom是用來判斷一個類Class1和另一個類Class2是否相同或是另一個類的超類或接口
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());//服務必須extendSystemService
            }
            final T service;
            try {
                Constructor 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);
            }

            // Register it.
            mServices.add(service);//注冊服務,添加到ArrayList mServices中

            // 啟動服務.
            try {
                service.onStart();
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;//返回服務
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

可以看出這兩個方法執行的系統服務類都是SystemService的子類。在第二個方法中,先是判斷這個服務是不是SystemService的子類,,然後我們創建服務的對象,再通過添加到服務列表添加到ArrayList mServices中,並且同時通過調用SystemService.onStart()方法對這個啟動的服務進行相關配置。onStart()方法由SystemService的子類實現,就是啟動哪個服務就調用哪個服務類裡的onStart()方法,比如BatteryService服務類:

@Override
    public void onStart() {
        IBinder b = ServiceManager.getService("batteryproperties");//獲取屬性配置
        final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
                IBatteryPropertiesRegistrar.Stub.asInterface(b);
        try {
            batteryPropertiesRegistrar.registerListener(new BatteryListener());//注冊電量監聽
        } catch (RemoteException e) {
            // Should never happen.
        }

        publishBinderService("battery", new BinderService());
        publishLocalService(BatteryManagerInternal.class, new LocalService());
    }

然而我們此時可以發現SystemServiceManager.startService方法只是加載了系統服務,並沒有啟動,仔細閱讀SystemServer類我們會發現,代碼每執行一段後會執行如下方法:

 mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

startBootPhase方法作用是啟動執行到這兒的這一階段的所有系統服務,參數為SystemService中定義的常量:

    /*
     * 開機階段
     */
    public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; 

    /**
     * 到了這兒, 可以接受鎖屏狀態下的數據.
     */
    public static final int PHASE_LOCK_SETTINGS_READY = 480;

    /**
     * 到了這兒, 服務可以安全的和核心系統服務交互.
     */
    public static final int PHASE_SYSTEM_SERVICES_READY = 500;

    /**
     *到了這兒,服務可以接受廣播Intents.
     */
    public static final int PHASE_ACTIVITY_MANAGER_READY = 550;

    /**
     * 到了這兒,服務可以啟動/綁定第三方apps.
     */
    public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;

    /**
     * 當收到這個啟動指令, 服務允許用戶與設備交互.設備開機完成並且啟動了桌面應用
     */
    public static final int PHASE_BOOT_COMPLETED = 1000;

SystemServiceManager.startBootPhase方法為:

     /**啟動執行到這兒的這一階段的所有系統服務
      * @param phase The boot phase to start.
     */
    public void startBootPhase(final int phase) {
        if (phase <= mCurrentPhase) {//是否小於當前的階段常量值
            throw new IllegalArgumentException("Next phase must be larger than previous");
        }
        mCurrentPhase = phase;

        Slog.i(TAG, "Starting phase " + mCurrentPhase);
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
            final int serviceLen = mServices.size();//獲取mServices的大小
            for (int i = 0; i < serviceLen; i++) {
                final SystemService service = mServices.get(i);//獲取服務
                try {
                    service.onBootPhase(mCurrentPhase);//調用SystemService.onBootPhase()方法啟動
                } catch (Exception ex) {
                    throw new RuntimeException("Failed to boot service "
                            + service.getClass().getName()
                            + ": onBootPhase threw an exception during phase "
                            + mCurrentPhase, ex);//啟動失敗拋出異常,在mCurrentPhase階段
                }
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

這裡又調用了SystemService.onBootPhase()方法的實現方法,比如啟動到了BatteryService服務,BatteryService.onBootPhase():

 @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_ACTIVITY_MANAGER_READY) {
            // check our power situation now that it is safe to display the shutdown dialog.
            synchronized (mLock) {
                ContentObserver obs = new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        synchronized (mLock) {
                            updateBatteryWarningLevelLocked();
                        }
                    }
                };
                final ContentResolver resolver = mContext.getContentResolver();
                resolver.registerContentObserver(Settings.Global.getUriFor(
                        Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                        false, obs, UserHandle.USER_ALL);
                updateBatteryWarningLevelLocked();
            }
        }
    }

ServiceManager.addService()

/**
     * 放進service manager 中@a service called @a name .
     * 
     * @param name 新service的名字
     * @param service service對象
     */
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

getIServiceManager()如下,返回的是一個IServiceManager對象:

 private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // 查找service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

查找service manager中調用了ServiceManagerNative.asInterface():


/**
     * 將一個Binder對象轉換成一個 service manager接口;生成一個代理,如果需要.
     */
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }

        //查詢本地是否有IServiceManager
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);//queryLocalInterface(descriptor)返回值是IInterface類型,其是IServiceManager的父接口
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);//如果沒有則返回ServiceManagerProxy對象
    }

此時可得getIServiceManager().addService()就是ServiceManagerProxy.addService():


 public void addService(String name, IBinder service, boolean allowIsolated)
            throws RemoteException {
        /准備Parcel數據
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        //獲取結果
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        //回收對象的引用
        reply.recycle();
        data.recycle();
    }

ServiceManager相關類關系圖:
這裡寫圖片描述

如果簡單來說,這裡一部分類之間使用了代理模式:
這裡寫圖片描述

代理模式

代理模式:為其它對象提供一種代理以控制對這個對象的訪問。

1,抽象接口IServiceManager:它聲明了真實主題和代理主題的共同接口,這樣一來在任何使用真實主題的地方都可以使用代理主題,客戶端通常需要針對抽象主題角色進行編程。

2,代理類ServiceManagerNative:它包含了對真實類的引用,從而可以在任何時候操作真實類對象;在代理類中提供一個可以使用的接口,以便在任何時候都可以替代真實類,供客戶端使用;代理類還可以控制對真實類的使用,負責在需要的時候創建和刪除真實類對象,並對真實類對象的使用加以約束。通常,在代理類中,客戶端在調用所引用的真實類操作之前或之後還需要執行其他操作,而不僅僅是單純調用真實類對象中的操作。

對真實類的引用,控制對真實類的訪問:如果本地已經緩存有了,使用本地的,否則調用真實類ServiceManagerProxy的對象:

     /**
     * 將一個Binder對象轉換成一個 service manager接口;.
     */
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);//查詢本地是否有IServiceManager
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);//如果沒有則返回ServiceManagerProxy對象
    }

構造器,以便在任何時候都可以替代真實類,供客戶端使用

 public ServiceManagerNative()
    {
        //Binder.attachInterface(IInterface owner, String descriptor)
        attachInterface(this, descriptor);
    }

3,真實類ServiceManagerProxy:它定義了代理類所代表的真實對象,在真實類中實現了真實的業務操作,客戶端可以通過代理類間接調用真實類中定義的操作。

構造器:

public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }

4,客戶端ServiceManager對抽象接口進行編程:

private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // 調用代理類ServiceManagerNative的asInterface方法
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

這個方法的使用上面已經陳述過了。

android源碼中使用代理模式的地方很多,尤其是系統服務方面,因為需要使用Binder才能與系統服務進行通信,等等。

代理模式效果與適用場景

代理模式是常用的結構型設計模式之一,它為對象的間接訪問提供了一個解決方案,可以對對象的訪問進行控制。代理模式類型較多,其中遠程代理、虛擬代理、保護代理等在軟件開發中應用非常廣泛。

模式優點

(1) 能夠協調調用者和被調用者,在一定程度上降低了系統的耦合度。

(2) 客戶端可以針對抽象主題角色進行編程,增加和更換代理類無須修改源代碼,符合開閉原則,系統具有較好的靈活性和可擴展性。

此外,不同類型的代理模式也具有獨特的優點,例如:

(1) 遠程代理為位於兩個不同地址空間對象的訪問提供了一種實現機制,可以將一些消耗資源較多的對象和操作移至性能更好的計算機上,提高系統的整體運行效率。

(2) 虛擬代理通過一個消耗資源較少的對象來代表一個消耗資源較多的對象,可以在一定程度上節省系統的運行開銷。

(3) 緩沖代理為某一個操作的結果提供臨時的緩存存儲空間,以便在後續使用中能夠共享這些結果,優化系統性能,縮短執行時間。

(4) 保護代理可以控制對一個對象的訪問權限,為不同用戶提供不同級別的使用權限。

模式缺點

(1) 由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢,例如保護代理。

(2) 實現代理模式需要額外的工作,而且有些代理模式的實現過程較為復雜,例如遠程代理。

代理模式的類型較多,不同類型的代理模式有不同的優缺點,它們應用於不同的場合:

(1) 當客戶端對象需要訪問遠程主機中的對象時可以使用遠程代理。

(2) 當需要用一個消耗資源較少的對象來代表一個消耗資源較多的對象,從而降低系統開銷、縮短運行時間時可以使用虛擬代理,例如一個對象需要很長時間才能完成加載時。

(3) 當需要為某一個被頻繁訪問的操作結果提供一個臨時存儲空間,以供多個客戶端共享訪問這些結果時可以使用緩沖代理。通過使用緩沖代理,系統無須在客戶端每一次訪問時都重新執行操作,只需直接從臨時緩沖區獲取操作結果即可。

(4) 當需要控制對一個對象的訪問,為不同用戶提供不同級別的訪問權限時可以使用保護代理。

(5) 當需要為一個對象的訪問(引用)提供一些額外的操作時可以使用智能引用代理。

設計模式之代理模式

開發中獲取系統服務

使用系統服務需要跨進程通信,而android已經為我們封裝好了,應用程序可以通過系統提供的Manager接口來訪問這些Service提供的數據。比如通常使用的Context.getSystemService()來獲取系統服務,Context中定義了大部分標識系統服務的常量。比如:

TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 

追溯獲取系統服務過程:
ContextImpl.getSystemService():

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

SystemServiceRegistry.getSystemService(this, name):

/**
     * 從給定的context獲取系統服務.
     */
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);//從ServiceFetcher中查找服務
        return fetcher != null ? fetcher.getService(ctx) : null;//如果fetcher不為空返回fetcher.getService(ctx)
    }

ServiceFetcher是一個接口,fetcher.getService(ctx)的實現是實現ServiceFetcher類,有三個,都是SystemServiceRegistry的內部類,getService(ctx)返回的是使用的服務對象,比如我們要使用AccessibilityManager,返回的是AccessibilityManager對象:

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

AccessibilityManager.getInstance(ctx):

/**
     * 獲得一個AccessibilityManager 對象 (create one if necessary).
     *
     * @param context Context in which this manager operates.
     *
     * @hide
     */
    public static AccessibilityManager getInstance(Context context) {
        synchronized (sInstanceSync) {
            if (sInstance == null) {
                final int userId;
                if (Binder.getCallingUid() == Process.SYSTEM_UID//進程UID
                        || context.checkCallingOrSelfPermission(//檢查權限
                                Manifest.permission.INTERACT_ACROSS_USERS)
                                        == PackageManager.PERMISSION_GRANTED
                        || context.checkCallingOrSelfPermission(
                                Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                                        == PackageManager.PERMISSION_GRANTED) {
                    userId = UserHandle.USER_CURRENT;
                } else {
                    userId = UserHandle.myUserId();
                }
                IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
                IAccessibilityManager service = iBinder == null
                        ? null : IAccessibilityManager.Stub.asInterface(iBinder);//取得AccessibilityManagerService
                sInstance = new AccessibilityManager(context, service, userId);//創建服務對象
            }
        }
        return sInstance;
    }

可以看到最終是ServiceManager.getService(Context.ACCESSIBILITY_SERVICE)獲取一個iBinder對象,然後通過AIDL獲得系統服務AccessibilityManagerService,最後通過構造器得到一個AccessibilityManager對象。ServiceManager.getService方法:

/**
     * 根據名字返回一個服務的引用(a reference to a service).
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or null if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

getIServiceManager().getService(name)是ServiceManagerProxy.getService(String name):

public IBinder getService(String name) throws RemoteException {
        //獲取Parcel數據
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        //發送請求
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        //獲取結果
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

大部分服務都可以用Context.getSystemService()獲取,但也有小部分不是通過Context.getSystemService()獲取的,比如:

PackageManager mPackageManager = SystemContext.getPackageManager();//獲取PackageManager

ResourcesManager mResourcesManager = ResourcesManager.getInstance();//獲取ResourcesManager

。。。

明白了使用系統服務調用方法的步驟,對在開發中使用系統服務有很大便利,比如最常見的攔截電話,正常情況下是不能夠通過代碼自動掛斷電話的,但通過調用電話本地服務的隱藏方法endCall()則可以,關鍵步驟如下(上面系統服務和啟動系統服務相關的類都是隱藏的):

Class clazz=Class.forName("android.os.ServiceManager");//獲取類ServiceManager
Method method=clazz.getMethod("getService",String.class);//獲取方法getService
IBinder binder= (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
ITelephony iTelephony = ITelephony.Stub.asInterface(binder);//獲取服務對象
iTelephony.endCall();//調用服務中的方法,掛斷電話
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved