6.理解ActivityManagerService

理解ActivityManagerService

这篇文章只是对刘望舒大佬书籍的摘抄,适合复习用,没看过的请先看大佬的原书
下面是大佬博客的链接Android进阶三部曲 第二部《Android进阶解密》

一、AMS家族

由于AMS的逻辑多而复杂,因此是有一些类帮助AMS完成相关逻辑,而AMS和这些类就被称为AMS家族。

Android7.0和Android8.0对于AMS相关部分处理有较大区别,需要区别看待

Android7.0的AMS家族

ActivityManager是一个和AMS相关联的类,它主要对运行中的Activity进行管理,但是这些管理工作并不是由ActivityManager来处理的,而是交给AMS来处理的。ActivityManager中的方法会通过ActivityManagerNative(简称AMN)的getDefault方法来得到ActivityManagerProxy(简称AMP),通过AMP就可以和ActivityManagerService(AMS)进行通信,而AMN是一个抽象类,它将功能交给子类AMS来处理。因此AMP就是AMS的代理类。而ActivityManager只是提供了一部分AMS的api,并不算是AMS家族的一部分。

下面是一些AMS家族的源码

/frameworks/base/core/java/android/app/ActivityManagerNative.java

static public IActivityManager getDefault() {
  return gDefault.get();
}
//单例类,对象没有的时候会调用create方法创建,但是只会调用一次create方法
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
  protected IActivityManager create() {
    //得到名为"activity"Service引用,业绩是IBinder类型的AMS引用
    IBinder b = ServiceManager.getService("activity");
    if (false) {
      Log.v("ActivityManager", "default service binder = " + b);
    }
    //通过asInterface方法封装成AMP类型对象
    IActivityManager am = asInterface(b);
    if (false) {
      Log.v("ActivityManager", "default service = " + am);
    }
    return am;
  }
};
static public IActivityManager asInterface(IBinder obj) {
  if (obj == null) {
    return null;
  }
  //查询本地进程是否有IActivityManager接口的实现
  //descriptor值为 android.app.IActivityManager
  IActivityManager in =(IActivityManager)obj.queryLocalInterface(descriptor);
  if (in != null) {
    //如果有就返回
    return in;
  }
  //没有就加过你IBinder类型的引用封装成AMP
  return new ActivityManagerProxy(obj);
}
class ActivityManagerProxy implements IActivityManager{
  public ActivityManagerProxy(IBinder remote)
  {
    mRemote = remote;
  }
  ...
}

上面几个类的关系如下

请添加图片描述

AMP是AMN的内部类,他们都实现了IActivityManager接口,这样他们就可以实现代理模式,具体来说是远程代理:AMP和AMN运行在两个进程中,AMP是Client端,AMS则是Service端,而Service端中的的具体功能都是由AMN的子类AMS来实现的,因此,AMP就是AMS在Client端的代理类。AMN又实现了Binder类,这样AMP和AMS就可以通过BInder来进行进程间通信。

除了ActivityManager外,其他类想要和AMS通信也要通过AMP

请添加图片描述

Android8.0的AMS家族

Android8.0的ActivityManager的实现和Android7.0不同

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

private static final Singleton<IActivityManager> IActivityManagerSingleton =
  new Singleton<IActivityManager>() {
  @Override
  protected IActivityManager create() {
    查询本地进程是否有IActivityManager接口的实现
    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
    //使用aidl方式生成的类IActivityManager.Stub的asInterface创建本地代理
    final IActivityManager am = IActivityManager.Stub.asInterface(b);
    return am;
  }
};

Android8.0的AMS系统使用了AIDL。去掉了AMP,代替他的是IActivityManager它是AMS在本地的代理。

Android8.0的AMS家族如图所示

请添加图片描述

二、AMS的启动过程

AMS的启动是在SystemServer进程中启动的,SystemServer进程在第二章中我们已经知道了,这里从SystemServer的main方法开始看

/frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
  //创建一个对象并调用run方法
  new SystemServer().run();
}
private void run() {
  try {
    ...
    //创建消息Looper
    Looper.prepareMainLooper();
    // 加载动态库libandroid_servers
    System.loadLibrary("android_servers");
    performPendingShutdown();
    //创建系统的Context
    createSystemContext();
    //2.创建SystemServiceManager,它会对系统的服务进行创建、启动和声明周期管理
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    SystemServerInitThreadPool.get();
  } finally {
    traceEnd();  // InitBeforeStartServices
  }

  try {
    traceBeginAndSlog("StartServices");
    //启动引导服务,里面会启动AMS等服务
    startBootstrapServices();
    //启动核心服务
    startCoreServices();
    //启动其他服务
    startOtherServices();
    SystemServerInitThreadPool.shutdown();
  } catch (Throwable ex) {
    ...
  }
  ...
  //开启消息循环
  Looper.loop();
  throw new RuntimeException("Main thread loop unexpectedly exited");
}

我们看startBootstrapServices方法,它会启动AMS

private void startBootstrapServices() {
 	...
  //调用SystemServiceManager的startService方法
  mActivityManagerService = mSystemServiceManager.startService(
    ActivityManagerService.Lifecycle.class).getService();
  mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
  mActivityManagerService.setInstaller(installer);
  traceEnd();
  ...
}

/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public <T extends SystemService> T startService(Class<T> serviceClass) {
  try {
    final String name = serviceClass.getName();
    ...
    final T service;
    try {
      //找到类的构造器,然后创建对象,这里是创建了ActivityManagerService.Lifecycle类型的对象
      Constructor<T> constructor = serviceClass.getConstructor(Context.class);
      service = constructor.newInstance(mContext);
    } catch (InstantiationException ex) {
      ...
    }
    startService(service);
    return service;
  } finally {
    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
  }
}

public void startService(@NonNull final SystemService service) {
  //将ActivityManagerService.Lifecycle类型的service对象添加到mServices这个ArrayList中
  mServices.add(service);
  long time = System.currentTimeMillis();
  try {
    //调用ActivityManagerService.Lifecycle的start方法,启动AMS
    service.onStart();
  } catch (RuntimeException ex) {
   ...
  }
  warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
}

这里先是将ActivityManagerService.Lifecycle类型的service对象添加到mServices,然后调用它的onStart方法启动AMS

ActivityManagerService.Lifecycle是ActivityManagerService类的内部类,接下来我们看下它的源码

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public static final class Lifecycle extends SystemService {
  private final ActivityManagerService mService;
  public Lifecycle(Context context) {
    super(context);
    //创建AMS对象
    mService = new ActivityManagerService(context);
  }
  public void onStart() {
    //调用Service.start方法
    mService.start();
  }
  public ActivityManagerService getService() {
    return mService;
  }
}

ActivityManagerService.Lifecycle构造器里创建了AMS的对象,onStart方法里调用了AMS的start方法,也就是AMS启动了

三、AMS与应用程序进程

Zygote的Java框架层中,会创建一个Server的Socket,这个Socket用来等待AMS请求Zygote来创建新的应用程序进程。

要启动一个应用程序首先要保证这个应用程序所需要的应用程序进程已经存在。

在启动应用程序进程时AMS会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程创建需要的应用程序进程。

下面是Service的启动过程示例

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                                   boolean whileRestarting, boolean permissionsReviewRequired)
  throws TransactionTooLargeException {
  ...
  //1.获取Service想要在那个进程启动,默认是当前进程
  final String procName = r.processName;
  String hostingType = "service";
  ProcessRecord app;
  if (!isolated) {
    //ProcessRecord主要用来描述运行的应用程序进程的信息
    //2.查询是否存在一个与Service对应的ProcessRecord类型的对象app,
    app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
    if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                         + " app=" + app);
    //3.如果运行Service的应用程序进程存在
    if (app != null && app.thread != null) {
      try {
        app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
        //4.启动Service
        realStartServiceLocked(r, app, execInFg);
        return null;
      } catch (TransactionTooLargeException e) {
        throw e;
      } catch (RemoteException e) {
        Slog.w(TAG, "Exception when starting service " + r.shortName, e);
      }

    }
  } else {
    app = r.isolatedProc;
    if (WebViewZygote.isMultiprocessEnabled()
        && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
      hostingType = "webview_service";
    }
  }
  //5.如果用来运行Service的应用程序进程不存在
  if (app == null && !permissionsReviewRequired) {
    //6.创建应用程序进程
    if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                                    hostingType, r.name, false, isolated, false)) == null) {
      String msg = "Unable to launch app "
        + r.appInfo.packageName + "/"
        + r.appInfo.uid + " for service "
        + r.intent.getIntent() + ": process is bad";
      Slog.w(TAG, msg);
      bringDownServiceLocked(r);
      return msg;
    }
    if (isolated) {
      r.isolatedProc = app;
    }
  }
  ...
  return null;
}

