android 源码分析(二)

Android启动关键点

当系统引导程序启动Linux内核时, 内核会加载各种数据结构和驱动程序。
有了驱动之后, 开始启动Android系统并加载用户级别的第一个进程:init

system/core/init/Init.c:

int main(int argc, char **argv){
 ……

    // 创建各种文件夹和挂载目录.
    mkdir("/dev", 0755);
    ......

    // 初始化日志.
    log_init();
    
    // 解析配置文件.
    init_parse_config_file("/init.rc");

    ...

    return 0;
}

加载Init.rc文件, 主要启动了一个Zygote(孵化器)进程,此进程是Android系统启动关键服务的一个母进程。
system/core/rootdir/Init.rc:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd

app_process 这个C++的程序对应的是App_main.cpp,Zygote进程的初始化在App_main.cpp文件中开启的。
frameworks\base\cmds\app_process \App_main.cpp:

int main(int argc, const char* const argv[])
    {
        // 定义Android运行时环境.
        AppRuntime runtime;
        int i = runtime.addVmArguments(argc, argv);
    
        ......
    
        bool startSystemServer = (i < argc) ? 
                strcmp(argv[i], "--start-system-server") == 0 : false;
        setArgv0(argv0, "zygote");
        set_process_name("zygote");

        // 使用运行时环境启动Zygote的初始化类.
        runtime.start("com.android.internal.os.ZygoteInit",
            startSystemServer);
         ......
    }

ZygoteInit.java初始化类被调用,其中startSystemServer的值一般均为true,为false会报错。

frameworks\base\core\java\com\android\internal\os\ ZygoteInit.java:

public static void main(String argv[]) {
            // 加载系统运行依赖的class类.
            preloadClasses();

            ...
            
            if (argv[1].equals("true")) {
                // Zygote孵化器进程开始孵化系统核心服务.
                startSystemServer();
            } else if (!argv[1].equals("false")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
            
            ...
        }

        private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {
            String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
                "--capabilities=130104352,130104352",
                "--runtime-init",
                "--nice-name=system_server",
                "com.android.server.SystemServer",
            };

            ...

            // 孵化器分叉开启SystemServer类, 并且把上面定义的参数.
            // 传递给此类. 用于启动系统关键服务.
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids, debugFlags, null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        
            ...
        }

SystemServer.java被调用,在其main方法中,init1()方法被调用。

frameworks\base\services\java\com\android\server\ SystemServer.java:

public static void main(String[] args) {
            ...
            
            // 加载本地的动态链接库.
            System.loadLibrary("android_servers");
    
            // 调用动态链接库中的c函数.
            init1(args);
        }
    
   // 这里init1的函数定义在:
// frameworks\base\services\jni\com_android_server_SystemServer.cpp下
  native public static void init1(String[] args);

Init1()方法是一个C代码实现的方法,其方法实现在com_android_server_SystemServer.cpp下。

frameworks\base\services\jni\com_android_server_SystemServer.cpp:

