AMS 深入了解(一、进程管理)(and5.1)

转载地址: https://blog.csdn.net/kc58236582/article/details/50065925

Android应用程序的载体是APK文件,它是一个组件和资源的容器。APK文件和我们常见的执行文件还是有区别的:每个执行文件都是运行在一个进程中,但是APK可能运行在一个进程中,也可能和其他APK运行在一个进程中。Android的设计理念中弱化进程的存在,而是以组件的概念代替。

但是Android毕竟是建立在Linux,基础的环境还是由进程组成。

一、应用进程的组成

Android应用的核心类是ActivityThread类,mActivityies,mServices、mProviderMap3个变量的类型都是ArrayMap,保存有了应用中所有的Activity、Service、ContentProvider。没有BroadcastReceiver,应用广播的生命周期比较短,属于调用一次运行一次的类型。

mInitialApplication变量是一个Application对象,应用中Application对象只有一个。如果每个应用从Application类派生了自己的类,mInitialApplication对象将是应用中自定义的实例对象。

ApplicationThread类型的变量mAppThread是一个Binder实体对象,AMS通过它来调用应用的接口。

mPackages和mResourcePackages保存的是应用apk包的信息。这里有两个变量的原因是appliction属性中,有hascode属性。如果不包含代码,只有资源文件的保存在mResourcePackages相反保存在mPackages。

1.1 ApplicationThread

ApplicationThread是ActivityThread的一个嵌套类。它不是一个Thread,是一个Binder的服务类。AMS及时通过Binder调用ApplicationThread里面的接口。

ApplicationThread继承ApplicationThreadNative,而ApplicationThreadNative又是继承Binder。对应的客户端的Binder是IApplicationThread,是在AMS中。

比如说在ApplicationThread中调用scheduleResumeActivity,最后会发送一个消息。


  
 
  1. public final void scheduleResumeActivity(IBinder token, int processState,
  2. boolean isForward, Bundle resumeArgs) {
  3. updateProcessState(processState, false);
  4. sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
  5. }

最终消息处理会去调用handleResumeActivity函数。


  
 
  1. case RESUME_ACTIVITY:
  2. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
  3. handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
  4. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  5. break;

知道这流程后,我们就知道AMS调用schedule。。。函数,最总都睡调到handle。。。函数。

1.2 Context

Context的字母意义是上下文环境。应用上层代码都是通过Context类提供的接口来操作Android的4大组件和资源的。

Context的实现类是ContextWrapper类,它其中有一个成员mBase,是ContextImpl类,这是一个典型的代理模式,好多功能都在ContextImpl实现。

而且为了方便,Service、Application、Activity都是ContextWrapper的子类。

二、AMS服务

AMS是AndroidFramework的核心,管理着四大组件。

AMS是Binder服务,但是不是通过AIDL自动生成的。AMS从ActivityManagerNative类派生,这个类实现了IActivityManager的接口。然后还有一个内部类ActivityManagerProxy,这个是应用ActivityManager调用过来的。相当于AMS的客户端Binder

一般ActivityManager中都是通过下面的方法,来获取AMS的Binder客户端

ActivityManagerNative.getDefault()
  

  
 
  1. private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
  2. protected IActivityManager create() {
  3. IBinder b = ServiceManager.getService( "activity");
  4. if ( false) {
  5. Log.v( "ActivityManager", "default service binder = " + b);
  6. }
  7. IActivityManager am = asInterface(b);
  8. if ( false) {
  9. Log.v( "ActivityManager", "default service = " + am);
  10. }
  11. return am;
  12. }
  13. };

2.1 AMS的初始化

AMS运行在SystemServer进程中:


  
 
  1. mActivityManagerService = mSystemServiceManager.startService(
  2. ActivityManagerService.Lifecycle.class).getService();
  3. mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

AMS的构造函数就是初始化一些成员变量,然后建一个消息处理handler等,这边就不分析了。