四、AMS重要的数据结构

ActivityRecord、TaskRecord和ActivityStack是Activity任务栈模式的基础

ActivityRecord

ActivityRecord记录了Activity的所有信息,它用来描述一个Activity,它是在启动Activity时被创建的,具体是在ActivityStarter的startActivity方法中被创建的

ActivityRecord的部分成员变量如下表

名称类型说明
serviceActivityManagerServiceAMS的引用
infoActivityInfoActivity中代码和AndroidManifests设置的节点信息,比如launchMode
launchedFromPackageString启动Activity的包名
taskAffinityStringActivity希望归属的栈
taskTaskRecordActivityRecord所在的TaskRecord
appProcessRecordActivityRecord所在的应用程序进程
stateActivityState当前Activity的状态
iconintActivity的图标资源标识符
themeintActivity的主题资源标志符

TaskRecord

TaskRecord用来描述一个Activity任务栈。其内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录和AMS的引用等。

下面是一些重要成员变量的介绍

名称类型说明
taskIdint任务栈的唯一标识符
affinityString任务栈的倾向性
intentIntent启动这个任务栈的Intent
mActivitiesArrayList<ActivityRecord>按照历史顺序排列的Activity记录
mStackActivityStack当前归属的ActivityStack
mServiceActivityManagerServiceAMA的引用

ActivityStack

ActivityStack用来管理系统的所有Activity,其内部维护了Activity的所有状态、特殊状态的Activity以及和Activity相关的列表等数据。ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public ActivityManagerService(Context systemContext) {
  ...
  //创建ActivityStackSupervisor的实例
  mStackSupervisor = createStackSupervisor();
  ...
}
protected ActivityStackSupervisor createStackSupervisor() {
  return new ActivityStackSupervisor(this, mHandler.getLooper());
}
ActivityStack的实例类型

在ActivityStackSupervisor中有多种ActivityStack实例,如下所示

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
  ...
  //存储LauncherApp的所有Activity
  ActivityStack mHomeStack;
  //当前正在接收输入或启动下一个Activity 的所有Activity
  ActivityStack mFocusedStack;
  //此前接收输入的所有Activity
  private ActivityStack mLastFocusedStack;
  ...
}

ActivityStackSupervisor提供获取上述ActivityStack的方法,比如要获取mFocusedStack,调用getFocusStack方法即可

ActivityState

在ActivityStack中通过枚举存储了Activity的所有的状态

/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

enum ActivityState {
  INITIALIZING,
  RESUMED,
  PAUSING,
  PAUSED,
  STOPPING,
  STOPPED,
  FINISHING,
  DESTROYING,
  DESTROYED
}
特殊状态的Activity

在ActivityStack中定义了一些特殊状态的Activity,如下所有

class ActivityStack<T extends StackWindowController> extends ConfigurationContainer implements StackWindowListener {
  //正在暂停的Activity
  ActivityRecord mPausingActivity = null;
  //上一个已经暂停的Activity
  ActivityRecord mLastPausedActivity = null;
  //最近一次没有历史记录的Activity
  ActivityRecord mLastNoHistoryActivity = null;
  //已经Resume的Activity
  ActivityRecord mResumedActivity = null;
  //传输给coverToTranslucent方法的最上层的Activity
  ActivityRecord mTranslucentActivityWaiting = null;
}
维护的ArrayList