static JNINativeMethod gMethods[] = {
             // 把native方法init1, 映射到android_server_SystemServer_init1
            { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
        };

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

        // 此方法没有方法体.
        extern "C" int system_init();

system_init()方法的方法体, 在System_init.cpp类中。

frameworks\base\cmds\system_server\library\ System_init.cpp

extern "C" status_t system_init()
        {
            ......
        
            // 开启一些硬件相关的服务.
            SensorService::instantiate();
            
if (!proc->supportsProcesses()) {
        // Start the AudioFlinger
        AudioFlinger::instantiate();
        // Start the media playback service
        MediaPlayerService::instantiate();
        // Start the camera service
        CameraService::instantiate();
        // Start the audio policy service
        AudioPolicyService::instantiate();
    }
            ......
            
            // 获取Android运行时环境
            AndroidRuntime* runtime = AndroidRuntime::getRuntime();
        
            LOGI("System server: starting Android services.\n");
            // 调用SystemServer类中静态方法init2. 从native层转到java层.
            runtime->callStatic("com/android/server/SystemServer", "init2");
             ......
        }

至此,native层面的服务被启动起来了,System_init()在开启完native层面的服务后,又返回去调用SystemServer的init2()方法去了。

frameworks\base\services\java\com\android\server\SystemServer.java:

public static final void init2() {
            Slog.i(TAG, "Entered the Android system server!");

            // 进入Android系统服务的初始化.
            Thread thr = new ServerThread();
            thr.setName("android.server.ServerThread");
            thr.start();
 }

在init2()方法中,开启了一个ServerThread,ServerThread的run方法中,开启了各种Framework层面的服务,其中,PackageManagerService和ActivityManagerService也是在这个时候被启动的。

frameworks\base\services\java\com\android\server\SystemServer.java:

class ServerThread extends Thread {
    ……
    @Override
    public void run() {
        ……
 
        LightsService lights = null;
        PowerManagerService power = null;
        BatteryService battery = null;
        ConnectivityService connectivity = null;
        IPackageManager pm = null;
        Context context = null;
        WindowManagerService wm = null;
        BluetoothService bluetooth = null;
        BluetoothA2dpService bluetoothA2dp = null;
        HeadsetObserver headset = null;
        DockObserver dock = null;
        UsbObserver usb = null;
        UiModeManagerService uiMode = null;
        RecognitionManagerService recognition = null;
        ThrottleService throttle = null;
        
        // 初始化系统的服务, 并且把服务添加ServiceManager中, 便于以后系统进行统一管理
        // Critical services...
        try {
            Slog.i(TAG, "Entropy Service");
            ServiceManager.addService("entropy", new EntropyService());
 
            Slog.i(TAG, "Power Manager");
            power = new PowerManagerService();
            ServiceManager.addService(Context.POWER_SERVICE, power);
 
            ………
}
}

Framework层面的服务就都被启动起来了。

Android启动细节

  • 创建文件夹,挂载设备

  • 重定向输入输出,如错误信息输出

  • 设置日志输出

  • 解析和当前设备相关的配置信息(/init.%s.rc)

  • 处理动作执行:这个阶段Zygote将被启动

     各动作的执行有其自己的优先级:
    
       early-init
       Init
       early-boot
       boot
    
  • 无限循环阶段,等待一些事情发生

int main(int argc, char **argv)
{
……
// 创建文件夹,挂载设备

    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);
 
    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
    mkdir("/dev/pts", 0755);
    mkdir("/dev/socket", 0755);
    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);
 
……
// 初始化日志的输入输出
    open_devnull_stdio();
    log_init();
    
    // 加载init.rc配置文件
    init_parse_config_file("/init.rc");
 
   ……
    // 解析和当前设备相关的配置信息
    get_hardware_name(hardware, &revision);
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    init_parse_config_file(tmp);
 
//处理动作执行:这个阶段Zygote将被启动(按优先级执行各动作)
    action_for_each_trigger("early-init", action_add_queue_tail);
……
    action_for_each_trigger("init", action_add_queue_tail);
    ……
    action_for_each_trigger("early-boot", action_add_queue_tail);
    action_for_each_trigger("boot", action_add_queue_tail);
……
// 无限循环阶段,等待一些事情发生

    for(;;) {
        ……
    }
}

Init.rc启动细节

  • 开启各种守护进程

  • 启动app_process

……
// 启动守护进程
service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
onrestart restart media
……
// 启动app_process
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
onrestart restart netd
……

App_main实现细节

  • startVM——开启虚拟机(进行堆内存设置)

  • 注册JNI函数

  • 启动“com.android.internal.os.ZygoteInit”的main方法

void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
    ……
// 开启虚拟机,stratVm中调用了:
// property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");来设置堆内存
    /* start the virtual machine */
    if (startVm(&mJavaVM, &env) != 0)
        goto bail;
 
//注册JNI函数

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        LOGE("Unable to register all android natives\n");
        goto bail;
    }
……
// 启动“com.android.internal.os.ZygoteInit”
env->CallStaticVoidMethod(startClass, startMeth, strArray);
……
}

