热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android源码学习之浅析SystemServer脉络

在之前的博文中《Android源码学习之如何创建使用JNI》和《Android源码学习之如何使用eclipse+NDK》中,浅谈了如何创建使用JNI和如何利用NDK工具开发创建和lib**.s

    在之前的博文中《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 
#include 

#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 proc(ProcessState::self());

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

    sp 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源码组织的框架架构,对理解整个源码是更加轻松的。

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

 

 

 


推荐阅读
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • Java设计模式详解:解释器模式的应用与实现
    本文详细介绍了Java设计模式中的解释器模式,包括其定义、应用场景、优缺点以及具体的实现示例。通过音乐解释器的例子,帮助读者更好地理解和应用这一模式。 ... [详细]
  • 普通树(每个节点可以有任意数量的子节点)级序遍历 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • Python多线程详解与示例
    本文介绍了Python中的多线程编程,包括僵尸进程和孤儿进程的概念,并提供了具体的代码示例。同时,详细解释了0号进程和1号进程在系统中的作用。 ... [详细]
  • 本文将介绍如何在混合开发(Hybrid)应用中实现Native与HTML5的交互,包括基本概念、学习目标以及具体的实现步骤。 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • JVM钩子函数的应用场景详解
    本文详细介绍了JVM钩子函数的多种应用场景,包括正常关闭、异常关闭和强制关闭。通过具体示例和代码演示,帮助读者更好地理解和应用这一机制。适合对Java编程和JVM有一定基础的开发者阅读。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • 版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https:blog.csdn.netweixin_43171186art ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
author-avatar
低調浮華
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有