探究APP应用启动过程

一:前言

相信很多Android开发人员都知道Application、Activity的生命周期是什么,但是具体的启动流程却不太清晰,我们不是盲目的写代码,理清这一点可以帮助我们更好的学习。

二:从源码分析

1.app应用程序是由Launcher启动起来的

public final class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {
    ...

    public void onClick(View v) {
        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                pos[0] + v.getWidth(), pos[1] + v.getHeight()));
            startActivitySafely(intent, tag);
        } else if (tag instanceof FolderInfo) {
            ......
        }
    }

    void startActivitySafely(Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            startActivity(intent);
        } catch (ActivityNotFoundException e) {
            ......
        } 
    }
    ......
}

2.Activity.startActivityForResult(Launcher继承Activity往下执行startActivity)

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
        }else{...}
       }
}

主要代码:
mInstrumentation.execStartActivity(this,mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options)
字段解析:
mInstrumentation:
Instrumentation类,可以将Instrumentation理解为一种没有图形界面
的,具有启动能力的,用于监控app与android系统交互的工具类

mMainThread:
ActivityThread类,主线程,attach传入。

mToken:
IBinder对象,负责和ActivityThread进行进程间通信

3.Instrumentation.execStartActivity

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        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) {
        }
        return null;
    }

ActivityManagerNative.getDefault()得到的是ActivityManagerService的远程接口ActivityManagerProxy:

 static public IActivityManager getDefault() {
        return gDefault.get();
    }

 private static final Singleton gDefault = new Singleton() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
              ...
            IActivityManager am = asInterface(b);
              ...
            return am;
        }

static public IActivityManager asInterface(IBinder obj) {
        IActivityManager in =(IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ActivityManagerProxy(obj);
    }

4.ActivityManagerProxy.startActivity

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 {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

5. mRemote 实际通过ActivityManagerNative.getDefault进行注册的,实际就是ActivityManagerService
IBinder b = ServiceManager.getService(“activity”);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
调用binder的transact再到ActivityManagerNative的Ontransact方法

6.实际调用proxy中的Ontransact方法

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {

        data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
            int grantedMode = data.readInt();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();  
            int requestCode = data.readInt();
            boolean onlyIfNeeded = data.readInt() != 0;
            boolean debug = data.readInt() != 0;
            int result = startActivity(app, intent, resolvedType,
            grantedUriPermissions, grantedMode, resultTo, resultWho,
            requestCode, onlyIfNeeded, debug);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }

6 startActivity 实际调用ActivityManagerService中的startActivity方法

public final int startActivity(IApplicationThread caller,  
            Intent intent, String resolvedType, Uri[] grantedUriPermissions,  
            int grantedMode, IBinder resultTo,  
            String resultWho, int requestCode, boolean onlyIfNeeded,  
            boolean debug) {  
        return mMainStack.startActivityMayWait(caller, intent, resolvedType,  
            grantedUriPermissions, grantedMode, resultTo, resultWho,  
            requestCode, onlyIfNeeded, debug, null, null);  
    }  

7.ActivityStack.startActivityMayWait

final int startActivityMayWait(IApplicationThread caller,
            Intent intent, String resolvedType, Uri[] grantedUriPermissions,
            int grantedMode, IBinder resultTo,
            String resultWho, int requestCode, boolean onlyIfNeeded,
            boolean debug, WaitResult outResult, Configuration config) {

        ......

        boolean componentSpecified = intent.getComponent() != null;

        // Don't modify the client's object!
        intent = new Intent(intent);

        // Collect information about the target of the Intent.
        ActivityInfo aInfo;
        try {
            ResolveInfo rInfo =
                AppGlobals.getPackageManager().resolveIntent(
                intent, resolvedType,
                PackageManager.MATCH_DEFAULT_ONLY
                | ActivityManagerService.STOCK_PM_FLAGS);
            aInfo = rInfo != null ? rInfo.activityInfo : null;
        } catch (RemoteException e) {
            ......
        }

        if (aInfo != null) {
            // Store the found target back into the intent, because now that
            // we have it we never want to do this again.  For example, if the
            // user navigates back to this point in the history, we should
            // always restart the exact same activity.
            intent.setComponent(new ComponentName(
                aInfo.applicationInfo.packageName, aInfo.name));
            ......
        }

        synchronized (mService) {
            int callingPid;
            int callingUid;
            if (caller == null) {
                ......
            } else {
                callingPid = callingUid = -1;
            }
            mConfigWillChange = config != null
                && mService.mConfiguration.diff(config) != 0;
            ......
            if (mMainStack && aInfo != null &&(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {      
                      ......
            }

            int res = startActivityLocked(caller, intent, resolvedType,
                grantedUriPermissions, grantedMode, aInfo,
                resultTo, resultWho, requestCode, callingPid, callingUid,
                onlyIfNeeded, componentSpecified);

            if (mConfigWillChange && mMainStack) {
                ......
            }
            ......
            if (outResult != null) {
                ......
            }
            return res;
        }
    }

8.ActivityStack.startActivityLocked

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType,
            Uri[] grantedUriPermissions,
            int grantedMode, ActivityInfo aInfo, IBinder resultTo,
                String resultWho, int requestCode,
            int callingPid, int callingUid, boolean onlyIfNeeded,
            boolean componentSpecified) {
            int err = START_SUCCESS;

        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                ......
            }
        }
        ......
        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            int index = indexOfTokenLocked(resultTo);
            ......
            if (index >= 0) {
                sourceRecord = (ActivityRecord)mHistory.get(index);
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    ......
                }
            }
        }

        int launchFlags = intent.getFlags();
        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
            && sourceRecord != null) {
            ......
        }

        if (err == START_SUCCESS && intent.getComponent() == null) {
            ......
        }

        if (err == START_SUCCESS && aInfo == null) {
            ......
        }

        if (err != START_SUCCESS) {
            ......
        }
        ......
        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
            intent, resolvedType, aInfo, mService.mConfiguration,
            resultRecord, resultWho, requestCode, componentSpecified);

        ......

        return startActivityUncheckedLocked(r, sourceRecord,
            grantedUriPermissions, grantedMode, onlyIfNeeded, true);
    }