ZygoteInit实现细节

  • 预加载相应的类preloadClasses()(这个过程大概就要花费20秒,通过反射预加载2000左右个类)

  • 预加载资源文件preloadResources()

  • 启动SystemServer

public static void main(String argv[]) {
        try {
            ……
            // 预加载相应的类
            preloadClasses();
            //预加载资源文件
            preloadResources();
            ……
            // 启动SystemServer
            if (argv[1].equals("true")) {
                startSystemServer();
            } else if (!argv[1].equals("false")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
        ……
    }

现在的手机经过不断的优化,预加载类和资源已经用不了20秒这么久,我们大部分的开机时间,其实还是耗在了扫描apk上。


image.png

SystemServer实现细节

  • 通过init1(),开启native世界

  • 通过init2(),开启Framework层的Java世界

  • Init2()开启Framework层时,当PackageMangerService被开启后,它开始扫描监控:

          system/framework、 system/app、data/app、data/app-private几个文件夹下的所有apk信息,扫描所有apk权限及四大组件信息,最后找到具有:  
    
        <category android:name="android.intent.category.HOME" />
    
      这个过滤器信息的Launcher并启动,完成整个系统的启动
    

应用启动详解

PackageManagerService的主要作用

  1. 建立 java 层的 installer 与 c 层的 installd 的 socket 联接,使得在上层的 install,remove,dexopt等功能最终由 installd 在底层实现

  2. 建 立 PackageHandler 消 息 循 环 , 用 于 处 理 外 部 的 apk 安 装 请 求 消 息 , 如 adbinstall,packageinstaller 安装 apk 时会发送消息

  3. 加载、解析并管理各apk所需的权限信息

  4. 启动 AppDirObserver 线程监测/system/framework,/system/app,/data/app,/data/app-private 目录的事件,主要监听 add 和 remove 事件。

  5. 对所有的apk进行逐个的解析(AndroidManifest.xml、assert、res等等…),建立每个APK的配置结构,并将每个apk的信息添加到全局列表

  6. 将解析的每个 apk 的信息保存到:data/system/packages.xml、packages.list中。

     packages.list 记录了如下数据:pkgName,userId,debugFlag,dataPath(包的数据路径) 
    
PackageManagerService如何识别Launcher应用

PackageManagerService在解析apk的AndroidManifest.xml时,会找到Intent-Filter包含:

<category android:name="android.intent.category.HOME" />

的应用并启动

PackageManagerService的桌面图标如何生成

PackageManagerService在解析apk的AndroidManifest.xml时,会找到Intent-Filter包含:

<intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>

的Activity,此Activity即为在桌面上点击图标时,被开启的Activity。

应用程序启动的入口类是哪个?

ActivityThread是主要用来启动应用程序的主线程,并且管理在应用端跟用户打交道的activity,管理各组件的生命周期。
frameworks\base\core\java\android\app\ ActivityThread.java

public static final void main(String[] args) {
        ……
        // ActivityThread其实就是我们经常说的UI thread,也就是主线程。
// 主线程可以使用Handler进行异步通信,因为主线程中已经创建了Looper,而这个Looper就是在这里创建的。如果其他线程需要使用Handler通信,就要自己去创建Looper
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
 
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
 
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
 
        Looper.loop();
 
        ……
}
 
/** 将进行启动activity的相关工作 */
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ……
        Activity a = performLaunchActivity(r, customIntent);
 
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward);
            ……
         }
}
 
/** 进行了一些初始化和赋值操作后,创建activity,并调用其onCreate方法*/
private final Activity performLaunchActivity(ActivityClientRecord r, 
Intent customIntent) {
        ……
        Activity activity = null;
        ……
        activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        ……
            if (activity != null) {
                ……
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstance,
                        r.lastNonConfigurationChildInstances, config);
 
                // 开始调用acitivity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);
                ……
}
……
        return activity;
    }
 
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
       ……
        ActivityClientRecord r = performResumeActivity(token, clearHide);
}
 
/** H负责处理ApplicationThread发送到消息队列的消息 */
private final class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        ……
        
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
 
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo);
                    handleLaunchActivity(r, null);
                } break;
              ……
        }
      ……
}
 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容