在ActivityStack中维护了很多ArrayList,这些ArrayList中的元素类型主要有ActivityRecord和TaskRecord,

ArrayList元素类型说明
mTaskHistoryTaskRecord所有没有被销毁的Activity任务栈
mLRUActivitysActivityRecord正在运行的Activity,列表中的第一个条目是最近最少使用的Activity
mNoAnimActivitysActivityRecord不考虑动画的Activity
mValidateAppTokensTaskGroup用于与窗口管理器验证应用令牌

ActivityStack维护了元素类型为TaskRecord的列表,这样ActivityStack和TaskRecord就有了关联,Activity任务栈存储在ActivityStack中。

五、Activity栈管理

Activity是放入在Activity任务栈中的,有了任务栈,系统和开发者就能够更好的应用和管理Activity,来完成各种业务逻辑。

Activity任务栈模型

Activity任务栈是由多种数据结构共同组合而成的,上面的ActivityRecord、TaskRecord和ActivityRecord,他们就是Activity任务栈的重要组成部分。如下图所示

请添加图片描述

  • ActivityRecord用来记录一个Activity的所有信息,TaskRecord中包含了一个或多个ActivityRecord

  • TaskRecord用来表示Activity的任务栈,用来管理栈中的ActivityRecord。

  • ActivityStack又包含了一个或多个TaskRecord,它是TaskRecord的管理者。

Activity栈管理就是建立在Activity任务栈模型之上的,有了栈管理,我们就可以对应用程序进行操作,应用就可以复用自身应用中以及其他应用的Activity,节省了资源

例如当我们的一款社交应用,联系人详情界面提供了联系人的邮箱,当我们点击邮箱会跳转到发送邮件的界面,如图

请添加图片描述

社交应用和系统E-mail的Activity是出于不同应用进程的,而有了栈管理,就可以把发送邮件界面放到社交应用中详情界面所在的栈的栈顶。来做跨进程做操。

为了更灵活的进行栈管理,Android系统提供了很多配置,包括Launch Mode、Intent的FLAG和taskAffinity等,

Launch Mode

Launch Mode用来设定Activity的启动方式。这就要有以下四种

  • standerd:默认模式,每次启动Activity都会创建一个新的Activity实例。

  • singleTop:如果要启动的Activity已经在栈顶了。则不会重新创建Activity,同时该Activity的onNewIntent方法会被调用。如果要启动的Activity不再栈顶,则会重新创建该Activity的实例。

  • singleTask:如果要启动的Activity已经存在于它想要归属的栈中,那么不会创建该Activity的实例,将栈中位于该Activity上的所有Activity出栈,同时该Activity的onNewIntentx方法被调用。

    如果要启动的Activity不在它想要归属的栈内,并且该栈存在则会重新创建该Activity的实例

    如果要启动的Activity想要归属的栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入到新栈中

  • singleInstance:和singleTask基本类似,不同的是启动Activity时,首先要创建一个新栈,然后创建该Activity实例并压入新栈中

Intent的FLAG

在Intent中定义了很多FLAG,有几个FLAG可以设定Activity的启动方式,如果Launch Mode 和Flag 设定的Activity的启动方式有冲突,则以 FLAG 设定的为准。

  • FLAG_ACTIVITY_SINGLE_TOP

    和Launch Mode中的singleTop 效果一样。

  • FLAG_ACTIVITY_NEW_TASK

    和Launch Mode 中的singleTask 效果一样

  • FLAG_ACTIVITY_CLEAR_TOP

    如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity出栈。singleTask默认具有此标记的效果

