Android启动流程简析(三)

接上一篇文章:Android启动流程简析(二)

7. SystemServer启动介绍

SystemServer需要从Zygote fork SystemServer开始分析,主要是设置参数,然后调用Zygote的forkSystemServer方法,再判断是否有SecondaryZygote启动,有则等待其启动,无则返回

private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
    long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_IPC_LOCK,
        OsConstants.CAP_KILL,
        OsConstants.CAP_NET_ADMIN,
        OsConstants.CAP_NET_BIND_SERVICE,
        OsConstants.CAP_NET_BROADCAST,
        OsConstants.CAP_NET_RAW,
        OsConstants.CAP_SYS_MODULE,
        OsConstants.CAP_SYS_NICE,
        OsConstants.CAP_SYS_PTRACE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG,
        OsConstants.CAP_WAKE_ALARM
    );
    /* Containers run without this capability, so avoid setting it in that case */
    if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
        capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
    }
    /* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        /* Request to fork the system server process */
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        zygoteServer.closeServerSocket();
        return handleSystemServerProcess(parsedArgs);
    }

    return null;
}

Zygote的forkSystemServer方法主要是调用了native方法nativeForkSystemServer,在native层进行fork动作,并设置pid、gid、selinux安全上下文等,最后启动com.android.server.SystemServer

public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    VM_HOOKS.preFork();
    // Resets nice priority for zygote process.
    resetNicePriority();
    int pid = nativeForkSystemServer(
            uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
    // Enable tracing as soon as we enter the system_server.
    if (pid == 0) {
        Trace.setTracingEnabled(true, debugFlags);
    }
    VM_HOOKS.postForkCommon();
    return pid;
}
static const JNINativeMethod gMethods[] = {
    { "nativeForkAndSpecialize",
      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
      (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
    { "nativeForkSystemServer", "(II[II[[IJJ)I",
      (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
    { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V",
      (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork },
    { "nativeUnmountStorageOnInit", "()V",
      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit },
    { "nativePreApplicationInit", "()V",
      (void *) com_android_internal_os_Zygote_nativePreApplicationInit }
};
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL, NULL);
  if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }

      // Assign system_server to the correct memory cgroup.
      if (!WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {
        ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);
      }
  }
  return pid;
}

SystemServer是一个Java类,从main函数入口分析,主要调用run方法,主要工作是:

  1. 调整时间,如果系统时间比1970还要早,调整到1970年
  2. 设置语言
  3. 调整虚拟机堆内存大小和内存利用率
  4. 初始化Looper为mainLooper
  5. 装载库libandroid_server.so
  6. 初始化系统Context
  7. 创建SystemServiceManager负责系统Service启动
  8. 创建和启动Java服务
  9. 调用Looper.loop(),进入处理消息的循环
public static void main(String[] args) {
    new SystemServer().run();
}

public SystemServer() {
    // Check for factory test mode.
    mFactoryTestMode = FactoryTest.getMode();
    // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}

private void run() {
    try {
        traceBeginAndSlog("InitBeforeStartServices");
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
        if (timezoneProperty == null || timezoneProperty.isEmpty()) {
            Slog.w(TAG, "Timezone not set; setting to GMT.");
            SystemProperties.set("persist.sys.timezone", "GMT");
        }

        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", "");
        }

        // The system server should never make non-oneway calls
        Binder.setWarnOnBlocking(true);

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
        }

        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        // 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);
        mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }

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

    // For debug builds, log event loop stalls to dropbox for analysis.
    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
        final int MAX_UPTIME_MILLIS = 60 * 1000;
        if (uptimeMillis > MAX_UPTIME_MILLIS) {
            Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                    "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
        }
    }

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

7.1 ActivityManagerService启动

AMS在SystemServer的startBootstrapServices中启动,主要是创建了一个Lifecycle对象创建AMS。
创建AMS后会调用AMS的start方法。setSystemServiceManager方法是把AMS纳入SystemServerManager的管理。
在AMS的构造函数中初始化了很多变量和一些服务,如果管理广播的队列、电池和CPU等相关服务,服务会在start方法中启动,并等待启动完成。
最后,调用AMS的systemReady方法完成初始化,在SystemReady中启动桌面。

// Activity manager runs the show.
traceBeginAndSlog("StartActivityManager");
mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
traceEnd();
public static final class Lifecycle extends SystemService {
    private final ActivityManagerService mService;

