ActivityManagerService启动过程(基于android 8.0)

下边这个图是7.0 的


AMS类的结构,copy自网络

1.看得出AMS 实现了看门狗(Watchdog.Monitor)以及电量监控(BatteryStatsImpl.BatteryCallback) 接口,并且继承了ActivityManagerNative
2.ActivityManagerNative实现了IActivityManager,使用Binder来跟应用程序进行通信,只不过这里AMN内部增加了一个代理类解藕,最终其他进程要跟AMS交互还是使用Binder机制。
这里很好玩的是8.0系统上ActivityManagerNative上已经被delete

/**
 * {@hide}
 * @deprecated will be removed soon. See individual methods for alternatives.
 */
@Deprecated
public abstract class ActivityManagerNative

而且本身的AMS的继承类也相应的变化了:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

这里的它的区别是继承了IActivityManager.Stub 接口类,了解Bindler机制的人应该知道此处应该是一个IActivityManager.aidl生成的java类。只不过这里android可能删除了ActivityManagerNative这个类,并把一些Binder代码转化为了AIDL模版方式。
可以看下下边两个sdk中的代码:
8.0上:
ActivityManagerNative.class中的代码:

 /**
     * Retrieve the system's default/global activity manager.
     *
     * @deprecated use ActivityManager.getService instead.
     */
    static public IActivityManager getDefault() {
        return ActivityManager.getService();
    }

ActivityManager.class 中的代码:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

7.0上:
ActivityManagerNative.class中的代码:

/**
*获得IActivityManager类
*/
static public IActivityManager getDefault() {
        return gDefault.get();
    }

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
 
        return new ActivityManagerProxy(obj);

ActivityManager.class 中的代码:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);//注意这一行
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

可以看得出来,两个的写法不一样,本质上都是一样的,只不过这里android可能使用了统一的AIDL方式进行ipc,减少了代码的维护。所以我们在写ipc的时候还是使用aidl模版比较好,利于维护。

好了有点扯远了,回到正题上AMS的启动过程:

AMS的启动是在SystemServer(系统进程)中进行启动的,我们知道android所有的进程都是由zygote fork出来的,SystemServer也不例外。下边捋一下SystemServer的代码:

SystemServer
/**
     * The main entry point from zygote.
     */
//很清楚看到是由zygote进程fork来的
    public static void main(String[] args) {
        new SystemServer().run();
    }

run方法:

private void run() {
           ....
             (1)
            Looper.prepareMainLooper();

            // Initialize native services.
            System.loadLibrary("android_servers");
          ....
             (2)
            // Initialize the system context.
            createSystemContext();  
             (3)
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext); 
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
           ....
          (4) 
        // 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();
        }
        ....
        // Loop forever.
        Looper.loop();
         (5)
        throw new RuntimeException("Main thread loop unexpectedly exited");
}
  • (1).Looper.prepareMainLooper();方法:

初始化MainLooper,这里可以看得出我们这个SystemServer本身可能就是一个应用进程。
这里稍微扩展一下Looper.prepareMainLooper()函数是创建了一个全局静态的sMainLooper,创建函数是:

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

1.这里我当时没想明白是怎么把ActivityThread跟Looper进行绑定的,毕竟ActivityThread是在Looper初始化之后new的,而Looper的new过程是伴随着绑定当前线程的。这里我们一定要注意:
ActivityThread不是一个线程,尽管以此命名,我们new的ActivityThread只不过是一个普通类。同时行使主线程的能力罢了。
2.这里的Looper是使用sThreadLocal保证全局唯一的,ThreadLocal也是一个很有意思的类,它可以看作是一个Map的工具类,使用统一的工具类管理各个分散在不同Thread中的ThreadLocalMap,以ThreadLocal为key,管理各个thread中map值,当然这里必须使用弱引用防止内存问题。这种统一管理方式很值得学习。

  • (2)createSystemContext方法:

1.得到了一个ActivityThread对象,它代表当前进程 (此时为系统进程) 的主线程;
2.得到了一个Context对象,对于SystemServer而言,它包含的Application运行环境与framework-res.apk有关。

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);
    }
public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }
  • (3)创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。
  • (5)throw new RuntimeException("Main thread loop unexpectedly exited");

这里一种防止Looper quit的一种方式

  • (4) 启动各种service,这里startBootstrapServices ()方法是初始化AMS的,只需要看此方法即可
      private void startBootstrapServices() {
....
        Installer installer = mSystemServiceManager.startService(Installer.class);
....
        // Activity manager runs the show.
        //真正启动AMS的地方
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
....
// Set up the Application instance for the system process and get started. 
    //注册一些系统服务
//将framework-res.apk的信息加入到SystemServer对应的LoadedApk中,
//同时构建SystemServer进程对应的ProcessRecord, 以将SystemServer进程纳入到AMS的管理中。
        mActivityManagerService.setSystemProcess();
....
    }

