Android 9.0源码学习 - Launcher Activity

本文详细分析了Android 9.0中Launcher Activity的启动流程,从Launcher通知ActivityManagerService (AMS) 开始,经过AMS与Zygote的交互,到最后AMS如何启动并控制Activity。涉及关键步骤包括:Launcher调用AMS,AMS与Zygote的通信,以及AMS如何控制App进程的Activity执行。同时,文章提供了启动流程的简化示意图。
摘要由CSDN通过智能技术生成

其实9.0与8.0的ActivityManager差不多,但是看到网上的文章基本是分析了8.0之前的,导致我看这些博客再对照9.0的Code看的时候经常会卡壳,所以干脆自己写一篇好了,虽然会花费大量的时间,但是应该会有更深的理解了。

Artical Architecture

  • Activity Base
  • Process

那首先会写Activity基础的基本概念,不然是没法继续看code。

Activity Base

之前写过一篇Activity基本的知识,有兴趣请移步Android App components - Activities
还有一些博客,关于Task&LauncherMode:
基础总结篇之一:Activity生命周期
基础总结篇之二:Activity的四种launchMode

那就我看code的情况,需要知道的概念有:

  • Tasks&Back Stack
  • Lifecycle
  • LauncherMode(standard/singleTop/singleTask/singleInstance)

File List&Class List

File List

packages/apps/Launcher2/src/com/android/launcher2/
	- Launcher.java

frameworks/base/core/java/android/app/
	- Activity.java
	- Instrumentation.java
	- ActivityManager.java
	- IActivityManager.aidl
	- ActivityThread.java
		- ApplicationThread.java
		- H.java
	- ClientTransactionHandler.java

frameworks/base/services/core/java/com/android/server/am/
	- ActivityManagerService.java
	- ActivityStarter.java
	- ActivityStackSupervisor.java
	- ActivityStack.java
	- ActivityRecord.java
	- ProcessRecord.java
	- ClientLifecycleManager.java

/frameworks/base/core/java/android/app/servertransaction/	
	- ClientTransaction.java	
	- TransactionExecutor.java

Class List

Class Function
Launcher Default launcher application.
Activity Interact with the user.
Instrumentation Monitor all of the interaction the system has with the application.
ActivityManager Gives information about, and interacts with, activities, services, and the containing process.
ActivityThread ApplicationThread /H
ActivityManagerService This is a System Service
ActivityStarter Controller for interpreting how and then launching an activity. This class collects all the logic for determining how an intent and flags should be turned into an activity and associated task and stack.
ActivityStackSupervisor Supervisor of ActivityStack
ActivityStack State and management of a single stack of activities.
ClientLifecycleManager Class that is able to combine multiple client lifecycle transition requests and/or callbacks, and execute them as a single transaction.
ClientTransaction A container that holds a sequence of messages, which may be sent to a client.
ClientTransactionHandler Defines operations that a {@link android.app.servertransaction.ClientTransaction} or its items can perform on client.
TransactionExecutor Class that manages transaction execution in the correct order.

Process Communication

在看函数调用之前,需要先了解process之间的关系,那这里的Launcher,system_service,Zygote,在System启动的时候就启起来了。那Launcher中是有所有App的图标,当用户点击这个图标,Launcher会告诉AMS(ActivityManagerService,在system_server进程中),我要启动一个Activity(App中android.intent.category.LAUNCHER的Activity)。但此时App还没启起来,因此,AMS通过Socket告诉Zygote去启一个process,那Zygote会fork这个App Process,最后App Process告诉AMS,process已经启起来了。

在这里插入图片描述

下面这张图是在前人的基础上稍稍改了一些,这张图也没什么好解释的,简化的Activity启动过程。

  1. Launcher告诉ActivityManagerService,我要启动一个APP了
  2. ActivityManagerService告诉Zygote,请求fork一个进程
  3. fork新进程,也就是APP进程
  4. 告诉AMS,APP进程已经启动完成
  5. 告诉Binder对象去发送启动Activity的请求
  6. 向应用程序发送启动Activity的请求
  7. 向APP进程的主线程发送启动MainActivity组件的操作,LAUNCH_ACTIVITY
  8. handleLaunchActivity
    在这里插入图片描述

Activity Start Flow

那我们就照着Process中提到的顺序一步一步分析:

  • Launcher -> AMS
  • APP -> AMS
  • AMS -> APP

与Zygote与Process有关的这里就不分析了。

Step 1: Launcher -> AMS

首先是Launcher告诉AMS我要启动一个Activity的Flow

当用户点击App图标,会调用Launcher中startActivitySafely(),这个函数本身没做什么事情,只是接着调用 startActivity(),取得startActivity()的返回值,并做异常处理,真正的逻辑在startActivity()里。

startActivity(),可以看到intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),这涉及到Activity的Task,每个Activity都有一个Task,那么启动App的时候,Activity在一个新的Task中创建。然后又调用了一个startActivity(),这里的startActivity()是Launcher父类,也就是Activity的startActivity()

/packages/apps/Launcher2/src/com/android/launcher2/Launcher.java - startActivity()


    boolean startActivity(View v, Intent intent, Object tag) {
   
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
   
            // Only launch using the new animation if the shortcut has not opted out (this is a
            // private contract between launcher and may be ignored in the future).
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
            UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
            LauncherApps launcherApps = (LauncherApps)
                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
            if (useLaunchAnimation) {
   
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                        v.getMeasuredWidth(), v.getMeasuredHeight());
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
   
                    // Could be launching some bookkeeping activity
                    startActivity(intent, opts.toBundle());
                } else {
   
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
   
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
   
                    startActivity(intent);
                } else {
   
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
   
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
                    "or use the exported attribute for this activity. "
                    + "tag="+ tag + " intent=" + intent, e);
        }
        return false;
    }

/frameworks/base/core/java/android/app/Activity.java
startActivity()中它会,调用startActivityForResult()

/frameworks/base/core/java/android/app/Activity.java - startActivityForResult()

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
   
        if (options != null) {
   
            startActivityForResult(intent, -1, options);
        } else {
   
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

startActivityForResult()中,会调用InstrumentationexecStartActivity(),那Instrumentation这个类之前有介绍,是用来监控system与application之间的交互。

/frameworks/base/core/java/android/app/Activity.java - startActivityForResult()

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
   
        if (mParent == null) {
   
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
   
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
   
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
   
            if (options != null) {
   
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
   
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

execStartActivity()里,前面有一些ActivityMonitor相关的代码,然后ActivityManager.getService() .startActivity() ,看到ActivityManager.getService(),这里应该敏感的看出这是一个Binder对象(其实Android中很多这种IPC的套路,AccessibilityManager/LocationManager…)。你可以去看ActivityManager看到这个函数是获取了一个IActivityManager对象,那它其实就是AMS的Binder对象。也就是说这里其实是调用了AMS的startActivity()函数。

/frameworks/base/core/java/android/app/Instrumentation.java - execStartActivity()

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
   
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
   
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
   
            synchronized (mSync) {
   
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
   
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
   
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
   
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
   
                        am.mHits++;
                        if (am.isBlocking()) {
   
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
   
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .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;
    }

到这里呢,AMS就知道要启动一个Activity了。
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java - startActivity()

    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
   
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

下面简单总结了一下Launcher到AMS的过程
在这里插入图片描述

Step 2: AMS -> Zygote

刚才讲到,到了AMS的startActivity(),里面调用了startActivityAsUser()
这里可以看到返回了一个,mActivityStartController.obtainStarter(),那其实返回了ActivityStarter类的startActivityMayWait()的结果。

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java - startActivityAsUser()

    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
   
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }

startActivityMayWait()调用了startActivity()。这段代码很长,因此这里省略了一部分。

/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - startActivityMayWait()

    private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
   
		/*
		省略
		*/

            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);

            return res;
       	/*
		省略
		*/
    }

startActivity()调用了startActivityUnchecked()

/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - startActivity()

    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
   
        int result = START_CANCELED;
        try {
   
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
   
            // If we are not able to proceed, disassociate the activity from the task. Leaving an
            // activity in an incomplete state can lead to issues, such as performing operations
            // without a window container.
            if (!ActivityManager.isStartResultSuccessful(result)
                    && mStartActivity.getTask() != null) {
   
                mStartActivity.getTask().removeActivity(mStartActivity);
            }
            mService.mWindowManager.continueSurfaceLayout();
        }

        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                mTargetStack);

        return result;
    }

startActivityUnchecked()里面,做了一些check的工作,比如顶部的Activity是否一样,是否应该launch等等。最后调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked()

/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java - startActivityUnchecked()

    // Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
   

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);

        computeLaunchingTaskFlags();

        computeSourceStack();

        mIntent.setFlags(mLaunchFlags);

        ActivityRecord reusedActivity = getReusableIntentActivity();

        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值