android7.x Launcher3 源码解析(1)--- 启动流程

Launcher系列目录:
一、android7.x Launcher3源码解析(1)—启动流程
二、android7.x Launcher3源码解析(2)—框架结构

Launcher是安卓系统中的桌面启动器,安卓系统的桌面UI统称为Launcher。Launcher是安卓系统中的主要程序组件之一,安卓系统中如果没有Launcher就无法启动安卓桌面,Launcher出错的时候,安卓系统会出现“进程 com.Android.launcher 意外停止”的提示窗口。这时需要重新启动Launcher。 —— 百度百科

下面盗用网上的一张启动流程图:
《android7.x Launcher3 源码解析(1)--- 启动流程》

1、init进程

Linux内核启动之后,运行的第一个进程是init,这个进程是一个守护进程,它的生命周期贯穿整个linux 内核运行的始终, linux中所有其它的进程的共同始祖均为init进程。
Android系统是运作在linux内核上的,为了启动并运行整个android系统,google实现了android系统的init进程。
Android init进程的入口文件在system/core/init/init.cpp中。

init进程主要做了三件事:
1. 创建一些文件夹并挂载设备
2. 初始化和启动属性服务
3. 解析init.rc配置文件并启动zygote进程

关于init进程,想要详细了解的同学可以参考博客Android7.0 init进程源码分析

2、Zygote孵化器

在Android系统中,JavaVM(Java虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也将它称为孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动时会创建JavaVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个JavaVM的实例拷贝。

Zygote进程共做了如下几件事:
1. 创建AppRuntime并调用其start方法,启动Zygote进程。
2. 创建JavaVM并为JavaVM注册JNI.
3. 通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
4. 通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。
5. 启动SystemServer进程。

3、SystemServer

SyetemServer在启动时做了如下工作:
1.启动Binder线程池,这样就可以与其他进程进行通信。
2.创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理。
3.启动各种系统服务。

分析一下SystemServer.java的代码(原谅我只分析java代码,cpp代码好多年不用了)

   public static void main(String[] args) {
        new SystemServer().run();
    }

进入run方法,发现里面做了很多事情

private void run() {
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitBeforeStartServices");
            // 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.
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                Slog.w(TAG, "System clock is before 1970; setting to 1970.");
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }

            // If the system has "persist.sys.language" and friends set, replace them with
            // "persist.sys.locale". Note that the default locale at this point is calculated
            // using the "-Duser.locale" command line flag. That flag is usually populated by
            // AndroidRuntime using the same set of system properties, but only the system_server
            // and system apps are allowed to set them.
            //
            // NOTE: Most changes made here will need an equivalent change to
            // core/jni/AndroidRuntime.cpp
            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();

                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            }

            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

            // In case the runtime switched since last boot (such as when
            // the old runtime was removed in an OTA), set the system
            // property so that it is in sync. We can't do this in
            // libnativehelper's JniInvocation::Init code where we already
            // had to fallback to a different runtime because it is
            // running as root and we need to be the system user to set
            // the property. http://b/11463182
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

            // Enable the sampling profiler.
            if (SamplingProfilerIntegration.isEnabled()) {
                SamplingProfilerIntegration.start();
                mProfilerSnapshotTimer = new Timer();
                mProfilerSnapshotTimer.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            SamplingProfilerIntegration.writeSnapshot("system_server", null);
                        }
                    }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
            }

            // Mmmmmm... more memory!
            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);

            // Some devices rely on runtime fingerprint generation, so make sure
            // we've defined it before booting further.
            Build.ensureFingerprintProperty();

            // Within the system server, it is an error to access Environment paths without
            // explicitly specifying a user.
            Environment.setUserRequired(true);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);

            // Ensure binder calls into the system always run at foreground priority.
            BinderInternal.disableBackgroundScheduling(true);

            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();

            // Initialize native services.
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            createSystemContext();

            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

代码还算清晰,首先初始化一些时间、local、binder的最大进程数,启动Binder线程池啥的。

下来就是加载android_servers库,
《android7.x Launcher3 源码解析(1)--- 启动流程》

