android6.0源码分析之ams服务源码分析

古冥 古冥     2022-12-06     452

关键词:

activitymanagerservice服务源码分析


1、ActivityManagerService概述


ActivityManagerService(以下简称AMS)作为android中最核心的服务,主要负责系统的四大组件的启动、切换、调度以及应用进程的管理和调度等工作。它类似于操作系统中的进程管理和调度模块类似,所以要想掌握android,AMS至关重要。AMS属于service的一种,所以它也是由system_server进行启动以及管理。本文将以两条不同的主线来分析AMS:第一条与其他服务一样,分析system_server中AMS的调用轨迹;第二条将分析一个Activity的启动过程,而Activity的启动过程将在下一篇中进行分析。
先来看AMS的家族图谱:

图中有一个ActivityManager类,由于ActivityManagerService是系统的核心服务,很多API不能开放给客户端使用,所以在家族图谱中增加了ActivityManager类,ActivityManager类通过调用ActivityManagerNative的getDefault函数来得到一个ActivityManagerProxy对象,通过它就可以实现ActivityManager与AMS的交互。


2、AMS的调用流程分析


AMS作为系统的核心服务,由system_server创建,system_server由Zygote进程的startsystemserver触发,此处以android6.0源码为基础,分析其run函数:

private void run()
    ...
    //初始化native servers
    System.loadLibrary("android_servers");
    ...
    //初始化system context
    createSystemContext();
    //创建System service manager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class,mSystemServiceManager);

    //start services
    try
        startBootstrapservices();
        startCoreServices();
        startOtherServices();
    catch(Throwable ex)
        throw ex;
    
    ...
    Looper.loop();
    ...

2.1 createSystemContext()方法分析


private void createSystemContext()
    //创建一个ActivityThread对象,它代表应用进程的主线程
    ActivityThread activityThread = ActivityThread.systemMain();
    //获取一个和应用进程一样的android运行上下文环境
    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函数,记住,此处attach函数传入的参数为true而在分析Activity启动的时候,它会为false,到时再对比分析。此处继续分析attach函数:

private void attach(boolean system) 
    ...
    if (!system) //此处为true,所以不会执行此处代码
        ...
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
            UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try 
            mgr.attachApplication(mAppThread);
         catch (RemoteException ex) 
            // Ignore
        
        ...
     else //执行此分支
        android.ddm.DdmHandleAppName.setAppName("system_process",
            UserHandle.myUserId());
        try 
            mInstrumentation = new Instrumentation();
            //由ContextImol创建Context对象
            ContextImpl context = ContextImpl.createAppContext(
                this, getSystemContext().mPackageInfo);
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
         catch (Exception e) 

        
   
   //添加Dropbox logging 到libcore
   DropBox.setReporter(new DropBoxReporter());
   ViewRootImpl.addConfigCallback(new ComponentCallbacks2()
        ...
   );
   ...

由于此处为系统服务,所以会执行else分支的代码,创建一个context对象,并且会根据Package信息来初始化一个Application对象。接着分析ActivityThread的getSystemContext()方法:

public ContextImpl getSystemContext()
    Synchronized(this)
        if(mSystemContext == null)
            mSystemContext = ContextImpl.createSystemContext(this);
        
        return mSystemContext;
    

显然,如果systemMain方法中创建Context成功,则返回,否则新建Context对象,综上,createSystemContext()方法主要功能就是,创建一个ActivityThread对象和一个ContextImpl对象,而这两个对象即组成了android运行环境。
时序图如下:

2.2 startBootstrapServices()方法分析


先看核心代码:

private void startBootStrapServices()
    //启动Installer服务
    Installer installer = mSystemServiceManager.startService(Installer.class);
    //启动ActivityManagerService服务
    mActivityManagerService = mSystemServiceManager.
        startService(ActivityManagerService.Lifecycle.class).getService();
    //启动PowerManagerService服务
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    ...
    //初始化属性缓存
    AttributeCache.init(mSystemContext);
    mActivityManagerService.setSystemProcess();

    startSensorService();

