安卓的ActivityManagerService

AMS一个很重要的系统服务,安卓的四大组件都与之关联,这里便深入了解下它。

知识点在这里插入图片描述

一、AMS关联类

Android 7.0和Android 8.0对于AMS相关部分处理有较大的区别,为了更好地理解AMS家族,这里将分别介绍Android 7.0和Android 8.0的AMS关联类。

1、Android 7.0的AMS关联类

简介
  • ActivityManager:主要对运行中的Activity进行管理。管理工作实际并不是由ActivityManager来处理的,而是交由AMS来处理的。
  • ActivityManagerNative :简称AMN。是一个抽象类,其功能由他的子类AMS处理。其getDefault方法可得到ActivityManagerProxy(简称AMP)。ActivityManager通过AMP与AMN通信。
  • ActivityManagerProxy:AMN的内部类、AMS的代理类。
  • ActivityManagerService:系统服务,运行在SystemSever进程。AMS作为系统服务,很多API是不会暴露给ActivityManager的。

接下来看下AMS在安卓7.0中Activity启动过程中的使用,这里就从Activity的startActivity看起,最终会调用Instrumentation的execStartActivity

   public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

...
  try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;

}

可以看到,execStartActivity方法中会调用AMN的getDefault来获取AMS的代理类AMP。接着调用了AMP的startActivity方法,先来查看AMN的getDefault方法做了什么:

AMN 类中:

 static public IActivityManager getDefault() {
 //1、在getDefault方法中调用了gDefault的get方法。
        return gDefault.get();
    }
    /*2、
    
gDefault是一个Singleton类


*/
     private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        //得到Ibind 类型的AMS引用
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            // 3、将它封装成AMP类型对象,并将它保存到gDefault中,
            //此后调用AMN的getDefault方法就会直接获得AMS的代理对象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 in =
        //4、descriptor值为android.app.IActivityManager类型
            (IActivityManager)obj.queryLocalInterface(descriptor);

//5、查询本地进程是否有IActivityManager接口的实现,
//如果有则返回,如果没有就使用ActivityManagerProxy将IBinder类型的AMS引用封装成AMP
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

//6、在AMP的构造方法中将AMS的引用赋值给变量mRemote,这样在AMP中就可以使用AMS了。
//其中IActivityManager是一个接口,AMN和AMP都实现了这个接口,
//用于实现代理模式和Binder通信
public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }

再回到Instrumentation的execStartActivity方法,来查看AMP的startActivity方法,AMP是AMN的内部类

  public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {

...
//private IBinder mRemote;
 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
}

首先将传入的参数写入到Parcel类型的data中。通过IBinder类型对象mRemote(AMS的引用)向服务器端的AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务器端AMS就会从Binder线程池中读取客户端发来的数据,最终会调用AMN的onTransact方法。

  @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
...
// 调用AMS的start 方法
 int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
}

调用AMS的start 方法,AMS的startActivity方法最后会返回startActivityAsUser方法,等后续就是一系列无关AMS的调用了。。。

图解&小结

在这里插入图片描述

在这里插入图片描述

AMP是AMN的内部类,它们都实现了IActivityManager接口,这样它们就可以实现代理模式。具体来讲是远程代理。

AMP和AMN是运行在两个进程中的,AMP是Client端,AMN则是Server端,而Server端中具体的功能都是由AMN的子类AMS来实现的,因此,AMP就是AMS在Client端的代理类。

AMN又实现了Binder类,这样AMP和AMS就可以通过Binder来进行进程间通信

ActivityManager通过AMN的getDefault方法得到AMP,通过AMP就可以和AMS进行通信。除ActivityManager以外,有些想要与AMS进行通信的类也需要通过AMP,如上图解。

2、Android 8.0的AMS关联类