还有一些FLAG对我们分析栈管理有帮助

  • FLAG_ACTIVITY_NO_HISTORY

    Activity一旦退出,就不会存在于栈中,同样地,也可以在AndroidManifest.xml中设置android:noHistory

  • FLAG_ACTIVITY_MULITIPLE_TASK

    需要和FLAG_ACTIVITY_NEW_TASKU一同使用才有效果,系统会启动一个新的栈来容纳新启动的Activity.

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

    Activity不会被放入到 “最近启动的Activity” 列表中.

  • FLAG_ACTIVITY_BROUGHT_TO_FRONT

    这个标志位通常不是由应用程序中的代码设置的,而是 LaunchMode 为 singleTask 时,由系统自动加上的

  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

    这个标志位通常不是由应用程序的代码设置的,而是从历史记录启动的(长按Home键调出)

  • FLAG_ACTIVITY_CLEAR_TASK

    需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,用于清除与启动的Activity相关栈的所有其他Activity。

FLAG在源码中的应用

根Activity启动时会调用AMS的startActivity方法,经过层层调用会调用ActivityStarter的startActivityUnchecked方法,如下图

请添加图片描述

/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
  //1.初始化启动Activity的各种配置,在初始化前会重置各种配置再进行配置,
  //这些配置包括ActivityRecord、Intent、TaksRecord和LaunchFlags(Activity启动的FLAG)
  setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor);
  //2.计算出Activity启动的FLAG,并将计算的值赋值给mLaunchFlags。
  computeLaunchingTaskFlags();
  computeSourceStack();
  //3.将mLaunchFlags设置给Intent,达到设定Activity启动方式的目地
  mIntent.setFlags(mLaunchFlags);
  ...
}
private void computeLaunchingTaskFlags() {
  ...
  
  if (mInTask == null) {
    //1.如果要加入的栈不存在
    if (mSourceRecord == null) {
      //2.初始Activity所在的栈不存在,初始Activity表示要启动新Activity的那个Activity
      if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
        Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
               "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
        //3.如果要加入的栈不存在,初始Activity所在的栈不存在,mLaunchFlags标记为需要创建新栈
        mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
      }
    } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
      //4.如果初始Activity所在的栈只允许存在一个Activity实例,mLaunchFlags标记为需要创建新栈
      mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    } else if (mLaunchSingleInstance || mLaunchSingleTask) {
      //5.如果Launch Mode 谁知为了 singleTask 或singleInstance,mLaunchFlags标记为需要创建新栈
      mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
    }
  }
}

taskAffinity

在AndroidManifest中设置android:taskAffinity,用来指定Activity希望归属的栈,在默认情况下,同一个应用程序的所有Activity都有相同的taskAffinity。

taskAffinity在下面两种情况时会产生效果。

  1. taskAffinity与FLAG_ACTIVITY_NEW_TASK或者singleTaks配合。

    如果新启动Activity的taskAffinity和栈的taskAffinity相同则加入到该栈中,如果不同则会创建新栈。

  2. taskAffinity与allowTaskReparenting配合

    如果allowTaskReparenting为true,说明Activity具有转移的能力。

    例如以上面的社交和邮件应用交互为例,当社交应用启动发送邮件的Activity,此时发送邮件的Activity是和社交应用出于同一个栈中,并且这个栈位于前台。如果发送邮件的Activity的allowTaskReparenting设置为true,此后E-mail应用所在的栈位于前台时,发送邮件的Activity就会由社交应用中栈转移到与它taskAffinity相同的邮件应用所在的栈中

    请添加图片描述

在系统源码中,ActivityStackSupervisor的findTaskLocked方法用于找到Activity最匹配的栈,最终会调用ActivityStack的findTaskLocked方法:

/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

void findTaskLocked(ActivityRecord target, FindTaskResult result) {
  ...
  //1.遍历mTaskHistory列表,列表中的元素为TaskRecord,它用于存储没有被会销毁的栈。
  for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
    //2.得到某一个栈
    final TaskRecord task = mTaskHistory.get(taskNdx);
    ...
    else if (!isDocument && !taskIsDocument
               && result.r == null && task.rootAffinity != null) {
      //3.将栈的rootAffinity(初始的taskAffinity)和目标的taskAffinity做对比,
      //如果相同,则将FindTaskResult的matchedByRooAffinity属性设置为true,说明找到了匹配的栈
      if (task.rootAffinity.equals(target.taskAffinity)) {
        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
        result.r = r;
        result.matchedByRootAffinity = true;
      }
    } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值