代码中,会将一系列的服务添加到servicemanager管理,主要包括Installer,AMS,PMS等系统服务,并初始化属性缓存,最后会调用AMS的setSystemProcess()方法将sytem_server进程并入AMS的管理范围,继续分析setSystemProcess()方法:

public void setSystemProcess()
    try
        //添加ActvityManagerService等服务到ServiceManager
        ServiceManager.addService(Context.ACTIVITY_SERVICE,this,true);
        ...
        ServiceManager.addService("meminfo",new MemBinder(this));
        ServiceManager.addService("gfxinfo",new GraohicsBinder(this));
        ServiceManager.addService("dbinfo"new DbBinder(this));
        ...
        //从packagemanagerservice中获取ApplicationInfo信息
        ApplicationInfo info = mContext.getPackageManager()
            .getApplicationInfo("android",STOCK_PM_FLAGS);
        //根据info初始化android运行环境,即ActivityThread以及ContextImpl对象
        mSystemThread.installSystemApplicationInfo(info,getClass().getClassLoader());
        synchronized(this)
            //创建新的进程
            ProcessRecord app = newProcessRecordLocked(info,info.processName,false,0);
            app.persistent = true;
            app.pid = MY_PID;
            app.maxAdj = ProcessList.SYSTEM_ADJ;
            //绑定主线程
            app.makeActive(mSystemThread.getApplicationThread(),mProcessStats);
            synchronized(mPidsSelfLocked)
                mPidsSelfLocked.put(app.pid,app);
            
            //更新进程管理
            updateLruProcessLocked(app,false,null);
            updateOomAdjLocked();
        catch(PackageManager.NameNotFoundException ex)
            throw new RuntimeException("unable to find android system package",ex);
        
    

首先分析installSystemApplicationInfo方法,它依次调用ActivityThread->ContextImpl->LoadedApk等的installSystemApplicationInfo方法,LoadedApk中的代码如下:

void installSystemApplicationInfo(ApplicationInfo info,ClassLoader classLoader)
    assert info.packageName.equals("android");
    mApplicationInfo = info;
    mClassLoader = classLoader;

显然,是根据先前从Package里面获取的ApplicationInfo对系统的应用信息进行初始化,主要包括ApplicationInfo以及ClassLoader对象。
接着,分析创建新进程的方法newProcessRecordLocked():

final ProcessRecord newProcessRecordLocked(ApplicationInfo info,String customProcess,
    boolean isolated,int isolatedUid)
    ...
    final ProcessRecord r = new ProcessRecord(stats,info,proc,uid);
    ...
    addProcessNameLocked(r);
    return r;

它首先创建一个进程对象ProcessRecord,并将其加入到自定义的ProcessMap类型的容器里,最后返回。
最后,分析更新进程管理updateLruProcessLocked()方法:

final updateLruProcessLocked(ProcessRecord app,boolean activityChange,ProcessRecord client)
    final boolean hasActivity = app.activities.size()>0||app.hasClientActivities
        ||app.treatLikeActivity;
    final boolean hasService = false;//android 6.0没实现
    //如果没有Activity切换,切当前进程有Activity存在,则进程调度直接返回
    if(!activityChange&&hasActivity)
        return;
    
    ...
    //记录下一个进程的索引
    int nextIndex;
    if(hasActivity)
        //获取Lru进程表中进程的数量
        final int N = mLruProcesses.size();
        //该进程没有activity,而进程表中其他进程有activity
        if(app.activities.size() == 0&&mLruProcessActivityStart<(N-1))
            //将进程加入进程表
            mLruProcesses.add(N-1,app);
            ...//将其调整到第二个进程位置
        else//如果该进程有activity
            //直接将其加入到Lru进程表顶端
            mLruProcesses.add(app);
        
        nextIndex = mLruProcessesServiceStart;
    else if(hasService)
        //如果有service存在,将它加入到service链表的顶端
        mLruProcesses.add(mLruProcessActivityStart,app);
        nextIndex = mLruProcessServiceStart;
        mLruProcessServiceStart++;
    else
        //如果是新建进程
        int index = mLruProcessServiceStart;
        if(client!=null)
            int clientIndex = mLruProcesses.lastIndexOf(client);
            if(clientIndex <= lrui)
                clientIndex = lrui;
            
            if(clientIndex >= 0&&index > clientIndex)
                index = clientIndex;
            
        
        mLruProcesses.add(index,app);
        ...
    
    ...