    public Lifecycle(Context context) {
        super(context);
        mService = new ActivityManagerService(context);
    }

    @Override
    public void onStart() {
        mService.start();
    }

    @Override
    public void onCleanupUser(int userId) {
        mService.mBatteryStatsService.onCleanupUser(userId);
    }

    public ActivityManagerService getService() {
        return mService;
    }
}

systemReady在SystemServer的startOtherServices的最后被调用,主要是动作是标记和等待各个服务启动完成如等待PMS启动结束,接着启动SystemUI和启动HomeActivity。在Android N之后引入DirectBoot,DirectBoot是一种安全模式,是开机完成但用户还没有解锁的时候处于的一种运行环境。

mActivityManagerService.systemReady(() -> {
    Slog.i(TAG, "Making services ready");
    traceBeginAndSlog("StartActivityManagerReadyPhase");
    mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
    traceEnd();
    traceBeginAndSlog("StartObservingNativeCrashes");
    try {
        mActivityManagerService.startObservingNativeCrashes();
    } catch (Throwable e) {
        reportWtf("observing native crashes", e);
    }
    traceEnd();

    // No dependency on Webview preparation in system server. But this should
    // be completed before allowring 3rd party
    final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
    Future<?> webviewPrep = null;
    if (!mOnlyCore) {
        webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
            Slog.i(TAG, WEBVIEW_PREPARATION);
            TimingsTraceLog traceLog = new TimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(WEBVIEW_PREPARATION);
            ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
            mZygotePreload = null;
            mWebViewUpdateService.prepareWebViewInSystemServer();
            traceLog.traceEnd();
        }, WEBVIEW_PREPARATION);
    }

    if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
        traceBeginAndSlog("StartCarServiceHelperService");
        mSystemServiceManager.startService(CarServiceHelperService.class);
        traceEnd();
    }
    
    traceBeginAndSlog("StartSystemUI");
    try {
        startSystemUi(context, windowManagerF);
    } catch (Throwable e) {
        reportWtf("starting System UI", e);
    }
    traceEnd();
    
    ...

    traceBeginAndSlog("StartWatchdog");
    Watchdog.getInstance().start();
    traceEnd();

    // Wait for all packages to be prepared
    mPackageManagerService.waitForAppDataPrepared();

    // It is now okay to let the various system services start their third party code...
    traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
    // confirm webview completion before starting 3rd party
    if (webviewPrep != null) {
        ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
    }
    mSystemServiceManager.startBootPhase(
            SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
    traceEnd();

     ...

    traceBeginAndSlog("MakeTelephonyRegistryReady");
    try {
        if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying TelephonyRegistry running", e);
    }
    traceEnd();
    
    traceBeginAndSlog("MakeMediaRouterServiceReady");
    try {
        if (mediaRouterF != null) mediaRouterF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying MediaRouterService running", e);
    }
    traceEnd();
    
    traceBeginAndSlog("MakeMmsServiceReady");
    try {
        if (mmsServiceF != null) mmsServiceF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying MmsService running", e);
    }
    traceEnd();

    traceBeginAndSlog("MakeNetworkScoreServiceReady");
    try {
        if (networkScoreF != null) networkScoreF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying NetworkScoreService running", e);
    }
    traceEnd();
    
    traceBeginAndSlog("IncidentDaemonReady");
    try {
        // TODO: Switch from checkService to getService once it's always
        // in the build and should reliably be there.
        final IIncidentManager incident = IIncidentManager.Stub.asInterface(
                ServiceManager.checkService("incident"));
        if (incident != null) incident.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying incident daemon running", e);
    }
    traceEnd();
}, BOOT_TIMINGS_TRACE_LOG);

AMS初始化在启动完成后,在锁屏界面Keyguard绘制完成后(finishKeyguardDrawn),然后调用WindowManagerService的enableScreenAfterBoot,WMS会接着调用performEnableScreen通知SurfaceFlinger关闭开机动画,接着WMS调用AMS的bootAnimationComplete通知AMS开机动画结束,AMS最后通过调用finishBooting设置属性sys.boot_complete通知系统开机完成,可以执行属性sys.boot_complete设置之后的任务

private void performEnableScreen() {
    synchronized(mWindowMap) {
        try {
            IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
            if (surfaceFlinger != null) {
                Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
                Parcel data = Parcel.obtain();
                data.writeInterfaceToken("android.ui.ISurfaceComposer");
                surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
                        data, null, 0);
                data.recycle();
                if (mWindowManagerDebugger.WMS_DEBUG_ENG) {
                    Slog.d(TAG, "Tell SurfaceFlinger finish boot animation");
                }
            }
        } catch (RemoteException ex) {
            Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
        }
        mDisplayEnabled = true;
        mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
    }
    try {
        mActivityManager.bootAnimationComplete();
    } catch (RemoteException e) {
    }
    mPolicy.enableScreenAfterBoot();
    updateRotationUnchecked(false, false);
}
final void finishBooting() {
    synchronized (this) {
        if (!mBootAnimationComplete) {
            mCallFinishBooting = true;
            return;
        }
        mCallFinishBooting = false;
    }
    // Let system services know.
    mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
    synchronized (this) {
        SystemProperties.set("sys.boot_completed", "1");
    }
}

WMS与SurfaceFlingerBinder进行Binder通信的协议:

class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
    enum {
        // Note: BOOT_FINISHED must remain this value, it is called from
        // Java by ActivityManagerService.
        BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
        CREATE_CONNECTION,
        UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
        CREATE_DISPLAY_EVENT_CONNECTION,
        CREATE_DISPLAY,
        DESTROY_DISPLAY,
        GET_BUILT_IN_DISPLAY,
        SET_TRANSACTION_STATE,
        AUTHENTICATE_SURFACE,
        GET_SUPPORTED_FRAME_TIMESTAMPS,
        GET_DISPLAY_CONFIGS,
        GET_ACTIVE_CONFIG,
        SET_ACTIVE_CONFIG,
        CONNECT_DISPLAY,
        CAPTURE_SCREEN,
        CLEAR_ANIMATION_FRAME_STATS,
        GET_ANIMATION_FRAME_STATS,
        SET_POWER_MODE,
        GET_DISPLAY_STATS,
        GET_HDR_CAPABILITIES,
        GET_DISPLAY_COLOR_MODES,
        GET_ACTIVE_COLOR_MODE,
        SET_ACTIVE_COLOR_MODE,
        ENABLE_VSYNC_INJECTIONS,
        INJECT_VSYNC,
        CREATE_SCOPED_CONNECTION
    };

    virtual status_t onTransact(uint32_t code, const Parcel& data,
            Parcel* reply, uint32_t flags = 0);
};
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
    explicit BpSurfaceComposer(const sp<IBinder>& impl)
        : BpInterface<ISurfaceComposer>(impl)
    {
    }

    virtual ~BpSurfaceComposer();

    virtual void bootFinished()
    {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
    }
}

可以看到WMS通过binder通信,调用IBinder.FIRST_CALL_TRANSACTION函数,也就是android.ui.ISurfaceComposer的BOOT_FINISHED对应的函数bootFinished(),SurfaceFlinger是继承BpSurfaceComposer的,所以最后调用的是SurfaceFlinger::bootFinished(),通过设置属性service.bootanim.exit标记开机动画结束

void SurfaceFlinger::bootFinished()
{
    if (mStartPropertySetThread->join() != NO_ERROR) {
        ALOGE("Join StartPropertySetThread failed!");
    }
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );

    // wait patiently for the window manager death
    const String16 name("window");
    sp<IBinder> window(defaultServiceManager()->getService(name));
    if (window != 0) {
        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
    }

    if (mVrFlinger) {
      mVrFlinger->OnBootFinished();
    }

    // stop boot animation
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    property_set("service.bootanim.exit", "1");

    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

    sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
        readPersistentProperties();
    });
    postMessageAsync(readProperties);
}

7.2 PackageManagerService启动

PMS是在SystemServer的startBootstrapServices中启动,启动时构建一个PMS实例,初始化相关服务,主要的动作有扫描app目录包括system/app、system/priv-app、vendor/app等,首次启动会调用DexManager对获取到的Package进行load操作,主要是通过SCAN_FIRST_BOOT_OR_UPGRADE这个scanFlag进行区分,而判断设备是否是第一次启动是通过判断文件data/system/packages.xml是否存在进行判断

traceBeginAndSlog("StartPackageManagerService");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // Self-check for initial settings.
    PackageManagerServiceCompilerMapping.checkProperties();

    PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
    m.enableSystemUserPackages();
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
    ServiceManager.addService("package_native", pmn);
    return m;
}

首次开机和非首次开机区别就在于扫描app目录时,首次开机做了dex2ota的动作,相对来说就要较非首次开机耗时

// Set flag to monitor and not change apk file paths when scanning install directories.
int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

if (mIsUpgrade || mFirstBoot) {
    scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
}

PMS的systemReady调用在SystemServer的startOtherServices的最后AMS的systemReady调用之前,也就是说PSM的初始化需要先于AMS,PMS标记systemReady主要是使UserManager和InstallerService等服务标记为systemReady

@Override
public void systemReady() {
    enforceSystemOrRoot("Only the system can claim the system is ready");
    mSystemReady = true;
    final ContentResolver resolver = mContext.getContentResolver();
    ContentObserver co = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange) {
            mEphemeralAppsDisabled = (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
                            (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
        }
    };
    mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                    .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
            false, co, UserHandle.USER_SYSTEM);
    mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
                    .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
    co.onChange(true);
     // Disable any carrier apps. We do this very early in boot to prevent the apps from being
    // disabled after already being started.
    CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
            mContext.getContentResolver(), UserHandle.USER_SYSTEM);
     // Read the compatibilty setting when the system is ready.
    boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
            mContext.getContentResolver(),
            android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
    PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
    if (DEBUG_SETTINGS) {
        Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
    }

    int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;

    synchronized (mPackages) {
        ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
        for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
            PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
            removed.clear();
            for (PreferredActivity pa : pir.filterSet()) {
                if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
                    removed.add(pa);
                }
            }
            if (removed.size() > 0) {
                for (int r=0; r<removed.size(); r++) {
                    PreferredActivity pa = removed.get(r);
                    Slog.w(TAG, "Removing dangling preferred activity: "
                            + pa.mPref.mComponent);
                    pir.removeFilter(pa);
                }
                mSettings.writePackageRestrictionsLPr(
                        mSettings.mPreferredActivities.keyAt(i));
            }
        }

        for (int userId : UserManagerService.getInstance().getUserIds()) {
            if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
                grantPermissionsUserIds = ArrayUtils.appendInt(
                        grantPermissionsUserIds, userId);
            }
        }
    }
    sUserManager.systemReady();

    // If we upgraded grant all default permissions before kicking off.
    for (int userId : grantPermissionsUserIds) {
        mDefaultPermissionPolicy.grantDefaultPermissions(userId);
    }

    // If we did not grant default permissions, we preload from this the
    // default permission exceptions lazily to ensure we don't hit the
    // disk on a new user creation.
    if (grantPermissionsUserIds == EMPTY_INT_ARRAY) {
        mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions();
    }

    // Kick off any messages waiting for system ready
    if (mPostSystemReadyMessages != null) {
        for (Message msg : mPostSystemReadyMessages) {
            msg.sendToTarget();
        }
        mPostSystemReadyMessages = null;
    }

    mInstallerService.systemReady();
    mPackageDexOptimizer.systemReady();
    
    ...

    // Now that we're mostly running, clean up stale users and apps
    sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
    reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);

    if (mPrivappPermissionsViolations != null) {
        Slog.wtf(TAG,"Signature|privileged permissions not in "
                + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
        mPrivappPermissionsViolations = null;
    }
}

8. Launcher启动介绍

8.1SystemUI启动

SystemUI在AMS执行systemReady时启动,主要是通过Intent启动包名为com.android.systemui组件名为SystemUIService的服务,然后通过调用WindowManager的onSystemUiStarted方法调用KeyguardService启动锁屏服务。SystemUI启动成功后表示系统的通知栏和导航栏已经初始化成功,接下来就是启动Launcher

traceBeginAndSlog("StartSystemUI");
try {
    startSystemUi(context, windowManagerF);
} catch (Throwable e) {
    reportWtf("starting System UI", e);
}
traceEnd();
static final void startSystemUi(Context context, WindowManagerService windowManager) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService"));
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    windowManager.onSystemUiStarted();
}

8.2Launcher启动

Launcher的启动在AMS的最后,通过startHomeActivityLocked把启动Launcher的Activity并将其置于Activity栈顶,然后通过resumeFocusedStackTopActivityLocked将栈顶的Activity显示到界面上,launcher的启动就已经完成了

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    traceLog.traceBegin("PhaseActivityManagerReady");
    synchronized(this) {
        if (mSystemReady) {
            // If we're done calling all the receivers, run the next "boot phase" passed in
            // by the SystemServer
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }

        mLocalDeviceIdleController = LocalServices.getService(DeviceIdleController.LocalService.class);
        mAssistUtils = new AssistUtils(mContext);
        mVrController.onSystemReady();
        // Make sure we have the current profile info, since it is needed for security checks.
        mUserController.onSystemReady();
        mRecentTasks.onSystemReadyLocked();
        mAppOpsService.systemReady();
        mSystemReady = true;
    }

    try {
        sTheRealBuildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(
                ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE))
                .getSerial();
    } catch (RemoteException e) {}
    ArrayList<ProcessRecord> procsToKill = null;
    synchronized(mPidsSelfLocked) {
        for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
            ProcessRecord proc = mPidsSelfLocked.valueAt(i);
            if (!isAllowedWhileBooting(proc.info)){
                if (procsToKill == null) {
                    procsToKill = new ArrayList<ProcessRecord>();
                }
                procsToKill.add(proc);
            }
        }
    }

    synchronized(this) {
        if (procsToKill != null) {
            for (int i=procsToKill.size()-1; i>=0; i--) {
                ProcessRecord proc = procsToKill.get(i);
                Slog.i(TAG, "Removing system update proc: " + proc);
                removeProcessLocked(proc, true, false, "system update done");
            }
        }

        // Now that we have cleaned up any update processes, we
        // are ready to start launching real processes and know that
        // we won't trample on them any more.
        mProcessesReady = true;
    }

    Slog.i(TAG, "System now ready");
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
        SystemClock.uptimeMillis());

    ...

    traceLog.traceBegin("ActivityManagerStartApps");
    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
            Integer.toString(currentUserId), currentUserId);
    mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
            Integer.toString(currentUserId), currentUserId);
    mSystemServiceManager.startUser(currentUserId);

    synchronized (this) {
        // Only start up encryption-aware persistent apps; once user is
        // unlocked we'll come back around and start unaware apps
       startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);

        // Start up initial activity.
        mBooting = true;
        // Enable home activity for system user, so that the system can always boot. We don't
        // do this when the system user is not setup since the setup wizard should be the one
        // to handle home activity in this case.
        if (UserManager.isSplitSystemUser() &&
                Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) {
            ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
            try {
                AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
                        UserHandle.USER_SYSTEM);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }
        startHomeActivityLocked(currentUserId, "systemReady");

        try {
            if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
                Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
                        + " data partition or your device will be unstable.");
                mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget();
            }
        } catch (RemoteException e) {
        }

        if (!Build.isBuildConsistent()) {
            Slog.e(TAG, "Build fingerprint is not consistent, warning user");
            mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_UI_MSG).sendToTarget();
        }
        long ident = Binder.clearCallingIdentity();
        try {
            Intent intent = new Intent(Intent.ACTION_USER_STARTED);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                    | Intent.FLAG_RECEIVER_FOREGROUND);
            intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
            broadcastIntentLocked(null, null, intent,
                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                    null, false, false, MY_PID, SYSTEM_UID,
                    currentUserId);
            intent = new Intent(Intent.ACTION_USER_STARTING);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
            broadcastIntentLocked(null, null, intent,
                    null, new IIntentReceiver.Stub() {
                        @Override
                        public void performReceive(Intent intent, int resultCode, String data,
                                Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                                throws RemoteException {
                        }
                    }, 0, null, null,
                    new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
                    null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
        } catch (Throwable t) {
            Slog.wtf(TAG, "Failed sending first user broadcasts", t);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        mStackSupervisor.resumeFocusedStackTopActivityLocked();
        mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
        traceLog.traceEnd(); // ActivityManagerStartApps
        traceLog.traceEnd(); // PhaseActivityManagerReady
    }
}
boolean startHomeActivityLocked(int userId, String reason) {
    if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
            && mTopAction == null) {
        // We are running in factory test mode, but unable to find
        // the factory test app, so just sit around displaying the
        // error message and don't try to start anything.
        return false;
    }
    Intent intent = getHomeIntent();
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    if (aInfo != null) {
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        // Don't do this if the home app is currently being instrumented.
        aInfo = new ActivityInfo(aInfo);
        aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
        ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                aInfo.applicationInfo.uid, true);
        if (app == null || app.instr == null) {
            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
            final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
            // For ANR debugging to verify if the user activity is the one that actually launched.
            final String myReason = reason + ":" + userId + ":" + resolvedUserId;
            mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
        }
    } else {
        Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
    }
    return true;
}
Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

9. Log抓取与分析方法

开机时间主要分析kernel log、events log、logcat log

adb shell dmesg > dmesg.txt
adb logcat –v threadtime –b events –d > logcat_events.log
adb logcat –v threadtime –d *:V > logcat.txt

高通平台分析kernel log:

01-01 13:32:28.012 I/KPI ( 0): Bootloader start count = 26437
01-01 13:32:28.012 I/KPI ( 0): Bootloader end count = 199388
01-01 13:32:28.012 I/KPI ( 0): Bootloader display count = 101764
01-01 13:32:28.012 I/KPI ( 0): Bootloader load kernel count = 3097
01-01 13:32:28.012 I/KPI ( 0): Kernel MPM timestamp = 226876
01-01 13:32:28.012 I/KPI ( 0): Kernel MPM Clock frequency = 32768

根据log可以获取以下信息:

  • NHLOS时间:Bootloader start count / Kernel MPM Clock frequency = 26437 / 32768 = 0.807s
  • lk启动时间:(Bootloader end count-Bootloader start count) / Kernel MPM Clock frequency = (199388 - 26437) / 32768 = 5.278s
  • bootloader启动时间:Kernel MPM timestamp / Kernel MPM Clock frequency = 226876 / 32768 = 6.924s

MTK平台分析bootprof:

<< /proc/bootprof >>:
----------------------------------------
0       BOOT PROF (unit:msec)
----------------------------------------
      5074        : preloader
      2808        : lk (Start->Show logo: 1282)

根据log可以获取以下信息:

  • perloader启动时间是5074ms
  • lk启动时间是2808ms

Events Log分析:

01-01 13:14:19.129 674 674 I boot_progress_start: 12401
01-01 13:14:20.135 674 674 I boot_progress_preload_start: 13408
01-01 13:14:21.025 675 675 I boot_progress_preload_start: 14297
01-01 13:14:21.935 674 674 I boot_progress_preload_end: 15208
01-01 13:14:22.519 675 675 I boot_progress_preload_end: 15792
01-01 13:14:22.660 1370 1370 I boot_progress_system_run: 15932
01-01 13:14:23.152 1370 1370 I boot_progress_pms_start: 16425
01-01 13:14:23.794 1370 1370 I boot_progress_pms_system_scan_start: 17067
01-01 13:14:25.566 1370 1370 I boot_progress_pms_data_scan_start: 18838
01-01 13:14:25.619 1370 1370 I boot_progress_pms_scan_end: 18892
01-01 13:14:27.060 1370 1370 I boot_progress_pms_ready: 20332
01-01 13:14:29.302 1370 1370 I boot_progress_ams_ready: 22574
01-01 13:14:30.472 1370 1455 I boot_progress_enable_screen: 23744
01-01 13:14:32.181 492 535 I sf_stop_bootanim: 25453
01-01 13:14:32.254 492 492 I sf_frame_dur: [BootAnimation,12,331,3,1,0,1,1]  // 25506 
01-01 13:14:32.343 1370 1480 I wm_boot_animation_done: 25616
Kernel part: boot_progress_start = 12401ms
Zygote time: boot_progress_preload_end - boot_progress_preload_start = 15792 - 13408 = 2384ms
System folder Scan time: boot_progress_pms_data_scan_start- boot_progress_pms_system_scan_start = 18838 - 17067 = 1771ms
Data folder scan time: boot_progress_pms_scan_end- boot_progress_pms_data_scan_start = 18892 - 18838 = 54ms
Home activity start time: boot_progress_enable_screen- boot_progress_ams_ready = 23744 - 22574 = 1170ms
Home activity idle to Bootanimation finish: sf_frame_dur - boot_progress_enable_screen = 25506 - 23744 = 1762ms
Home activity idle to SF stop bootanim: sf_stop_bootanim - boot_progress_enable_screen = 25453 - 23744 = 1709ms
Bootanim end time: wm_boot_animation_done - sf_stop_bootanim = 25616 - 25453 = 163ms
Log含义

结束语

到此Android的开机流程就分析完了,比较仓促,有许多不足的地方,开机过程中涉及的许多文件未有说明,如kernel下的defconfig文件,通过配置config文件的宏控,打开某些功能,这些config都会影响到开机的时间,eng、userdebug和user版的差异最大的地方就是这个defconfig的配置,调试的宏控开多了,会大大影响开机时间,曾经试过在eng版本上开机时间长达十分钟的,所以说,要优化开机时间,可以考虑从defconfig文件的配置入手。

了解开机时间流程是为了解Android的整体架构,在此做一下记录,与大家共勉。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容