美文网首页
AMS系列①—AMS的启动

AMS系列①—AMS的启动

作者: leap_ | 来源:发表于2020-10-19 21:31 被阅读0次

AMS作为Android FrameWork中最核心的一个部分,是应用层开发者进阶的里程碑,本文是AMS专栏的第一篇文章,介绍AMS的启动相关:

在学习AMS之前,需要掌握一些基础知识:

在学习完上面的内容后,我们可以知道AMS的启动是由SystemServer进程发起的:

AMS的入口方法SystemServer的main()做了两件事:

  • 调用CreateSystemContext()创建SystemContext
  • 开启三类服务:引导服务,核心服务,其他服务

1. SystemServer.createSystemContext():

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
    }

ActivityThread.systemMain():

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

在SystemMain中,首先创建了一个SystemServer进程的ActivityThread,没错,这就是用户进程的入口main的那个ActivityThread,所以从某种意义上讲,我们也可以将SystemServer进程看成一个App;

调用了ActivityThread的attach(),注意,这里传入的是true,而我们正常的App传入的是false,这个字段表示是否是系统进程(SystemServer进程):

ActivityThread.attach():

    private void attach(boolean system, long startSeq) {
...
        if (!system) {    //  如果是正常App进程,传入false
...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } 
...
        } else {   //  如果是SystemServer进程,传入true
...
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } 
        }
    }

如果是正常的APP,那么进入if逻辑,调用AMS的代理发起一次Binder消息,实际调用AMS的attachApplication();
在本次情况中是由SystemServer进程发起的,进入else逻辑:

  • 调用ContextImpl.createAppContext()创建App Context
  • 注意上一个方法,传入了一个getSystemContext().mPackageInfo参数
  • 调用makeApplication创建Application

我们先来看传入的参数:

ActivityThread.getSystemContext()

    public ContextImpl getSystemContext() {
        synchronized (this) {
                mSystemContext = ContextImpl.createSystemContext(this);
    }

getSystemContext()调用了ContextImpl的createSystemContext():

ContextImpl.createSystemContext():

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        return context;
    }

ContextImpl有一系列的创建Context的static 方法:



在这里创建了SystemContext,Context的具体作用就是用来获取资源,比如你的Activity需要使用apk里面的资源,而系统SystemServer也需要使用系统预设的资源文件,所以在这里也创建了一个Context对象;

那么Context是如何获取资源的呢?答案是LoadedApk这个类,LoadedApk是apk文件在内存中的存在形式
所以一般ApplicationContext或者ActivityContext都会持有它对应的apk文件的内存形式LoadedApk对象;那么我们的SystemServer是跟哪个APK绑定呢???看下面这张图就明白了:

虽然它是一个LoadedAPK对象,但是并没有对应apk文件,它存在的意义就是为SystemContext服务,为它提供获取系统资源的能力;注意倒数第二第三行,SystemClassLoader,SystemResource,如果是通过其他构造方法创建的LoadedApk,就不会有这个值,他们是通过对应apk文件解析出来的数据;

至此,我们的SystemContext创建完毕,回到ActivityThread.attach():这一步,参数看好了,参数就是SystemContext的LoadedApk,就是那个没有apk的LoadedAPK;

ContextImpl.CreateAppContext:

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        return context;
    }

在这里因为传入的LoadedAPK是被阉割的LoadedAPK对象,所以这个ApplicationContext,本质上和SystemContext一样,他们的resource都是System Resource;

context.mPackageInfo.makeApplication(true, null):

   public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        } 
...
        return app;
    }

mInstrumentation.newApplication()

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

makeApplication的逻辑就是创建Application对象,然后调用Application的attach方法:

    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

保存Application Context 和 LoadedApk到Application

至此SystemServer创建System Context的操作分析完毕,下面分析SystemServer的run()中开启三类服务中关于AMS的逻辑

SystemServer.startBootstrapServices():

    private void startBootstrapServices() {
...
       mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();

       mActivityManagerService.setInstaller(installer);

        mActivityManagerService.initPowerManagement();

        mActivityManagerService.setSystemProcess();
    }

在启动引导服务startBootstrapServices这个方法中,涉及AMS的逻辑主要做了四件事:

  1. 创建AMS实例
  2. 设置installer,App安装器
  3. 初始化PMS
  4. 调用setSystemProcess()

