zoukankan      html  css  js  c++  java
  • 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源码组织的框架架构,对理解整个源码是更加轻松的。

        记录下自己的学习过程,为己为人,内容肤浅,请高手多多指导~~~

  • 相关阅读:
    wenbao与manacher
    wenbao与拓扑排序
    wenbao与邻接表
    wenbao与最短路floyd
    wenbao与最短路dij
    wenbao与后缀自动机(SAM)
    wenbao与欧拉回路
    wenbao与字符串Hash
    wenbao与后缀数组
    wenbao与扩展kmp
  • 原文地址:https://www.cnblogs.com/yemeishu/p/2833415.html
Copyright © 2011-2022 走看看