紧接着就是创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
《android7.x Launcher3 源码解析(1)--- 启动流程》

接下来就是启动系统的各种服务
《android7.x Launcher3 源码解析(1)--- 启动流程》
上图可见,服务分为3类,
1、BootstrapServices为引导服务,启动的service包括:
Installer 系统安装apk时的一个服务类,启动完成Installer服务之后才能启动其他的系统服务
ActivityManagerService 负责四大组件的启动、切换、调度。
PowerManagerService 计算系统中和Power相关的计算,然后决策系统应该如何反应
LightsService 管理和显示背光LED
DisplayManagerService 用来管理所有显示设备
UserManagerService 多用户模式管理
SensorService 为系统提供各种感应器服务
PackageManagerService 用来对apk进行安装、解析、删除、卸载等等操作

2、 CoreServices为核心服务,包括:
BatteryService 管理电池相关的服务
UsageStatsService 收集用户使用每一个APP的频率、使用时常
WebViewUpdateService WebView更新服务

3、OtherServices其他服务,包括很多服务,比如:
CameraService 摄像头相关服务
AlarmManagerService 全局定时器管理服务
InputManagerService 管理输入事件
WindowManagerService 窗口管理服务
VrManagerService VR模式管理服务
BluetoothService 蓝牙管理服务
NotificationManagerService 通知管理服务
DeviceStorageMonitorService 存储相关管理服务
LocationManagerService 定位管理服务
AudioService 音频相关管理服务

4、ActivityManagerService

这里主要讲一下,为啥Launcher启动出来会成为桌面,先来看一下ActivityManagerService(SystemService启动的一个引导服务)内的startHomeActivityLocked方法。

boolean startHomeActivityLocked(int userId) {
        if(this.mHeadless) {
            this.ensureBootCompleted();
            return false;
        } else if(this.mFactoryTest == 1 && this.mTopAction == null) {
            return false;
        } else {
            Intent intent = new Intent(this.mTopAction, this.mTopData != null?Uri.parse(this.mTopData):null);
            intent.setComponent(this.mTopComponent);
            if(this.mFactoryTest != 1) {
                intent.addCategory("android.intent.category.HOME");
            }

            ActivityInfo aInfo = intent.resolveActivityInfo(this.mContext.getPackageManager(), 1024);
            if(aInfo != null) {
                intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
                aInfo = new ActivityInfo(aInfo);
                aInfo.applicationInfo = this.getAppInfoForUser(aInfo.applicationInfo, userId);
                ProcessRecord app = this.getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid);
                if(app == null || app.instrumentationClass == null) {
                    intent.setFlags(intent.getFlags() | 268435456);
                    this.mMainStack.startActivityLocked((IApplicationThread)null, intent, (String)null, aInfo, (IBinder)null, (String)null, 0, 0, 0, 0, (Bundle)null, false, (ActivityRecord[])null);
                }
            }

            return true;
        }
    }

创建了一个Intent,并将mTopAction和mTopData传入。mTopAction的值为Intent.ACTION_MAIN,并且如果系统运行模式不是1(这个1是什么意思?)则将intent的Category设置为android.intent.category.HOME

而Launcher的AndroidManifest.xml文件里面给Launcher定义的category就是android.intent.category.HOME,

        <activity  android:name="com.android.launcher3.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:windowSoftInputMode="adjustPan" android:screenOrientation="nosensor" android:configChanges="keyboard|keyboardHidden|navigation" android:resumeWhilePausing="true" android:taskAffinity="" android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

之后,就将含有这个属性的Launcher启动了

if(app == null || app.instrumentationClass == null) {
                    intent.setFlags(intent.getFlags() | 268435456);
                    this.mMainStack.startActivityLocked((IApplicationThread)null, intent, (String)null, aInfo, (IBinder)null, (String)null, 0, 0, 0, 0, (Bundle)null, false, (ActivityRecord[])null);
                }

至此,Launcher这个app作为一个home桌面就启动出来了。启动之后的界面划分和模块分析下一篇讲解。

    原文作者:Android源码分析
    原文地址: https://juejin.im/entry/58eb3cdfac502e4957cc0d15
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