可以看出AMS是使用SystemServiceManager(SSM)启动的,SSM启动的service必须继承自final Class<SystemService> serviceClass;,但是这里因为AMS并不是,所以使用了ActivityManagerService.Lifecycle.class类。

    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();
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }

很简单这只不过是AMS 的代理类,也是为了解藕,这种启动Service的处理方式蛮特别的。可以学习下SystemServiceManager的源码,这里不做深入。

这里Lifecycle.class中有两步操作 ,

  1. mService = new ActivityManagerService(context);
// Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext) {
        ...
        mServices = new ActiveServices(this);
        mProviderMap = new ProviderMap(this);
        mAppErrors = new AppErrors(mUiContext, this);
        ...
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }

可以看得出来AMS的构造方法中都是一些初始化操作,以及增加了看门狗

  1. mService.start();
private void start() {
        //完成统计前的复位工作
        removeAllProcessGroups();
        //开始监控进程的CPU使用情况
        mProcessCpuThread.start();
        //注册服务
        mBatteryStatsService.publish(mContext);
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
        // Wait for the synchronized block started in mProcessCpuThread,
        // so that any other acccess to mProcessCpuTracker from main thread
        // will be blocked during mProcessCpuTracker initialization.
        try {
            mProcessCpuInitLatch.await();
        } catch (InterruptedException e) {
            Slog.wtf(TAG, "Interrupted wait during start", e);
            Thread.currentThread().interrupt();
            throw new IllegalStateException("Interrupted wait during start");
        }
    }

主要处理了:
1、启动CPU监控线程。该线程将会开始统计不同进程使用CPU的情况。
2、发布一些服务,如BatteryStatsService、AppOpsService(权限管理相关)和本地实现的继承ActivityManagerInternal的服务。

看上边的startBootstrapServices方法中mActivityManagerService.setSystemProcess()方法

public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            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.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 e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

此方法中主要处理了
1、注册一些服务;
2、获取package名为“android”的应用的ApplicationInfo;
3、调用ActivityThread的installSystemApplicationInfo;
4、AMS进程管理相关的操作。

这里注意installSystemApplicationInfo ()方法:它主要处理了将package名为“android”的应用的ApplicationInfo;(即framework-res.apk,资源apk)赋值给LoadedApk,这里不详细拆分
SystemServer.run()startOtherServices();方法中有一类似的代码mActivityManagerService.installSystemProviders();此方法是加载运行在SystemServer进程中的ContentProvider,即SettingsProvider.apk (定义于frameworks/base/packages/SettingsProvider)。最终ContentProvider信息都将注册到AMS中的mProviderMap集合中。

最后一步SystemSever#startOtherServices中调用ActivityManagerService#systemReady方法

public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
...
//通知一些服务可以进行systemReady相关的工作,并进行启动服务或应用进程的工作
...
//开启HomeActivity
startHomeActivityLocked(currentUserId, "systemReady");
...
}

到此我们的AMS已经启动完全,后续是Activity的启动流程,这里不做讲解。

鉴于时间限制,我就盗用下边的流程图作为总结吧。。。。


AMS的启动流程图

其他:

  • AMS的通信机制:(使用AIDL)

APP向AMS发起进程间通信:(IActivityManager.aidl)
ActivityManger.getService() 获得AMS的Binder接口,在通过Stub.asInterface的方式,转成IActivityManager的接口。然后就可以通过IActivityManager向AMS发起进程间通信。

// android/app/Instrumentation.java
int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);

// android/app/ActivityManager.java
public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
 
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

AMS向APP发起进程间通信:(IApplication.aidl)
在AMS内部持有每个ActivityThread的IApplication接口实例,用时可以直接调用。当然这里也是Binder通信。
其实在ActivityThread.main()时会调用attach(bool)方法

private void attach(boolean system) {
      ...
        if (!system) {
           ...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //将IApplication注册给AMS
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
           ...
    }
 @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
           ...
            attachApplicationLocked(thread, callingPid);
          ...  
        }
    }
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
...
        updateLruProcessLocked(app, false, null);
...
 final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
...
        //AMS中 final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
         mLruProcesses.add(app);
...

反正一系列的方法最后将IApplication传递到了AMS中,等到AMS调用APP时使用。看下图:


AMS跟应用进程通信
  • AMS本身运行在SystemServer 中,但同时也管理SystemServer(可以看作一个特殊APP)

  • SettingProvider.apk

SettingProvider.apk 给Settings应用提供设置默认值、设置存储和设置修改服务。其源码在frameworks/base/packages目录下。其apk在设备上的位置:/system/priv-app/SettingsProvider。本次对SettingProvider的修改主要针对一些设置默认值

Framework-res.apk

系统默认的一些资源信息

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

推荐阅读更多精彩内容