framework之Activity启动流程(基于Android11源码)

Posted 一代小强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了framework之Activity启动流程(基于Android11源码)相关的知识,希望对你有一定的参考价值。

一步步看,你就会对activity的启动流程有深刻的认知。

引言

android11上,Activity的启动流程与Android10的实现(可以参考Activity的启动过程详解(基于10.0源码))又不一样了,但是万变不离其中,变的更多是代码上的优化。

为了照顾部分好学的同学,文章中的代码会稍微详细一些(有代码备注哦),如果不想看代码,可以直接看对应的时序图。

1、startActivity流程

代码分析

稍微了解activity的启动流程的读者应该知道,startActivity里面大概的工作:主要是通过Instrumentation用ActivityManagerService的代理对象,执行启动请求,中间涉及到binder的通信,如果大家不熟悉,可以看看笔者之前的文章 Android跨进程之ADIL原理

那我们来看看Android11 又是如何实现的呢?

startActivity调用的是startActivityForResult方法,直接看startActivityForResult的实现好了

public class Activity extends ContextThemeWrapper{
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
      ....
      Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
      ....
    }
}

Instrumentation#execStartActivity 方法的主要实现如下。大概能看出,这里是直接拿到ActivityTaskManager 服务去startActivity。

public class Instrumentation {
    ....
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
      ....
      int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getBasePackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
      // 检查启动结果
      checkStartActivityResult(result, intent);
      ....
    }
}

先看checkStartActivityResult的实现,就是处理启动activity失败的场景,典型的问题比如activity没有注册。

 // 检查启动结果
 public static void checkStartActivityResult(int res, Object intent) {
        ....
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
             ....
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

回到ActivityTaskManager.getService()的实现,通过下面的代码可以看出来getService方法返回的是IActivityTaskManager binder对象

public class ActivityTaskManager {
    ....
    // 一个单例的实现
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
        new Singleton<IActivityTaskManager>() {
        @Override
        protected IActivityTaskManager create() {
           final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
           return IActivityTaskManager.Stub.asInterface(b);
        }
    };
    ....
    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
   } 
}

看过ADIL实现的同学,应该很快反应出怎么找IActivityTaskManager 的实现类,全局搜一下 IActivityTaskManager.Stub即可,代码如下

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
   ....
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
}

那客户端又是怎么获取到IActivityTaskManager 的binder对象的呢?

从单例的实现,我们可以看到是通过 ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE) 方式拿到指定name对应的binder。ServiceManager 的实现如下

public final class ServiceManager {
   // Returns a reference to a service with the given name.
   // 返回对具有给定名称的服务的引用。
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                // 有缓存,直接从缓存获取
                return service;
            } else {
                // 否则重新通过ServiceManager获取
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
    // 通过指定name获取service的binder引用
    private static IBinder rawGetService(String name) throws RemoteException {
        final IBinder binder = getIServiceManager().getService(name);
        ....
        return binder;
    }
    
   // 获取ServiceManager的Binder对象
    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }
}

那客户端又是怎么拿到serviceManager的binder对象呢?有一个很重要的实现

public class BinderInternal {
    // 返回系统的全局“上下文对象”。这通常是 IServiceManager 的实现,
    // 您可以使用它来查找其他服务。
    public static final native IBinder getContextObject();
}

所以,客户端是通过ServiceManager对象拿到指定的service,再进行相关通信

时序图

startActivity对应的时序图如下:
在这里插入图片描述

2、服务端流程

服务注册

ActivityTaskManagerService 内部有一个Lifecycle的类

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    ....
    public static final class Lifecycle extends SystemService {
        private final ActivityTaskManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityTaskManagerService(context);
        }
        .... 

        @Override
        public void onStart() {
            publishBinderService(Context.ACTIVITY_TASK_SERVICE, mService);
            mService.start();
        }

        public ActivityTaskManagerService getService() {
            return mService;
        }
    }
}

SystemServer在启动的时候,会把Lifecycle 注册到SystemService里面,这样客户端就可以拿到对应的service

public final class SystemServer {

    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        ....
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        ....
    }
}

代码分析

与Android10上不一样的是,客户端不再对接ActivityManagerService,而是直接调用ActivityTaskManagerService 的接口。

// 用于管理活动及其容器(任务、堆栈、显示...)的系统服务。
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    private ActivityStartController mActivityStartController;
    ....
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    ....
    // 最终调用这个方法
    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        ....
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();

    }
    // 获取ActivityStartController
    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }
    ....
}