1. startService(ActivityManagerService.Lifecycle.class).getService();

startService()传入了一个AMS的内部类Lifecycle的Class对象,会创建一个Lifecycle的实例,接着这个Lifecycle会调用自己的getService方法获取AMS实例:

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

下面看一下AMS的构造方法,AMS的构造方法中,做了很多事情:

   public ActivityManagerService(Context systemContext) {
...
        // 前台服务线程 
        mHandlerThread = new ServiceThread(TAG,
                THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);

             //  后台服务线程
            sKillThread = new ServiceThread(TAG + ":kill",
                    THREAD_PRIORITY_BACKGROUND, true /* allowIo */);

         // CPU线程
        mProcessCpuThread = new Thread("CpuTracker") ;

         //  AMS家族:
        mConstants = new ActivityManagerConstants(this, mHandler);
        mServices = new ActiveServices(this);
        mStackSupervisor = createStackSupervisor();
        mActivityStartController = new ActivityStartController(this);

        //  开启 watch dog
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);

         // 创建 AppOpsService , Android原生应用程序权限管理相关
        mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);

        //创建进程状态服务,监听进程转发服务
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));

        //创建电量状态服务
        mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);


    }

在AMS的构造方法中,大概做了以下几件事:

  1. 创建各个工作线程,前台服务线程,后台服务线程,CPU线程
  2. 实例化AMS家族成员,ActivityManagerConstants,ActiveServices,StackSupervisor,ActivityStartController,这些在后续会详细介绍;
  3. 开启各种服务,watch dog,Appops,ProcessStatsService,BatteryStatsService
  • 软件看门狗来监控SystemServer中的线程。一旦发现问题,WatchDog会杀死SystemServer进程。SystemServer的父进程Zygote接收到SystemServer的死亡信号后,会杀死自己。Zygote进程死亡的信号传递到Init进程后,Init进程会杀死Zygote进程所有的子进程并重启Zygote。这样整个手机相当于重启一遍。通常SystemServer出现问题和kernel并没有关系,所以这种“软重启”大部分时候都能够解决问题。而且这种“软重启”的速度更快,对用户的影响也更小。
至此,第一步AMS的实例化分析完毕,步骤2 和 步骤3 是设置APk安装器和初始化PMS,不做过多介绍,下面详细看下步骤4setSystemProcess()

4 mActivityManagerService.setSystemProcess();

    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_HIGH);
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this),
                        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
            }
        } 

        // Start watching app ops after we and the package manager are up and running.
        mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null);
    }

在AMS的setSystemProcess()中主要做了四件事:

  1. 添加各种服务到ServiceManager中:this(自己AMS服务),内存,图像,权限,cpu,进程,相关服务
  2. installSystemApplicationInfo
  3. 创建ProcessRecord对象
  4. 调用AppOps服务的startWatch方法开启对应用程序包给定权限的监听;
步骤2:installSystemApplicationInfo():
    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        synchronized (this) {
            getSystemContext().installSystemApplicationInfo(info, classLoader);
            getSystemUiContext().installSystemApplicationInfo(info, classLoader);

            // give ourselves a default profiler
            mProfiler = new Profiler();
        }
    }

步骤2做了两件事:

  • 将ApplicationInfo对象设置给SystemContext
  • 创建Profiler对象,用于性能统计

至此SystemService开启引导服务中AMS相关的逻辑分析完毕;


SystemServer.startOtherServices():

mActivityManagerService.systemReady(() -> {
            mSystemServiceManager.startBootPhase(
            try {
                mActivityManagerService.startObservingNativeCrashes();
            }  
    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {


            mVrController.onSystemReady();
            mUserController.onSystemReady();
            mRecentTasks.onSystemReadyLocked();
            mAppOpsService.systemReady();
            mSystemReady = true;

            startHomeActivityLocked(currentUserId, "systemReady");
    }

在startOtherServices()中,AMS的主要逻辑就是调用了SystemReady()开启一个Activity,开启Activity的内容后期再讲,会设计AMS的大家族;

相关文章

网友评论

      本文标题:AMS系列①—AMS的启动

      本文链接:https://www.haomeiwen.com/subject/uirfmktx.html