zoukankan      html  css  js  c++  java
  • [Android]Android系统启动流程源码分析


    以下内容为原创,欢迎转载,转载请注明
    来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5013863.html

    Android系统启动流程源码分析

    首先我们知道,Android是基于Linux的,当Linux内核加载完成时就会自动启动一个init的进程。
    又因为我们每当我们启动一个App时,就会生成一个新的dalvik实例,并处于一个新的进程(当然一个App也可能是多进程的)。
    当我们打开第一个App的时候,就会通过init进程fork出一个zygote进程。之后打开新的App的时候都会fork之前的zygote进程。

    fork一个zygote进程时,会进入com.android.internal.os.ZygoteInitmain方法进行初始化操作:

    • 预加载资源
    // ...
    preloadClasses();
    preloadResources();
    preloadOpenGL();
    preloadSharedLibraries();
    preloadTextResources();
    // Ask the WebViewFactory to do any initialization that must run in the zygote process,
    // for memory sharing purposes.
    WebViewFactory.prepareWebViewInZygote();
    // ...
    
    • 从第一个zygote进程forkSystemServer进程,这个进程提供各种ManagerService
    startSystemServer(abiList, socketName);
    
    private static boolean startSystemServer(String abiList, String socketName)
                throws MethodAndArgsCaller, RuntimeException {
    	int pid;
    	// ...
    	String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "com.android.server.SystemServer",
            };
        /* Request to fork the system server process */
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
            // ...
    }
    
    • Fork完SystemServer进程之后,继续接下来在handleSystemServerProcess方法中传入参数到SystemServer
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    

    注意,这里传入的参数是forkSystemServer进程后剩下的参数(parsedArgs.remainingArgs),其实只剩下了com.android.server.SystemServer这个参数了。

    接下来继续调用applicationInit ,传入参数:

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
                throws ZygoteInit.MethodAndArgsCaller {
    	final Arguments args;
    	// ...
    	args = new Arguments(argv);
    	// ...
    }
    

    解析成Arguments后,得到了一个startClass对象,这个startClass其实就是刚刚的那个com.android.server.SystemServer

    接下来,继续调用 invokeStaticMain

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
    	Class<?> cl;
    	// ...
    	cl = Class.forName(className, true, classLoader);
    	// ...
    	m = cl.getMethod("main", new Class[] { String[].class });
    	// ...
    	throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }
    

    就是调用通过反射得到com.android.server.SystemServer(也就是上面的startClass)的main(argv[])方法,然后手动抛一个携带了这个main(argv[])方法的MethodAndArgsCaller异常,但是这个异常是在ZygoteInit.main()方法中被catch,然后去调用它的run()方法,当然这个run()方法中会再去通过反射调用携带的main()方法(这个绕法真是有点坑爹--。):

    public static class MethodAndArgsCaller extends Exception implements Runnable {
    	// ...
    	public void run() {
    		// ...
    	    mMethod.invoke(null, new Object[] { mArgs });
    		// ...
    	}
    	// ...
    }
    

    绕了这么一大圈,终于通过MethodAndArgsCaller调用SystemServermain()方法了,代码很简单,直接new了之后run

    new SystemServer().run();
    

    接着,我们看SystemServerrun方法:

    // ... (省略初始化当前的language、locale、country、指纹、用户等信息的初始化准备工作)
    // 设置当前进程设置优先级为THREAD_PRIORITY_FOREGROUND(-2)
    android.os.Process.setThreadPriority(
        android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);
    // 初始化主线程Looper
    Looper.prepareMainLooper();
    // ...
    // 启动消息循环
    Looper.loop()
    

    然后调用createSystemContext()方法创建初始化system context,这个待会再展开。

    创建SystemServiceManager

    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    

    使用SystemServiceManager去通过以下方法创建启动各个Service

    1. startBootstrapServices():
    • com.android.server.pm.Installer:提供安装、卸载App等服务
    • com.android.server.am.ActivityServiceManager:提供Activity等组件的管理的服务,这个比较复杂暂且再挖个坑。
    • com.android.server.power.PowerManagerService:电源管理的服务。
    • com.android.server.lights.LightsService:LED管理和背光显示的服务。
    • com.android.server.display.DisplayManagerService:提供显示的生命周期管理,根据物理显示设备当前的情况决定显示配置,在状态改变时发送通知给系统和应用等服务。
    • com.android.server.pm.PackageManagerService:管理所有的.apk
    • com.android.server.pm.UserManagerService:提供用户相关服务。
    • 通过startSensorService()本地方法启动Sensor服务。
    1. startCoreServices();
    • com.android.server.BatteryService:电量服务,需要LightService
    • com.android.server.usage.UsageStatsService:提供收集统计应用程序数据使用状态的服务。
    • com.android.server.webkit.WebViewUpdateService:私有的服务(@hide),用于WebView的更新。
    1. startOtherServices();
    • com.android.server.accounts.AccountManagerService:提供所有账号、密码、认证管理等等的服务。
    • com.android.server.content.ContentService:用户数据同步的服务。
    • com.android.server.VibratorService:震动服务。
    • IAlarmManager:提醒服务。
    • android.os.storage.IMountService:存储管理服务。
    • com.android.server.NetworkManagementService:系统网络连接管理服务。
    • com.android.server.net.NetworkStatsService:收集统计详细的网络数据服务。
    • com.android.server.net.NetworkPolicyManagerService:提供低网络策略规则管理服务。
    • com.android.server.ConnectivityService:提供数据连接服务。
    • com.android.server.NetworkScoreServiceandroid.net.NetworkScoreManager的备份服务。
    • com.android.server.NsdService:网络发现服务(Network Service Discovery Service)。
    • com.android.server.wm.WindowManagerService:窗口管理服务。
    • com.android.server.usb.UsbService:USB服务。
    • com.android.server.SerialService:串口服务。
    • com.android.server.NetworkTimeUpdateService:网络时间同步服务。
    • com.android.server.CommonTimeManagementService:管理本地常见的时间配置的服务,当网络配置变化时会重新配置本地服务。
    • com.android.server.input.InputManagerService:事件传递分发服务。
    • com.android.server.TelephonyRegistry:提供电话注册管理的服务。
    • com.android.server.ConsumerIrService:远程控制服务。
    • com.android.server.audio.AudioService:音量、铃声、声道等管理服务。
    • com.android.server.MmsServiceBrokerMmsService的代理,因为MmsService运行在电话进程中,可能随时crash,它会通过一个connectionMmsService建立一个桥梁,MmsService实现了公开的SMS/MMS的API。
    • TelecomLoaderService
    • CameraService
    • AlarmManagerService
    • BluetoothService
    • 还有其它很多很多Service,这方法竟然有近1000行……

    startOtherServices()方法的最后:

    mActivityManagerService.systemReady(new Runnable() {
    	@Override
    	public void run() {
    		// 下面仍然是各种Service的启动...
    	}
    }
    

    调用这个方法用来告诉ActivityManagerService,此时可以运行第三方的代码了(注意:这里的Home界面、Launcher等内置的App也算是第三方的App)。

    public void systemReady(final Runnable goingCallback) {
    	// ...
    	if (mSystemReady) {
    		// 回调到SystemServer,继续启动各种Service
    		if (goingCallback != null) {
    		    goingCallback.run();
    		}
    		return;
    	}
    	// ...
    
    	ResolveInfo ri = mContext.getPackageManager().resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST), STOCK_PM_FLAGS);
    	// ...
    	ActivityInfo ai = ri.activityInfo;
    	ApplicationInfo app = ai.applicationInfo;
    	// ...从PackageManager中获取要打开的HomeActivity
    	mTopComponent = new ComponentName(app.packageName, ai.name);
    	// ...
    	// 启动第一个Home界面
    	startHomeActivityLocked(mCurrentUserId, "systemReady");
    
    	// ...
    	// 广播通知启动完成
    	broadcastIntentLocked(/*...*/, mCurrentUserId);
    	broadcastIntentLocked(/*...*/, UserHandle.USER_ALL);
    	// ...
    }
    

    启动Home界面的startHomeActivityLocked方法,调用mStackSupervisor启动HomeActivity

    boolean startHomeActivityLocked(int userId, String reason) {
    	// ...
    	Intent intent = getHomeIntent();
    	// ...
    	intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
    	mStackSupervisor.startHomeActivity(intent, aInfo, reason);
    	// ...
    }
    
    Intent getHomeIntent() {
    	Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    	// 设置前面获取到的mTopComponent
    	intent.setComponent(mTopComponent);
    	// ...
    	intent.addCategory(Intent.CATEGORY_HOME);
    	// ...
    }
    

    到此为止,SystemServer start完毕,并且启动了Home界面。



    然后我们再回过头去看看在我们前面创建系统级的ContextcreateSystemContext)的时候做了什么:

    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    

    首先调用了ActivityThread的静态方法systemMain()

    public static ActivityThread systemMain() {
    	// ...
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }
    

    创建一个ActivityThread,然后调用它的attach()方法:

    thread.attach(true);
    
    private void attach(boolean system) {
    	if (!system) {
    		// ...
    	}else{
    		// ...
    		mInstrumentation = new Instrumentation();
            ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
    		// ...
    	}
    }
    

    参数system表示,是否是系统级的线程,现在我们是启动整个Android系统,显然当前传入的参数为true。所以进入else,首先,创建一个InstrumentationInstrumentation是什么?暂时先挖个坑。接着通过System Context创建一个ContextImpl,然后使用它的LoadedApk::makeApplication方法来创建整个应用的Application对象,然后调用ApplicationonCreate方法。

    然后看下LoadedApk::makeApplication方法的实现:

    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
    	// 只有第一次调用makeApplication才会往下执行
    	if (mApplication != null) {
    	    return mApplication;
        }
        // 初始化系统的Application,所以appClass是"android.app.Application"
    	String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }
    	// ...
    	ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    	// ...	
    }
    

    创建appContext,然后通过Instrumentation生成Application对象,并给appContext设置外部引用。

  • 相关阅读:
    输入框正则表达式验证
    MySQL表名、列名区分大小写详解
    前后台交互
    分页写法
    web程序调试方法
    html 标签
    Aborting commit: 'XXXXXXXX'remains in conflict错误
    返回按钮
    跳出frameset框架
    fastadmin中关联表时A为主表,想让B表和C表关联时怎么办?
  • 原文地址:https://www.cnblogs.com/tiantianbyconan/p/5013863.html
Copyright © 2011-2022 走看看