Instrumentation#execStartActivity方法
  public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {

...
  try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
}
ActivityManager#getService
 /**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                //1、获得Binder类型的AMS引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //2、将Binder类型引用转换成IActivityManager类型的对象,
                    //这段代码采用的是AIDL
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

采用AIDL后就不需要使用AMS的代理类AMP了,因此Android8.0去掉了AMP,代替它的是IActivityManager,它是AMS在本地的代理。

图解&小结

ActivityManager的getService方法会得到IActivityManager,AMS只需要继承IActivityManager.Stub类,就可以和ActivityManager实现进程间通信了
在这里插入图片描述

二、AMS的启动过程

AMS的启动是在SystemServer进程中启动的。也即AMS运行在SystemSever进程。SystemServer的main方法如下:

 /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
...         // 创建Looper
            Looper.prepareMainLooper();

            // 1、加载动态库android_servers(C,C++ 文件编译产物)
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            createSystemContext();

            // 2、创建system service manager。对系统的服务进行创建、启动、
            //生命周期管理
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
            ...
            //3、分批启动系统服务
            //启动引导服务
            startBootstrapServices();
            //启动核心服务
            startCoreServices();
            //启动其他服务
            startOtherServices();
            ...
              // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");

}

AMS服务就是在启动系统服务时启动的。

系统服务有很多的有的需要立即启动,有的不需要立即启动,所以系统就分三批启动系统服务:

  • 引导服务(BootstrapServices):主要开启了ActivityManagerService、PowerManagerService、PackageManagerService等服
  • 核心服务(CoreServices):主要开启了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService等服务
  • 其他服务(OtherServices):主要启动了CameraService、AlarmManagerService、VrManagerService等服务。

既然AMS的开启是SystemSever进程中调用引导服务时开启的,那么就看下startBootstrapServices方法:

 private void startBootstrapServices() {
...
 // 开启AMS相关的代码
        traceBeginAndSlog("StartActivityManager");
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        traceEnd();
...
}

可以发现具体是通过SystemServiceManager#startService方法传参 ActivityManagerService.Lifecycle.class来开启的。具体细节如下:

SystemServiceManager.java

 public void startService(@NonNull final SystemService service) {
        // 注册AMS服务,方便系统管理
        mServices.add(service);
        //调用AMS的start方法开启AMS服务
        long time = System.currentTimeMillis();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
    }

调用AMS的start方法开启AMS服务

这里需要注意:

  • 所有的系统服务父类都是SystemService

  • ActivityManagerService.Lifecycle.class 参数:可以看出Lifecycle是AMS的内部类。其实AMS对象创建、AMS的开启、AMS对象的获取都是这个内部类提供的功能。具体如下一看便知:

  public static final class Lifecycle extends SystemService {
        //AMS
        private final ActivityManagerService mService; 
        
        // 1、构造方法中创建AMS对象
        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }
       
       // 2、AMS start方法
        @Override
        public void onStart() {
            mService.start();
        }
       
       // 3、返回AMS对象
        public ActivityManagerService getService() {
            return mService;
        }
    }

三、AMS 与应用进程

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

要启动一个应用程序首先要保证应用程序的进程已经启动,否则就要先启动应用程序需要的进程,然后启动应用程序。

AMS管理着四大组件的开启以及组件信息的维护,AMS的职责是十分重要的。在启动应用程序时AMS会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程创建需要的应用程序进程。

这里就以startService为例子展示下:

ActiveService#bringUpServiceLocked()

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {

...
  //1、processName描述service想要运行的进程,默认值为当前进程
  final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
        //2、mAm为AMS类型对象,这里调用AMS的getProcessRecordLocked表示去AMS中查询
        //是否存在一个与service对应的ProcessRecord类型对象。
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {//3、service应用进程存在
                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";
            }
        }
        // 假如需要的应用进程不存在时,创建应用进程。
        if (app == null && !permissionsReviewRequired) {
            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;
}

伪代码表示

    //app 对象为ProcessRecord类型,开启应用进程时AMS内部会维护记录这个进程。
    if(app!=null,app.thread!=null){ 
     开启组件
    }else{
     ams向zogote发socket请求创建应用进程
    }

四、AMS重要的数据结构

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

Activity任务栈模型是由多种数据结构共同组合而成的:

在这里插入图片描述

  • ActivityRecord:记录一个Activity的所有信息。
  • TaskRecord:包含一个或者多个ActivityRecord,用来管理栈中的ActivityRecord。
  • ActivityStack:包含一个或者多个TaskRecord,用来管理栈中的TaskRecord,也即用来管理系统所有Activity。

ActivityStack

ActivityStack是一个管理类,用来管理系统所有Activity。

1、ActivityStack何时被创建??

ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建。

ActivityStackSupervisor成员变量中维护了很多类型的ActivityStack如:

  • ActivityStack mHomeStack:用来存储Launcher App的所有Activity
  • ActivityStack mFocusedStack:表示当前正在接收输入或启动下一个Activity的所有Activity

通过ActivityStackSupervisor提供了获取上述ActivityStack 的方法,比如要获取mFocusedStack,只需要调用ActivityStackSupervisor的getFocusedStack方法就可以了

2、ActivityStack内部维护的数据

(1)枚举了Activity所有状态

 enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED
    }

具体场景:Activity的切换动画系统源码

  @Override
    public void overridePendingTransition(IBinder token, String packageName,
            int enterAnim, int exitAnim) {
        synchronized(this) {
            ActivityRecord self = ActivityRecord.isInStackLocked(token);
            if (self == null) {
                return;
            }

            final long origId = Binder.clearCallingIdentity();

            if (self.state == ActivityState.RESUMED
                    || self.state == ActivityState.PAUSING) {
                mWindowManager.overridePendingAppTransition(packageName,
                        enterAnim, exitAnim, null);
            }

            Binder.restoreCallingIdentity(origId);
        }
    }

可以看到只有ActivityState 为RESUMED状态或者PAUSING状态时才会调用WMS类型的mWindowManager对象的overridePendingAppTransition方法来切换动画

(2)重要字段

//所有没有被销毁的Activity任务栈
   private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
   
// 正在运行的activity,列表中第一个是最近最少使用的Activity
final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

//不考虑转化动画的activity
   final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();

  //正在暂停的activity
   ActivityRecord mPausingActivity = null;
   //上一个已经暂停的activity
   ActivityRecord mLastPausedActivity = null;
   ...

TaskRecord相关重要字段

TaskRecord 用来描述一个Activity任务栈。TaskRecord的作用,其内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录和AMS的引用等,需要注意的是其中含有ActivityStack,也就是当前Activity任务栈所归属的ActivityStack。

字段说明
int taskId任务栈唯一标识符
String affinity任务倾向性
Intent intent启动任务栈的intent
ArrayList<ActivityRecord> mActivities按照历史顺序排列的activity记录
ActivityStack mStack当前activity归属的任务栈
ActivityManagerService mServiceAMS引用

ActivityRecord相关重要字段

用来描述一个Activity,记录了Activity的所有信息,包括AMS的引用、AndroidManifes节点信息、Activity状态、Activity资源信息和Activity进程相关信息等

需要注意的是其中含有该ActivityRecord所在的TaskRecord,这就将ActivityRecord和TaskRecord关联在一起。

具体是在启动Activity 时被创建的,具体是在ActivityStarter 的startActivity方法中被创建的。

字段说明
ActivityManagerService serviceAMS引用
ActivityInfo infoActivity中代码和AndroidManifes设置的节点,比如launchMode
String launchedFromPackage启动activity的包名
String taskAffinityActivity希望归属的栈
TaskRecord taskActivityRecord所在的TaskRecord
ProcessRecord appActivityRecord所在的应用程序进程
ActivityState state当前activity的状态
int iconActivity的图标资源标识符
int themeActivity的主题资源标识符

The end

参考:
安卓进阶解密:微信读书版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值