顺便提一下,ActivityManagerService中的startActivity 方法,实际上也是调用ActivityTaskManagerService的接口,不过这个方法已经被废弃了。

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    public ActivityTaskManagerService mActivityTaskManager;
  
    @Deprecated
    @Override
    public int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return mActivityTaskManager.startActivity(caller, callingPackage, null, intent,
                resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
    }
}

接着看。getActivityStartController 方法返回一个ActivityStartController对象,看看它的obtainStarter方法实现

// 用于委托活动启动的控制器。
// 该类的主要目标是获取外部活动启动请求,并将它们准备为一系列可由 
// {@link ActivityStarter} 处理的离散活动启动。它还负责处理活动启动周围发生的逻辑,但不一定影响活动启动。
// 示例包括电源提示管理、处理待处理活动列表以及记录home activity启动。
public class ActivityStartController {
     ....
     // @return一个启动程序,用于配置和执行启动活动。有效期直到调用{@link ActivityStarter#execute}之后。
     // 在这一点上,启动器应被视为无效,并且不再被修改或使用。 
     ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }
}

这个方法使用工厂模式,返回了一个ActivityStarter对象,接着用ActivityStarter对象设置了一些启动上的配置,直接看execute方法好了。

// 用于解释如何然后启动活动的控制器。此类收集用于确定意图和标志应如何转换为活动以及相关任务和堆栈的所有逻辑。
class ActivityStarter {
    // 根据前面提供的请求参数解析必要的信息,执行开始活动的请求。 
    // @return 起始结果。
    int execute() {
      ....
      if (mRequest.activityInfo == null) {
          mRequest.resolveActivity(mSupervisor);
      }
      int res;
      synchronized (mService.mGlobalLock) {
         ....
         res = executeRequest(mRequest);
         ....
      }
    }
}

里面是直接把request对象给到了executeRequest 方法,在里面会做一些参数的检查

class ActivityStarter {
		// 执行活动启动请求,开启活动启动之旅。首先是执行几个初步检查。
    // 通常的 Activity 启动流程会经过 {@link startActivityUnchecked} 到 {@link startActivityInner}。
    private int executeRequest(Request request) {
        int err = ActivityManager.START_SUCCESS;
        ....
        // 我们找不到可以处理给定 Intent 的类。
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            // We couldn't find a class that can handle the given Intent.
            // That's the end of that!
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }
        // 我们找不到 Intent 中指定的特定类。
        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            // We couldn't find the specific class specified in the Intent.
            // Also the end of the line.
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }
        ....
        // 检查启动activity的权限
        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
                request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultStack);
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);
        abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                callingPackage);  
        boolean restrictedBgActivity = false;
        if (!abort) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "shouldAbortBackgroundActivityStart");
                // 检查是否允许后台启动activity,以下情况会允许后台启动activity
                // 1、一些重要的UId比如System UID,NFC UID
                // 2、callingUid具有可见窗口或是持久性系统进程(即persistent的系统进程)
                // 3、callingUid具有START_ACTIVITIES_FROM_BACKGROUND权限
                // 4、调用方的uid与最近使用的组件具有相同的uid
                // 5、callingUid是设备所有者或者有伴侣设备
                // 6、callingUid具有SYSTEM_ALERT_WINDOW权限
                // 7、调用者在任何前台任务中有活动
                // 8、调用者被当前前台的 UID 绑定
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        request.originatingPendingIntent, request.allowBackgroundActivityStart,
                        intent);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
        }
        // 如果权限需要审阅才能运行任何应用程序组件,我们将启动审阅活动,
        // 并传递未决的意向以启动在审阅完成后现在要启动的活动。
        if (aInfo != null) {
            // 获取此包使用的某些权限是否需要用户审核才能运行任何应用程序组件。
            if (mService.getPackageManagerInternalLocked().以上是关于framework之Activity启动流程(基于Android11源码)的主要内容,如果未能解决你的问题,请参考以下文章

framework之Activity启动流程(基于Android11源码)

Framework之AMS启动流程,简单上手!

Framework源码面试六部曲:1.activity启动流程

[Android][Framework]Activity启动流程

framework之Activity 生命周期解析(基于Android11源码)

framework之Activity 生命周期解析(基于Android11源码)