此段代码就是进程LRU进程调度,具体参考注释。
小结:startBootStrapServices()主要是进行一系列的服务的注册,并且初始化进程信息,并将其加入到Lru进程表进行调度,同时也将System_server进程纳入AMS的管理。

2.3 startOtherServices()方法分析


与ActivityManagerService有关的核心代码如下:

private void startOtherServices()
    final Context context = mSystemContext;
    //启动一系列的服务,CameraService,Account Manager,Telephony registry等
    ...
    //启动settingProvider,它提供配置信息
    mActivityManagerService.installSystemProviders();
    ...
    //初始化窗口管理服务
    wm = WindowManagerService.main(content,inputManager,mFactoryTestMode != 
        FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot,mOnlyCore);
    ServiceManager.addService(Context.WINDOW_SERVICE,wm);
    ServiceManager.addService(Context.INPUT_SERVICE,inputManager);
    //在内部保存窗口管理服务WMS
    mActivityManagerService.setWindowManager(wm);
    ...
    //和WMS交互,弹出“启动进度”对话框
    mActivityManagerNative.getDefault().showBootMessage(context.getResources().getText(
        com.android.internal.R.String.android_upgrading_starting_apps));
    ...
    mActivityManagerService.systemReady(new Runnable()
        @Override
        public void run()
            ...
            //标记服务(services)准备完毕
            mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
            ...
            try
                //启动桌面
                startSystemUi(context);
            
            ...
        
    );

首先,分析installSystemProviders()方法:

public final void installSystemProviders()
    List<ProviderInfo> providers;
    synchronized(this)
        ProcessRecord app = mProcessNames.get("system",Process.SYSTEM_UID);
        //根据进程名以及进程uid向PKMS查询满足要求的ProviderInfo
        providers = generateApplicationProvidersLocked(app);
        ...
    
    if(providers != null)
        mSystemThread.installSystemProviders(providers);
    
    ...

从进程Map表里,根据进程名字system来获取进程,并根据进程app来获取其应用信息中的providers,接着调用ActivityThread的installSystemProviders()方法来进行配置信息解析。

//ActivityThread.java
public final void installSystemProviders(List<ProviderInfo> providers)
    if(providers != null)
        installContentProviders(mInitialApplication,providers);
    

跟踪installContentProviders()方法:

private void installContentProviders(Context context,List<ProviderInfo> providers)
    final ArrayList<IActivityManager.ContentProviderHolder> results = 
        new ArrayList<IActivityManager.ContentProviderHolder>();
    for(ProviderInfo cpi:providers)
        //通过调用istallProvider函数获得一个ContentProviderHolder对象
        IActivityManager.ContentProviderHolder cph = installProvider(context,null,cpi,false
            ,true,true);
        if(cph != null)
            cph.noReleaseNeeded = true;
            //保存获得的cph对象
            results.add(cph);
        
    
    try
        //调用AMS的publishContentProvider注册此前的results里的cph。
        ActivityManagerNative.getDefault().publishContentProviders(getApplicationThread(),
            results);
    catch(RemoteException ex)
    

从代码可以看出,首先调用installProvider函数获得一个ContentProviderHolder对象,并将其保存在容器中,最后在调用AMS的publishContentProvider来注册容器中的所有ContentProviderHolder对象。至此,一个SettingProvider对象就正式的注册到了AMS.
继续分析startOtherServices()方法中mActivityManagerService.systemReady(final Runnable goingcallback)方法:

public void systemReady(final Runnable goingCallback)
    synchronized(this)
        if(mSystemReady)//系统已经准备好,直接调用goingCallback的run方法,而我们此处为false
            if(goingCallbak != null)
                goingCallback.run();
            
            return;
        
        ...
        if(!mDidUpdate)//检查是否有升级更新
            if(mWaitingUpdate)
                return;
            
            final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
            //发送PRE_BOOT_COMPLETE广播
            mWaitingUpdate = deliverPreootCompleted(new Runnable()
                public void run()
                    synchronized(ActivityManagerService.this)
                        mDidUpdate = true;
                    
                    showBootMessage(mContext.getText(R.string.android_upgrading_complete),false);
                    writeLastDonePreBootReceivers(doneReceivers);
                    //此处调用函数本身,再次执行
                    systemReady(goingCallback);
                
            ,doneReceivers,UserHandle.USER_OWNER);
            if(mWaitingUpdate)
                return;
            
            mDidUpdate = true;
        
        mAppOpsService.systemReady();
        //将mSystemReady标记为true,即表示系统准备好
        mSystemReady = true;
    
    ...
    retrieveSettings();
    loadResourcesOnSystemReady();
    synchronized(this)
        readGrantedUriPermissionsLocked();
    
    //此处执行函数传入的回调的run方法,主要是启动SystemUIService
    if(goingCallback != null)
        goingCallback.run();
    
    ...
    synchronized(this)
        if(mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL)
            try
                //从PKMS中找出所有persistent属性为1的ApplicationInfo
                List apps = AppGlobals.getPackageManager().getPersistentApplications(
                    STOCK_PM_FLAGS);
                if(apps != null)
                    int N = apps.size();
                    int i;
                    for(i=0;i<N;i++)
                        ApplicationInfo info = (ApplicationInfo)apps.get(i);
                        if(info != null&&!info.packageName.equals("android"))
                            //逐个启动该Application所在的进程
                            addAppLocked(info,false,null);
                        
                    
                
            
        
    
    ...
    //启动初始化Activity
    mBooting = true;
    startHomeActivityLocked(mCurrentUserId,"systemReady");
    ...
    mStackSupervisor.resumeTopActivitiesLocked();
    sendUserSwitchBroadcastsLocked(-1,mCurrentUserId);
    

首先,检查系统是否是更新,并发送PRE_BOOT_COMPLETE广播,并将mSystemReady置为true。接着调用函数传入的回调goingCallback的run方法,在run方法中主要功能是启动SystemUIService服务,其代码如下:

static final void startSystemUi(Context context)
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
        "com.android.systemui.SystemUIService"));
        context.startServiceAsUser(intent,UserHandle.OWNER);

它主要是启动了一个SystemUIService服务,此服务由SystemUi.apk提供,实现了状态栏。执行了回调之后,systemReady方法接着,从PKMS中找出所有persistent属性为1的ApplicationInfo,并将其所在的进程逐个启动,最后再调用startHomeActivityLocked来启动Home界面,
总结:到此时,从system_server进程开始,着重分析了ActivityManagerService服务的启动过程,至此,整个系统准备完毕,此处不详细分析Home的启动过程,它的启动将会在Activity的启动过程中进行详细的分析,而Home启动成功后,AMS会发送ACTION_BOOT_COMPLETED广播。AMS的启动流程很复杂,下面给出整体的时序图:

android6.0源码分析之cameraapi2.0下的video流程分析

android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android6.0源码分析之CameraAPI2.0下的Capture流程分析android6.0源码分... 查看详情

android6.0源码分析之cameraapi2.0下的video流程分析

android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android6.0源码分析之CameraAPI2.0下的Capture流程分析android6.0源码分... 查看详情

android6.0源码分析之cameraapi2.0下的capture流程分析

...ture(拍照)流程进行分析。Camera2相关文章的目录如下:android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之 查看详情

