为了账号安全,请及时绑定邮箱和手机立即绑定

Android9.0源码学习 - Launcher Activity(一)

标签:
Android

那就我看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
- IApplicationThread.aidl

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

Class List

ClassFunction
LauncherDefault launcher application.
ActivityInteract with the user.
InstrumentationMonitor all of the interaction the system has with the application.
ActivityManagerGives information about, and interacts with, activities, services, and the containing process.
ActivityThreadApplicationThread /H
ActivityManagerServiceThis is a System Service
ActivityStarterController 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.
ActivityStackSupervisorSupervisor of ActivityStack
ActivityStackState and management of a single stack of activities.
ClientLifecycleManagerClass that is able to combine multiple client lifecycle transition requests and/or callbacks, and execute them as a single transaction.
ClientTransactionA container that holds a sequence of messages, which may be sent to a client.
ClientTransactionHandlerDefines operations that a {@link android.app.servertransaction.ClientTransaction} or its items can perform on client.
TransactionExecutorClass 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已经启起来了。

webp

在这里插入图片描述

下面这张图是在前人的基础上稍稍改了一些,这张图也没什么好解释的,简化的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


    webp

    在这里插入图片描述

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());



作者:Dufre
链接:https://www.jianshu.com/p/91ca5ac605be


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消