SystemServer中创建了AMS后,调用了其setSystemProcess


  
 
  1. public void setSystemProcess() {
  2. try {
  3. ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); //注册一些Service
  4. ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
  5. ServiceManager.addService( "meminfo", new MemBinder( this));
  6. ServiceManager.addService( "gfxinfo", new GraphicsBinder( this));
  7. ServiceManager.addService( "dbinfo", new DbBinder( this));
  8. if (MONITOR_CPU_USAGE) {
  9. ServiceManager.addService( "cpuinfo", new CpuBinder( this));
  10. }
  11. ServiceManager.addService( "permission", new PermissionController( this));
  12. ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
  13. "android", STOCK_PM_FLAGS);
  14. mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
  15. synchronized ( this) {
  16. ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0); //将SystemServer进程加入管理
  17. app.persistent = true;
  18. app.pid = MY_PID;
  19. app.maxAdj = ProcessList.SYSTEM_ADJ;
  20. app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
  21. mProcessNames.put(app.processName, app.uid, app);
  22. synchronized (mPidsSelfLocked) {
  23. mPidsSelfLocked.put(app.pid, app);
  24. }
  25. updateLruProcessLocked(app, false, null); //这两个方法比较关键后续会详细介绍
  26. updateOomAdjLocked();
  27. }
  28. } catch (PackageManager.NameNotFoundException e) {
  29. throw new RuntimeException(
  30. "Unable to find android system package", e);
  31. }
  32. }

在这个函数中,将一些Service注册到ServiceManager,并且最后把SystemServer加入到process的管理中。

2.2 systemReady方法

SystemServer启动完所有服务后,将调用AMS的systemReady方法。systemReady方法比较长,我们就挑一些重点说。


  
 
  1. ArrayList<ProcessRecord> procsToKill = null;
  2. synchronized(mPidsSelfLocked) {
  3. for ( int i=mPidsSelfLocked.size()- 1; i>= 0; i--) {
  4. ProcessRecord proc = mPidsSelfLocked.valueAt(i);
  5. if (!isAllowedWhileBooting(proc.info)){ //检查进程是否有persistent标志
  6. if (procsToKill == null) {
  7. procsToKill = new ArrayList<ProcessRecord>();
  8. }
  9. procsToKill.add(proc);
  10. }
  11. }
  12. }
  13. synchronized( this) {
  14. if (procsToKill != null) {
  15. for ( int i=procsToKill.size()- 1; i>= 0; i--) {
  16. ProcessRecord proc = procsToKill.get(i);
  17. Slog.i(TAG, "Removing system update proc: " + proc);
  18. removeProcessLocked(proc, true, false, "system update done");
  19. }
  20. }
  21. // Now that we have cleaned up any update processes, we
  22. // are ready to start launching real processes and know that
  23. // we won't trample on them any more.
  24. mProcessesReady = true;
  25. }

这段代码作用是找到已经启动的应用进程,然后杀掉它们。目的是为了在启动HOME前准备一个干净的环境。但是有一种进程不用退出,isAllowWhileBooting方法会判断进程是否带有FLAG_PERSISTENT标记,如果有就不用退出了。因为有这个标记还要启动它们的,这里就留下不清理了。


  
 
  1. synchronized ( this) {
  2. if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { //不在测试模式
  3. try {
  4. List apps = AppGlobals.getPackageManager().
  5. getPersistentApplications(STOCK_PM_FLAGS); //检查系统中带有FLAG_PERSISTENT标志的应用
  6. if (apps != null) {
  7. int N = apps.size();
  8. int i;
  9. for (i= 0; i<N; i++) {
  10. ApplicationInfo info
  11. = (ApplicationInfo)apps.get(i);
  12. if (info != null &&
  13. !info.packageName.equals( "android")) {
  14. addAppLocked(info, false, null /* ABI override */); //启动应用
  15. }
  16. }
  17. }
  18. } catch (RemoteException ex) {
  19. // pm is in same process, this will never happen.
  20. }
  21. }
  22. // Start up initial activity.
  23. mBooting = true;
  24. startHomeActivityLocked(mCurrentUserId, "systemReady"); //启动HOME应用
  25. ............
  26. }
  27. }

这段代码主要启动带有FLAG_PERSISTENT标志的应用,然后启动HOME应用,启动后会发出ACTION_BOOT_COMPLETED广播。

从systemReady方法可以知道:

1.系统应用如果响应ACTION_PRE_BOOT_COMPLETED,可以在升级后得到通知。

2.如果系统应用希望在HOME应用启动前启动,可以加入FLAG_PERSISTENT标志。接受Intent的ACTION_BOOT_COMPLETED的应用只能在HOME启动后启动。

2.3 Process管理

虽然Android的应用开发中,不再强调进程的概念。但是在AMS中,还必须管理和调度进程。AMS对进程的管理,主要在两个方面:

一、动态地调整进程在mLruProcess列表中的位置。

二、调整进程的oom_adj值。

这两项调整和系统进行自动内存回收有关,当内存不足时,系统会关闭一些进程来释放内存。系统就是根据oom_adj值来杀进程。值越大越可能被杀。

下面我们看下如何启动进程

