Android源码——Activity启动流程

之前在Mac环境下搭建了Android源码,接下来会在简书记录阅读一些经典场景的源码过程, 本文主要是在阅读启动Activity源码过程中做的一些记录, 其中主要的思路是参考罗老师的文章:Android应用程序启动过程源代码分析

几个重要概念

在看Activity启动源码之前,先看几个概念, 这几个是理解Activity启动流程的重要概念:

ActivityManagerService: AMS,服务端的类, 管理着Activity相关的行为

ApplicationThread:实现了IApplicationThread接口,这个接口的说明是

/**
This is given to the activity manager by an application  when it starts up, for the activity manager to tell the application about things it needs to do
**/

它是用来实现ActivityManagerService和ActivityThread之间的交互

ActivityThread:

/**
 * This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
 * manager requests.
 */

ActivityThread是App主线程(UI线程)管理者,并且作为调度和执行Activity, broadcast的角色。所以,Activity相关的操作,都是由ActivityThread来调度的。

对于每一个应用程序来说,都有一个ActivityThread来表示应用程序的主进程,而每一个ActivityThread都包含有一个ApplicationThread实例,它是一个Binder对象,负责和其它进程进行通信。

  • instrumentation
    这里的mInstrumentation是ActivityThread类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。

源码

说完几个基础概念,下面我们来看startActivity(Intent)的源码:

  1. startActivity函数也是调用了startActivityResult, 然后跟进去可以看到如下代码:

    Instrumentation.ActivityResult ar =
           mInstrumentation.execStartActivity(
               this, mMainThread.getApplicationThread(), mToken, this,
               intent, requestCode, options);

    这里就出现了我们上面提到的Instrumentation对象,它是监控应用程序和系统交互的类。执行execStartActivity方法,这里有两个参数重点看一下:
    mMainThread.getApplicationThread(): ApplicationThread对象,它是用来与服务端ActivityManagerServer交互的;
    mToken: IBinder对象;

  2. 下面是execStartActivity的源代码:

    public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
    try {
       intent.migrateExtraStreamToClipData();
       intent.prepareToLeaveProcess();
       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;
    }

    这里我省略了中间一段,就看核心的ActivityManagerNative.getDefault().startActivity这个函数,先看看getDefault获取了一个什么对象

  3. 下面是getDefault的实现:

    /*** Retrieve the system's default/global activity manager.
    */
    static public IActivityManager getDefault() {
    return gDefault.get();
    }
    private static final Singleton gDefault = new Singleton() {
     protected IActivityManager create() {
         //通过ServiceManager获取对应Service
         IBinder b = ServiceManager.getService("activity");
         if (false) {
             Log.v("ActivityManager", "default service binder = " + b);
         }
         IActivityManager am = asInterface(b);
         if (false) {
             Log.v("ActivityManager", "default service = " + am);
         }
         return am;
     }
    };

    上述代码我们看到一段熟悉的Binder机制代码, 就是ServiceManager.getService("activity"), 大概理解Binder机制就会知道,Binder是C/S架构,而Client客户端就是通过ServiceManager.getService的方式获取服务端代理对象(所以说是代理对象,因为真正的服务端在另外一个进程中)。

  4. 再回到刚刚ActivityManagerNative.getDefault().startActivity,getDefault是IActivityManager接口, 实例对象是ActivityManagerProxy,下面看看这个ActivityManagerProxy代码:
    这里就是经典的Binder的模式, 这里的mRemote就是上面第3步代码中获取的Service对象

  5. 第4步通过Binder机制(后面会再详细看看Binder机制, 简单说就是客户端方法映射到服务端的方法),所以这里就进入了服务端(另外一个进程)ActivityManagerService的startActivity函数:

    这里主要是调用了ActivityStackSupervisor类的startActivityMayWait方法, 下面会重点看一下ActivityStackSupervisor这个类的处理:

  6. startActivityMayWait(), 里面主要是对Intent做了解析,将要启动的Activity的信息保存在ActivityInfo(变量对应的是aInfo)中, 然后调用startActivityLocked方法;

  7. startActivityLocked: 这里又解析了一些信息,例如调用者callApp等,然后生成一个ActivityRecord对象

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                 requestCode, componentSpecified, voiceSession != null, this, container, options);
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                 startFlags, true, options, inTask);
  8. startActivityUncheckedLocked: 这个函数大约有六百多行代码,这个函数主要处理了Task相关的逻辑, 在AndroidManifest或者代码中, 我们可以定义Activity的4中启动模式: standard, singleTop, singleTask, singleInstance。这里就是判断了具体的启动模式,并根据当前Activity栈的情况,作出不同的处理。
    最终,走到一个基本的启动模式函数:targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)

  9. startActivityLocked在ActivityStack文件中,这里继续对Task相关的逻辑做处理,不做深入的分析了, 直接看接下来的处理: resumeTopActivitiesLocked
  10. resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options); 它的其中一个参数prev是在stack中的上一个activity, 那么这个函数要做的是对上一个activity做一些事情了,下面看具体的代码:
    // We need to start pausing the current activity so the top one
       // can be resumed...
       boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
       boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
       if (mResumedActivity != null) {
           if (DEBUG_STATES) Slog.d(TAG_STATES,
                   "resumeTopActivityLocked: Pausing " + mResumedActivity);
           pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
       }
    其中的注释说的很明白: 要启动top activity, 我们必须将目前正在运行的activity置于pause的状态。
  11. 下面又来到一个比较关键的节点:“将当前activity置于pause状态”, 代码如下:
    if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            }
    可以看到,最核心的是调用了prev.app.thread.schedulePauseActivity, 其中app是ProcessRecord对象,是当前正在前台运行的应用相关信息; thread是IApplicationThread对象,文中一开始的时候提到的ApplicationThread实现了这个接口,是应用进程和ActivityManagerService服务进程间通信的桥梁。
    下面要执行的就是进程间的通信了,这里是第二次执行Binder进程间通信了(第一次是第5步的时候, 应用进程作为客户端client,通知服务端AMS调用startActivity),这一次,则正好相反,是AMS进程通知应用进程执行pause activity操作。
    ------------一条分割线-------------
    这里再详细看看为什么thread.schedulePauseActivity可以完成一次Binder跨进程的调用,在一开始接触Binder的时候,都是client调用service的方法, 而service由ServiceManager对象管理,所以,client要调用service的时候,可以通过ServiceManager.getService("activity")这样的方法获取,现在是service调用client,那么service又是怎么知道我要调用哪个client呢?
    那要看看thread这个对象是怎么生成的? 通过一层层函数调用发现thread对象传递的流程如下:
    最开始, 当application启动的时候,ActivityThread的main函数作为应用程序的入口, 有如下这段代码:
    thread.attach(false);
    private void attach(boolean system) {
    ...
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            mgr.attachApplication(mAppThread);
            }
    ...
    }
    这里就通过Binder机制,将mAppThread对象,也就是我们一直提到ApplicationThread传递给ActivityManagerService, 而在service中的处理:
    public void handleMessage(Message msg) {
    switch (msg.what) {
        case ATTACH_APPLICATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
            if (app != null) {
                attachApplication(app);
            }
            reply.writeNoException();
            return true;
        }
    }
    }
    Override
    public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
    }
    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    app.makeActive(thread, mProcessStats);
    }
    public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
    thread = _thread;
    }
    上面这段代码, 很好的解释了, 我们上面看到的prev.app.thread对象, 就是当应用启动的时候从ActivityThread传递过来的ApplicationThread对象。所以调了thread.schedulePauseActivity, 就可以实现service与当前应用进程的通信;
    ------------又是一条分割线-------------
  12. 这里,我们又回到了应用进程, 执行的是ApplicationThread对象的schedulePauseActivity方法:

    public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

    因为ApplicationThread是ActivityThread的内部类,sendMessage函数是ActivityThread的实现, 如下:

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

    可以看到,这里是一个Handler发送消息的机制,ActivityThread的成员变量mH处理了来自ApplicationThread的PAUSEACTIVITY消息。至于这里为什么要用Handler机制呢?因为ApplicationThread作为和服务端交互的桥梁,它是单独挂起一个线程在接收服务端的消息的, 而下面我们要操作的是在主线程(UI线程)做PAUSEACTIVITY的处理, 所以这里就需要一个Handler把消息传递给主线程去执行相应操作。看下面的代码:

    //handler处理pause消息
    case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
    //ActivityThread处理pauseActivity
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }
    
            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());
    
            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
    
            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                 //通知服务端
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
    //由activity管理者来执行pause操作
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
            mInstrumentation.callActivityOnPause(r.activity);
            }
    //Activity 文件中的pause处理
    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

    可以看到,在最后Activity中的performPause() 函数中,调用了我们熟悉的生命周期函数onPause(), 到这里,就完成了服务端的PAUSEACTIVITY操作, 然后再ActivityThread中,又通知了服务端完成pauseActivity操作: ActivityManagerNative.getDefault().activityPaused(token);

  13. 下面又通过Binder机制回到Service端的代码, ActivityManagerService的activityPaused():

    Override
    public final void activityPaused(IBinder token) {
       final long origId = Binder.clearCallingIdentity();
       synchronized(this) {
           ActivityStack stack = ActivityRecord.getStackLocked(token);
           if (stack != null) {
               stack.activityPausedLocked(token, false);
           }
       }
       Binder.restoreCallingIdentity(origId);
    }
    //ActivityStack.java
    final void activityPausedLocked(IBinder token, boolean timeout) {
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
       mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
       if (mPausingActivity == r) {
           completePauseLocked(true);
       } 
    }
    }

    接下来继续执行resumeActivity的操作, 这里我省略了一些ActivityStack文件中的函数的跳转,直接看下面关键的节点函数:

    void startSpecificActivityLocked(ActivityRecord r,
           boolean andResume, boolean checkConfig) {
       // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
           r.info.applicationInfo.uid, true);
    
    r.task.stack.setLaunchTime(r);
    
    if (app != null && app.thread != null) {
       try {
           if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                   || !"android".equals(r.info.packageName)) {
               // Don't add this if it is a platform component that is marked
               // to run in multiple processes, because this is actually
               // part of the framework so doesn't make sense to track as a
               // separate apk in the process.
               app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                       mService.mProcessStats);
           }
           realStartActivityLocked(r, app, andResume, checkConfig);
           return;
       } catch (RemoteException e) {
           Slog.w(TAG, "Exception when starting activity "
                   + r.intent.getComponent().flattenToShortString(), e);
       }
    
       // If a dead object exception was thrown -- fall through to
       // restart the application.
    }
    
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
           "activity", r.intent.getComponent(), false, false, true);
    }

    这里的判断if (app != null && app.thread != null)中的两个变量在前面已经介绍过, 如果应用程序已经启动,在内部进行跳转的时候,这两个变量都是不为空的, 那么,我们就进入了realStartActivityLocked这个函数, 这个函数则会执行如下代码:

    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

    这段代码和上面app.thread.schedulePauseActivity非常相似, 这里也是通过Binder机制,又从服务端通知客户端ApplicationThread去执行scheduleLaunchActivity:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity a = performLaunchActivity(r, customIntent);
    }
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
    
       ActivityInfo aInfo = r.activityInfo;
       if (r.packageInfo == null) {
           r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                   Context.CONTEXT_INCLUDE_CODE);
       }
    
       ComponentName component = r.intent.getComponent();
       if (component == null) {
           component = r.intent.resolveActivity(
               mInitialApplication.getPackageManager());
           r.intent.setComponent(component);
       }
    
       if (r.activityInfo.targetActivity != null) {
           component = new ComponentName(r.activityInfo.packageName,
                   r.activityInfo.targetActivity);
       }
    
       Activity activity = null;
       try {
           java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
           activity = mInstrumentation.newActivity(
                   cl, component.getClassName(), r.intent);
           StrictMode.incrementExpectedActivityCount(activity.getClass());
           r.intent.setExtrasClassLoader(cl);
           r.intent.prepareToEnterProcess();
           if (r.state != null) {
               r.state.setClassLoader(cl);
           }
       } catch (Exception e) {
           if (!mInstrumentation.onException(activity, e)) {
               throw new RuntimeException(
                   "Unable to instantiate activity " + component
                   + ": " + e.toString(), e);
           }
       }
    
       try {
           Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    
           if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
           if (localLOGV) Slog.v(
                   TAG, r + ": app=" + app
                   + ", appName=" + app.getPackageName()
                   + ", pkg=" + r.packageInfo.getPackageName()
                   + ", comp=" + r.intent.getComponent().toShortString()
                   + ", dir=" + r.packageInfo.getAppDir());
    
           if (activity != null) {
               Context appContext = createBaseContextForActivity(r, activity);
               CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
               Configuration config = new Configuration(mCompatConfiguration);
               if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                       + r.activityInfo.name + " with config " + config);
               activity.attach(appContext, this, getInstrumentation(), r.token,
                       r.ident, app, r.intent, r.activityInfo, title, r.parent,
                       r.embeddedID, r.lastNonConfigurationInstances, config,
                       r.referrer, r.voiceInteractor);
    
               if (customIntent != null) {
                   activity.mIntent = customIntent;
               }
               r.lastNonConfigurationInstances = null;
               activity.mStartedActivity = false;
               int theme = r.activityInfo.getThemeResource();
               if (theme != 0) {
                   activity.setTheme(theme);
               }
    
               activity.mCalled = false;
               if (r.isPersistable()) {
                   mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
               } else {
                   mInstrumentation.callActivityOnCreate(activity, r.state);
               }
               if (!activity.mCalled) {
                   throw new SuperNotCalledException(
                       "Activity " + r.intent.getComponent().toShortString() +
                       " did not call through to super.onCreate()");
               }
               r.activity = activity;
               r.stopped = true;
               if (!r.activity.mFinished) {
                   activity.performStart();
                   r.stopped = false;
               }
               if (!r.activity.mFinished) {
                   if (r.isPersistable()) {
                       if (r.state != null || r.persistentState != null) {
                           mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                   r.persistentState);
                       }
                   } else if (r.state != null) {
                       mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                   }
               }
               if (!r.activity.mFinished) {
                   activity.mCalled = false;
                   if (r.isPersistable()) {
                       mInstrumentation.callActivityOnPostCreate(activity, r.state,
                               r.persistentState);
                   } else {
                       mInstrumentation.callActivityOnPostCreate(activity, r.state);
                   }
                   if (!activity.mCalled) {
                       throw new SuperNotCalledException(
                           "Activity " + r.intent.getComponent().toShortString() +
                           " did not call through to super.onPostCreate()");
                   }
               }
           }
           r.paused = true;
    
           mActivities.put(r.token, r);
    
       } 
    }
    }

    performLaunchActivity通过ClassLoader类加载机制生成Activity对象,然后通过Instrumentation去执行生命周期的函数, 同时还设置了主题等其他初始化操作。

到这里, 就基本将Activity启动流程走了一遍, 其中重点描述了几次Client与Service交互的操作,对于一些函数内部的实现没有深入分析,仅仅是走了一遍流程,在此做一些记录。

你可能感兴趣的:(Android源码——Activity启动流程)