9.ActivityStack.startActivityUncheckedLocked

final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
        int grantedMode, boolean onlyIfNeeded, boolean doResume) {
        final Intent intent = r.intent;
        final int callingUid = r.launchedFromUid;

        int launchFlags = intent.getFlags();

        // We'll invoke onUserLeaving before onPause only if the launching
        // activity did not explicitly state that this is an automated launch.
        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;

        ......

        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;

        // If the onlyIfNeeded flag is set, then we can do this if the activity
        // being launched is the same as the one making the call...  or, as
        // a special case, if we do not know the caller then we count the
        // current top activity as the caller.
        if (onlyIfNeeded) {
            ......
        }

        if (sourceRecord == null) {
            ......
        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            ......
        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
            ......
        }

        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            ......
        }

        boolean addingToTask = false;
        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                // If bring to front is requested, and no result is requested, and
                // we can find a task that was started with this same
                // component, then instead of launching bring that one to the front.
                if (r.resultTo == null) {
                    // See if there is a task to bring to the front.  If this is
                    // a SINGLE_INSTANCE activity, there can be one and only one
                    // instance of it in the history, and it is always in its own
                    // unique task, so we do a special search.
                    ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                        ? findTaskLocked(intent, r.info)
                        : findActivityLocked(intent, r.info);
                    if (taskTop != null) {
                        ......
                    }
                }
        }
        ......
        if (r.packageName != null) {
            // If the activity being launched is the same as the one currently
            // at the top, then we need to check if it should only be launched
            // once.
            ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
            if (top != null && r.resultTo == null) {
                if (top.realActivity.equals(r.realActivity)) {
                    ......
                }
            }
        } else {
            ......
        }
        boolean newTask = false;
        // Should this be considered a new task?
        if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
                // todo: should do better management of integers.
                mService.mCurTask++;
                if (mService.mCurTask <= 0) {
                    mService.mCurTask = 1;
                }
                r.task = new TaskRecord(mService.mCurTask, r.info, intent,
                    (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);
                ......
                newTask = true;
                if (mMainStack) {
                    mService.addRecentTaskLocked(r.task);
                }
        } else if (sourceRecord != null) {
            ...
        } else {
            ...
        }
        ...
        startActivityLocked(r, newTask, doResume);
        return START_SUCCESS;
    }

10.startActivityLocked

private final void startActivityLocked(ActivityRecord r, boolean newTask,  
            boolean doResume) {  
        final int NH = mHistory.size();  

        int addPos = -1;  

        if (!newTask) {  
            ......  
        }  

        // Place a new activity at top of stack, so it is next to interact  
        // with the user.  
        if (addPos < 0) {  
            addPos = NH;  
        }  

        // If we are not placing the new activity frontmost, we do not want  
        // to deliver the onUserLeaving callback to the actual frontmost  
        // activity  
        if (addPos < NH) {  
            ......  
        }  

        // Slot the activity into the history stack and proceed  
        mHistory.add(addPos, r);  
        r.inHistory = true;  
        r.frontOfTask = newTask;  
        r.task.numActivities++;  
        if (NH > 0) {  
            // We want to show the starting preview window if we are  
            // switching to a new task, or the next activity's process is  
            // not currently running.  
            ......  
        } else {  
            // If this is the first activity, don't do any fancy animations,  
            // because there is nothing for it to animate on top of.  
            ......  
        }  
        ......  
        if (doResume) {  
            resumeTopActivityLocked(null);  
        }  
    }  

11.Activity.resumeTopActivityLocked

final boolean resumeTopActivityLocked(ActivityRecord prev) {  
        // Find the first activity that is not finishing.  
        ActivityRecord next = topRunningActivityLocked(null);  

        // Remember how we'll process this pause/resume situation, and ensure  
        // that the state is reset however we wind up proceeding.  
        final boolean userLeaving = mUserLeaving;  
        mUserLeaving = false;  

        if (next == null) {  
            ......  
        }  

        next.delayedResume = false;  

        // If the top activity is the resumed one, nothing to do.  
        if (mResumedActivity == next && next.state == ActivityState.RESUMED) {  
            ......  
        }  

        // If we are sleeping, and there is no resumed activity, and the top  
        // activity is paused, well that is the state we want.  
        if ((mService.mSleeping || mService.mShuttingDown)  
            && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {  
            ......  
        }  

        ......  

        // If we are currently pausing an activity, then don't do anything  
        // until that is done.  
        if (mPausingActivity != null) {  
            ......  
        }  

        ......  

        // We need to start pausing the current activity so the top one  
        // can be resumed...  
        if (mResumedActivity != null) {  
            ......  
            startPausingLocked(userLeaving, false);  
            return true;  
        }  

        ......  
    }  

11.ActivityStack.startPausingLocked

private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {  
        if (mPausingActivity != null) {  
            ......  
        }  
        ActivityRecord prev = mResumedActivity;  
        if (prev == null) {  
            ......  
        }  
        ......  
        mResumedActivity = null;  
        mPausingActivity = prev;  
        mLastPausedActivity = prev;  
        prev.state = ActivityState.PAUSING;  
        ......  

        if (prev.app != null && prev.app.thread != null) {  
            ......  
            try {  
                ......  
                prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,  
                    prev.configChangeFlags);  
                ......  
            } catch (Exception e) {  
                ......  
            }  
        } else {  
            ......  
        }  

        ......  

    }  

12.ApplicationThread.scheduleLaunchActivity

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
            ActivityInfo info, Bundle state, List pendingResults,  
            List pendingNewIntents, boolean notResumed, boolean isForward) {  
            ActivityClientRecord r = new ActivityClientRecord();  
            r.token = token;  
            r.ident = ident;  
            r.intent = intent;  
            r.activityInfo = info;  
            r.state = state;  
            r.pendingResults = pendingResults;  
            r.pendingIntents = pendingNewIntents;  
            r.startsNotResumed = notResumed;  
            r.isForward = isForward;  
            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);  
        }  

13.ActivityThread.queueOrSendMessage

 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {  
            synchronized (this) {  
                ......  
                Message msg = Message.obtain();  
                msg.what = what;  
                msg.obj = obj;  
                msg.arg1 = arg1;  
                msg.arg2 = arg2;  
                mH.sendMessage(msg);  
            }  
        }  

14.H.handleMessage

 case LAUNCH_ACTIVITY: {
          ActivityRecord r = (ActivityRecord)msg.obj;                           r.packageInfo=getPackageInfoNoCheck(r.activityInfo.applicationInfo);
          handleLaunchActivity(r);
                } 
         }

15.ActivityThread.handleLaunchActivity

private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
        ...  
        Activity a = performLaunchActivity(r, customIntent);  

        if (a != null) {  
            r.createdConfig = new Configuration(mConfiguration);  
            Bundle oldState = r.state;  
            handleResumeActivity(r.token, false, r.isForward);  

            ... 
        } else {  
            ...  
        }  
    }  

16.ActivityThread.performLaunchActivity

public final class ActivityThread {

    ......

    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo,
                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);
            r.intent.setExtrasClassLoader(cl);
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            ......
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ......

            if (activity != null) {
                ContextImpl appContext = new ContextImpl();
                appContext.init(r.packageInfo, r.token, this);
                appContext.setOuterContext(activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mConfiguration);
                ......
                activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstance,
                    r.lastNonConfigurationChildInstances, config);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstance = null;
                r.lastNonConfigurationChildInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                mInstrumentation.callActivityOnCreate(activity, r.state);
                ......
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
        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);
        } catch (SuperNotCalledException e) {
            ......
        } catch (Exception e) {
            ......
        }
        return activity;
    }

    ......
}

总结步骤

一:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity

二:ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态

三:Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行

四:ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信

五:ActivityManagerService通过Binder进程间通信机制通知ActivityThread,执行Activity的启动操作

你可能感兴趣的:(探究APP应用启动过程)