在上面一节中,把带有FLAG_PERSISTENT标志的应用放进addAppLocked就可以启动应用,我们来看下这个函数:


  
 
  1. final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
  2. String abiOverride) {
  3. ProcessRecord app;
  4. if (!isolated) { //该值为true,表示要启动一个新的进程
  5. app = getProcessRecordLocked(info.processName, info.uid, true);
  6. } else {
  7. app = null;
  8. }
  9. if (app == null) {
  10. app = newProcessRecordLocked(info, null, isolated, 0); //创建一个ProcessRecord对象
  11. mProcessNames.put(info.processName, app.uid, app);
  12. if (isolated) {
  13. mIsolatedProcesses.put(app.uid, app);
  14. }
  15. updateLruProcessLocked(app, false, null);
  16. updateOomAdjLocked();
  17. }
  18. // This package really, really can not be stopped.
  19. try {
  20. AppGlobals.getPackageManager().setPackageStoppedState(
  21. info.packageName, false, UserHandle.getUserId(app.uid));
  22. } catch (RemoteException e) {
  23. } catch (IllegalArgumentException e) {
  24. Slog.w(TAG, "Failed trying to unstop package "
  25. + info.packageName + ": " + e);
  26. }
  27. if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
  28. == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
  29. app.persistent = true;
  30. app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
  31. }
  32. if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
  33. mPersistentStartingProcesses.add(app);
  34. startProcessLocked(app, "added application", app.processName, abiOverride, //启动进程
  35. null /* entryPoint */, null /* entryPointArgs */);
  36. }
  37. return app;
  38. }

这个方法会根据isolated来决定是否要启动一个进程,getProcessRecordLocked方法会在当前运行的进程列表中查找进程。updateLruProcessLocked和updateOomAdjLocked方法后面介绍。下面再来看看startProcessLocked方法:


  
 
  1. private final void startProcessLocked(ProcessRecord app, String hostingType,
  2. String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
  3. .......
  4. Process.ProcessStartResult startResult = Process.start(entryPoint,
  5. app.processName, uid, uid, gids, debugFlags, mountExternal,
  6. app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
  7. app.info.dataDir, entryPointArgs);
  8. checkTime(startTime, "startProcess: returned from zygote!");
  9. .......
  10. synchronized (mPidsSelfLocked) {
  11. this.mPidsSelfLocked.put(startResult.pid, app);
  12. if (isActivityProcess) {
  13. Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
  14. msg.obj = app;
  15. mHandler.sendMessageDelayed(msg, startResult.usingWrapper
  16. ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
  17. }
  18. }

最后会调用Process.start方法启动一个进程,启动进程后,会发送一个PROC_START_TIMEOUT_MSG消息,这个消息用来防止进程启动超时。如果超时弹出ANR对话框。

2.4 调整进程中的位置

AMS中代码经常调用updateLruProcessLocked来调整进程在mLruProcess列表的位置。在这个列表中,最近活动过得进程总是位于最高位置,同时拥有Activity的进程位置总是高于只有Service的进程位置。


2.5 调整进程的oom_adj值

AMS中调整oom_adj值的函数是updateOomAdjLocked,下面选了一段代码:


  
 
  1. for ( int i=N- 1; i>= 0; i--) { //从后面遍历mLruProcesses列表
  2. ProcessRecord app = mLruProcesses.get(i);
  3. if (!app.killedByAm && app.thread != null) {
  4. app.procStateChanged = false;
  5. computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
  6. // If we haven't yet assigned the final cached adj
  7. // to the process, do that now.
  8. if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
  9. switch (app.curProcState) {
  10. case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
  11. case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
  12. // This process is a cached process holding activities...
  13. // assign it the next cached value for that type, and then
  14. // step that cached level.
  15. app.curRawAdj = curCachedAdj;
  16. app.curAdj = app.modifyRawOomAdj(curCachedAdj);
  17. if (DEBUG_LRU && false) Slog.d(TAG, "Assigning activity LRU #" + i
  18. + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
  19. + ")");
  20. if (curCachedAdj != nextCachedAdj) {
  21. stepCached++;
  22. if (stepCached >= cachedFactor) {
  23. stepCached = 0;
  24. curCachedAdj = nextCachedAdj;
  25. nextCachedAdj += 2; //mLruProcesses列表越前面adj的值越大
  26. if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
  27. nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
  28. }
  29. }
  30. }
  31. break;

从上面的代码看出mLruProcesses列表越前面adj的值越大,也就越有可能被kill掉。



    原文作者:夏好鸟江
    原文地址: https://blog.csdn.net/hanguohui2222/article/details/82527143
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