Android源碼學習之淺析SystemServer脈絡


    在之前的博文中《Android源碼學習之如何創建使用JNI》和《Android源碼學習之如何使用eclipse+NDK》中,淺談了如何創建使用JNI和如何利用NDK工具開發創建和lib**.so(Windows下)庫和調用Naive函數,做了這些工作只有一個目的,就是因為Android源碼中“大量”的使用到Native,所以了解一些Native語言和Java如何與Native互通,對分析Android源碼還是有很大的幫助的(好像廢話很多~~~)。

    本人通過對SystemServer源碼進行淺析,看它是如何設計的。

    首先利用Source Insight工具搜索到SystemServer.java代碼,找到入口函數main(),代碼如下:

 native public static void init1(String[] args); public static void main(String[] args) {
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            // If a device's clock is before 1970 (before 0), a lot of
            // APIs crash dealing with negative numbers, notably
            // java.io.File#setLastModified, so instead we fake it and
            // hope that time from cell towers or NTP fixes it
            // shortly.
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        System.loadLibrary("android_servers"); init1(args);     }

    public static final void init2() {
        Slog.i(TAG, "Entered the Android system server!");
        Thread thr = new ServerThread();
        thr.setName("android.server.ServerThread");
        thr.start();
    }

在main函數最后兩行代碼System.loadLibrary("android_servers");和init1(args);還有第一行代碼native public static void init1(String[] args);要是理解了本人之前的兩篇博文的,對這三行代碼也太熟悉了,就是首先加載動態庫libandroid_servers.so,然后調用native的init1()函數。接着往下走,看看native函數init1()是什么樣子的(注:記得這里的init2()函數,一會兒在native層函數中會調用到這個函數)。

     首先如何找到該init1()函數?通過之前的博文,我們知道在調用native函數所在的類與native編寫的類進行溝通,是通過“類名”的相似性或者是在Android.mk文件中定義,所以根據這條思路我們知道該java類的包名為package com.android.server;以及類名為“SystemServer”,所以將它們的"."改成"_"組合為“com_android_server_SystemServer”,這樣通過source insight搜索有沒有這個文件,終於找到了,並且可以找到調用的nitive函數init()。代碼如下:

 

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <utils/Log.h>
#include <utils/misc.h>

#include "jni.h"
#include "JNIHelp.h"

namespace android {

extern "C" int system_init();

static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz)
{
    system_init();
}

/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] = {
    /* name, signature, funcPtr */
    { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
};

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

}; // namespace android

 

整個文件就這么幾行代碼,比較簡單。目前只關心Native函數android_server_SystemServer_init1(JNIEnv* env, jobject clazz),它是調用上面那個用extern聲明的一個外部system_init函數。接着搜索這個函數所在的文件,這個函數是在另外一個庫libsystem_server.so中實現,找到類System_init.cpp后,可以看到函數system_init(),代碼如下:

 

extern "C" status_t system_init()
{
    LOGI("Entered system_init()");

    sp<ProcessState> proc(ProcessState::self());

    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p\n", sm.get());

    sp<GrimReaper> grim = new GrimReaper();
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);

    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsurfaceflinger", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the SurfaceFlinger
        SurfaceFlinger::instantiate();
    }

    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }

    // And now start the Android runtime.  We have to do this bit
    // of nastiness because the Android runtime initialization requires
    // some of the core system services to already be started.
    // All other servers should just start the Android runtime at
    // the beginning of their processes's main(), before calling
    // the init function.
    LOGI("System server: starting Android runtime.\n");
    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

    LOGI("System server: starting Android services.\n");
    JNIEnv* env = runtime->getJNIEnv();
    if (env == NULL) {
        return UNKNOWN_ERROR;
    }
    jclass clazz = env->FindClass("com/android/server/SystemServer");
    if (clazz == NULL) {
        return UNKNOWN_ERROR;
    }
    jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
    if (methodId == NULL) {
        return UNKNOWN_ERROR;
    }
    env->CallStaticVoidMethod(clazz, methodId);

    LOGI("System server: entering thread pool.\n");
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    LOGI("System server: exiting thread pool.\n");

    return NO_ERROR;
}

 

函數具體要做什么,有什么功能我們暫且不考慮,我們找到我們關系的幾行代碼:

jclass clazz = env->FindClass("com/android/server/SystemServer");
   
if (clazz == NULL) {
       
return UNKNOWN_ERROR;
    }
    jmethodID methodId
= env->GetStaticMethodID(clazz, "init2", "()V");
   
if (methodId == NULL) {
       
return UNKNOWN_ERROR;
    }
    env
->CallStaticVoidMethod(clazz, methodId);
這幾行代碼我們熟~~~,是通過“com/android/server/SystemServer”找到類,這個類不就是我們本博文開篇的SystemServer.java的類嗎。找到類對象后,再調用該對象的init2函數,然后執行init2()函數,我們在溫習下init2()函數,代碼如下:

public static final void init2() {
        Slog.i(TAG,
"Entered the Android system server!");
        Thread thr
= new ServerThread(); thr.setName("android.server.ServerThread");
        thr.start();
    }

總結:我們放開代碼的功能不說,單純的從java和nitive的交互和相互調用上說,通過之前的學習,對於理解Android源碼的脈絡是有幫助的,只有在了解了整個Android源碼的脈絡和一些Android源碼組織的框架架構,對理解整個源碼是更加輕松的。

    記錄下自己的學習過程,為己為人,內容膚淺,請高手多多指導~~~

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM