安卓开发学习OA现金盘平台出租之SystemServer启动过程

背景

这两天OA现金盘平台出租 haozbbs.com Q 1446595067 有一个需求得联调,在等待服务端同事完事,等待过程中,阅读了一下Android8.0里SystemServer的启动过程,除了设置时区语言这些,其实主要就是初始化了系统上下文以及一些服务的启动。

main()方法

SystemServer是一个进程,由zygote进程fork出来,所以它的入口方法就是main方法,代码如下

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

直接就是new了一个SystemServer,而后执行run()方法

run()方法

方法比较长,代码如下

    private void run() {
        try {
            traceBeginAndSlog("InitBeforeStartServices");
            // 如果当前系统时间早于1970年元月1号,就更新之为1970年元月1号
            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
            }

            // 设置时区
            String timezoneProperty = SystemProperties.get("persist.sys.timezone");
            if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                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", "");
            }

            // 系统Server不能进行非oneway通信,因为非oneway通信要等待对方的恢复,这个等待过程是阻塞的
            Binder.setWarnOnBlocking(true); // 所以设置阻塞时警告

            // 正式启动SystemServer

            int uptimeMillis = (int) SystemClock.elapsedRealtime();
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
            if (!mRuntimeRestart) {
                MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
            }

            // 设置vmLibrary
            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);
            }

            // 清除内存增长上限,因为加载SystemServer需要很多内存
            VMRuntime.getRuntime().clearGrowthLimit();

            // 设置内存利用率最大是0.8
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

            // 初始化指纹系统
            Build.ensureFingerprintProperty();

            // 设置访问环境变量(例如sd卡路径等)时,必须指定用户
            Environment.setUserRequired(true);

            // 设置系统的Bundle是可defuse的,意为如果在解析bundle的时候,忽略发生的badParcelableException
            // 那个异常如果发送,就直接清空这个Bundle的内容。所以defuse使能最好在Bundle到了终点后再设置,因为这样总不会导致下流再失去bundle的内容
            BaseBundle.setShouldDefuse(true);

            // 保证进入SystemServer的binder都运行在前台
            BinderInternal.disableBackgroundScheduling(true);

            // 设置最大线程数为31
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // 设置当前线程(主线程)也是在前台进行
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false); // 主线程不能自己切到后台
            Looper.prepareMainLooper(); // 主线程的消息循环开始

            // 加载native服务
            System.loadLibrary("android_servers");

            // 检测上次是否成功关机
            performPendingShutdown();

            // 初始化系统上下文
            createSystemContext();

            // 初始化SysytemServiceManager,并把它添加到LocalServices中
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // 创建SystemServerInit线程池的单例
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd(); 
        }

        // 启动一些服务
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices(); // 启动引导服务
            startCoreServices(); // 启动核心服务
            startOtherServices(); // 启动其他服务
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            ...
        } finally {
            traceEnd();
        }

        ... // 日志

        // Loop forever.
        // 开始消息循环
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited"); // 消息循环是不能退出的
    }

代码多但是逻辑并不复杂,值得注意的方法除了启动引导服务、核心服务和其他服务外,再就是检测上次关机是否成功的performPendingShutdown()方法,这个方法主要是针对recovery模式下系统更新引起的重启,这种情况要多重启一次。而这里只是设置了一下sys.powerctl属性,没有执行重启操作

performPendingShutdown()方法

代码如下

    private void performPendingShutdown() {
        final String shutdownAction = SystemProperties.get(
                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); // 获取上次的关机信息
        if (shutdownAction != null && shutdownAction.length() > 0) {
            boolean reboot = (shutdownAction.charAt(0) == '1'); // 关机信息第一位表示关机是否是为了重启

            final String reason;
            if (shutdownAction.length() > 1) {
                reason = shutdownAction.substring(1, shutdownAction.length()); // 第一位往后表示关机的原因
            } else {
                reason = null;
            }

            if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
                /*
                 * 关机原因是否是REBOOT_RECOVERY_UPDATE,也就是recovery模式下,为了执行系统更新而关的机
                 * 这种情况下,一定会多重启一次,多的这一次重启,原因就不是REBOOT_RECOVERY_UPDATE了
                 * @hide
                   public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
                 */
                File packageFile = new File(UNCRYPT_PACKAGE_FILE);
                if (packageFile.exists()) {
                    String filename = null;
                    try {
                        filename = FileUtils.readTextFile(packageFile, 0, null); // 读取uncrypt_file的内容,获取的是一个文件名
                    } catch (IOException e) {
                        Slog.e(TAG, "Error reading uncrypt package file", e);
                    }

                    if (filename != null && filename.startsWith("/data")) { // 如果读出来的文件名以/data开头,也就是在data目录内
                        if (!new File(BLOCK_MAP_FILE).exists()) { // 如果block.map文件不存在,直接抛异常,重启失败
                            Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
                                    "unexpected runtime restart?");
                            return;
                        }
                    }
                }
            }
            ShutdownThread.rebootOrShutdown(null, reboot, reason);
        }
    }

主要是调用了ShutdownThread.rebootOrShutdown()方法,这个方法只是保存了一下sys.powerctl属性,代码如下

扫描二维码关注公众号,回复: 2035547 查看本文章
    public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
        if (reboot) {
            .. // 日志
            PowerManagerService.lowLevelReboot(reason);
            .. // 日志
            reason = null;
        } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
            // 关机前要进行振动
            Vibrator vibrator = new SystemVibrator(context); // 振动器
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES); // 传入振动持续时间和振动方式
            } catch (Exception e) {
                .. // 日志
            }

            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS); // 振动是异步的,所以当前线程要阻塞一会儿,保证振动完了,再关机
            } catch (InterruptedException unused) {
            }
        }
        // Shutdown power
        PowerManagerService.lowLevelShutdown(reason);

如果是进来这个方法是要重启,reboot就是真,先调用PowerManagerService.lowLevelReboot()方法,传入重启原因reason。此方法代码如下

    public static void lowLevelReboot(String reason) {
        if (reason == null) {
            reason = "";
        }

        if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
            sQuiescent = true;
            reason = "";
        } else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
            sQuiescent = true;
            reason = reason.substring(0,
                    reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
        }

        if (reason.equals(PowerManager.REBOOT_RECOVERY)
                || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) { // 如果reason是或REBOOT_RECOVERY或REBOOT_RECOVERY_UPDATE,就把reason换成recovery
            reason = "recovery";
        }

        if (sQuiescent) { 
            reason = reason + ",quiescent";
        }

        SystemProperties.set("sys.powerctl", "reboot," + reason); // 保存sys.powerctl属性
        try {
            Thread.sleep(20 * 1000L); // 阻塞20秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
    }

可以看到,主要是把重启原因进行转换和保存,然后把重启线程阻塞20s。方法执行完后,就会执行lowLevelShutdown(),代码如下

    public static void lowLevelShutdown(String reason) {
        if (reason == null) {
            reason = "";
        }
        SystemProperties.set("sys.powerctl", "shutdown," + reason); // 保存/更新sys.powerctl属性
    }

回到SystemServer.run()方法,检测完上次是否正常关机后,调用了createSystemContext()方法获取系统上下文,代码如下

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }

这个方法主要是调用了ActivityThread的一系列方法来实现,参见文章安卓开发学习之获取系统上下文。然后就是调用startBootstrapServices()、startCoreServices()、startOtherServices()方法启动一些服务,以前两个方法为例看一下代码
startBootstrapServices()方法

启动一些引导服务,代码如下

    private void startBootstrapServices() {

        // 创建SystemConfig,进行权限的获取
        SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);

        // 开启安装器服务
        Installer installer = mSystemServiceManager.startService(Installer.class);

        // 设备识别器服务
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);

        // 启动并初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // 启动电量管理服务
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 初始化电量管理器
        mActivityManagerService.initPowerManagement();

        if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
            traceBeginAndSlog("StartRecoverySystemService");
            // 启动RecoverySystem服务
            mSystemServiceManager.startService(RecoverySystemService.class);
        }

        // 标记裸机已经启动完了,如果我们困在了运行时的重启循环中,这个标记可以跳出这个循环
        RescueParty.noteBoot(mSystemContext);

        // 启动灯光服务,包括背景亮度、闪光灯等
        mSystemServiceManager.startService(LightsService.class);

        // 启动显示服务,用来显示UI
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        // 开始开机动画
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // 加密模式下,只运行内核应用,此处先设置标志位
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            mOnlyCore = true;
        }

        // 开启包管理器服务
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        // 获取包管理器
        mPackageManager = mSystemContext.getPackageManager();

        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                try {
                    // OTADexOpt(空中下载dex并优化,用于OTA升级)使能时,启动OTA升级服务
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {
                    ..
                } finally {
                   ..      
                }
            }
        }

        // 启动用户管理服务
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);

        traceBeginAndSlog("InitAttributerCache");
        // 从系统包中初始化属性资源
        AttributeCache.init(mSystemContext);

        // 设置系统进程
        mActivityManagerService.setSystemProcess();

        // 设置ui的调度策略
        mDisplayManagerService.setupSchedulerPolicies();

        // 启动OverlayManagerService,用于定制系统界面
        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));

        // 开启传感器服务
        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
            BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(START_SENSOR_SERVICE);
            startSensorService();
            traceLog.traceEnd();
        }, START_SENSOR_SERVICE);
    }

开启了一些服务,无需多解释

startCoreServices()方法

也是启动一些服务,代码如下

    private void startCoreServices() {

        // 启动DropBox服务,用来记录系统日志
        mSystemServiceManager.startService(DropBoxManagerService.class);

        // 启动电池服务
        mSystemServiceManager.startService(BatteryService.class);

        traceBeginAndSlog("StartUsageService");
        // 启动使用状态服务
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        // 启动WebView更新服务
        mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
    }

结语

SystemService的启动过程就是如此,主要还是启动一些服务

猜你喜欢

转载自blog.51cto.com/13861409/2139634