cameraapi2.0的应用

android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android6.0源码分析之CameraAPI2.0下的Capture流程分析android6.0源码分... 查看详情

cameraapi2.0的应用

android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android6.0源码分析之CameraAPI2.0下的Capture流程分析android6.0源码分... 查看详情

android6.0源码分析之cameraapi2.0下的preview(预览)流程分析

本文将基于android6.0的源码,对CameraAPI2.0下Camera的preview的流程进行分析。在文章android6.0源码分析之CameraAPI2.0下的初始化流程分析中,已经对Camera2内置应用的Open即初始化流程进行了详细的分析,而在open过程中,定... 查看详情

android6.0源码分析之cameraapi2.0下的preview(预览)流程分析

本文将基于android6.0的源码,对CameraAPI2.0下Camera的preview的流程进行分析。在文章android6.0源码分析之CameraAPI2.0下的初始化流程分析中,已经对Camera2内置应用的Open即初始化流程进行了详细的分析,而在open过程中,定... 查看详情

android6.0源码分析之cameraapi2.0下的capture流程分析

...ture(拍照)流程进行分析。Camera2相关文章的目录如下:android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android... 查看详情

android6.0源码分析之蓝牙框架简介

待续 查看详情

android6.0源码分析之蓝牙框架简介

待续 查看详情

android6.0源码分析之camera2hal分析

...的初始化等相关流程。以下是Camera2的相关文章目录:android6.0源码分析之CameraAPI2.0简介android6.0源码分析之Camera2HAL分析android6.0源码分析之CameraAPI2.0下的初始化流程分析android6.0源码分析之CameraAPI2.0下的Preview(预览)流程分析android... 查看详情

android6.0源码分析之zygote进程分析

在android6.0源码分析之Runtime的初始化一文中,对Zygote进程的初期的Runtime初始化过程进行了分析,在Runtime启动结束后,会对Zygote进程进行初始化,其它Java进程都需要从Zygote进程来fork,而Zygote的初始化是从ZygoteIn... 查看详情

android6.0源码分析之activity启动过程

Activity最为android开发者最熟悉的组件,由ActivityManagerService服务进行调度管理,而ActivityManagerService的启动过程在activitymanagerservice服务源码分析一文中进行了详细分析,本文基于其对Activity的启动过程进行分析,同... 查看详情

android6.0源码分析之cameraapi2.0下的初始化流程分析

...CameraAPI2.0的框架以及代码做了简单介绍,本文将基于android6.0源码,分析CameraAPI2.0下的Camera2内置应用中,对Camera的初始化的流程分析,主要涉及CameraHAL3.0,Java层的IPCBinder 查看详情

android6.0源码分析之runtime的初始化

android源码分析之Runtime的初始化android运行时作为android架构的一部分,起着非常重要的作用,它和核心库(CoreLibraries)组成了Android运行时库层。本文将依据android源码对AndroidRuntime(android运行时)的建立过程进行分析。1、Android... 查看详情

android6.0源码分析之录音功能(代码片段)

从现在开始一周时间研究录音,下周出来一个完整的博客,监督,激励!!!2017-02-09--------2017-02-17------------------------------------------------------------------------------------------------ 查看详情

android6.0源码分析之cameraapi2.0简介

前面几篇主要分析的是androidCameraAPI1.0的架构以及初始化流程,而google在android5.0(Lollipop)开始对Camera的架构进行了调整,为了适应HAL3,新添加实现了CameraDeviceClient,而CameraAPI1.0已经被deprecated(即可能在更新的版本里... 查看详情

android6.0源码分析之蓝牙显示接收到的文件(代码片段)

在蓝牙界面有个menu:显示接收到的文件。本文分析显示接收到的文件chapterone---显示接收到的文件/android/packages/apps/Settings/src/com/android/settings/bluetooth/文件夹下的BluetoothSettings.java开始分析caseMENU_ID_SHOW_RECEIVED:MetricsLogger.a 查看详情