android activity that thing

    Activity, service and Application all inherit from ContextWrapper, so when we startActivity, we will go to the startActivity of ContextWrapper, and we can easily see that the startActivity in ContextWrapper is mBase.startActivity(intent); we have already said here before mBase is actually an instance of ContextImpl, and ContextImpl, like ContextWrapper, inherits from Context. So let's go to ContextImpl to see
    @Override
    public void startActivity(Intent intent) {
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity)null, intent, -1);
    }

    We can see that execStartActivity passes in 6 parameters. Let's pay attention to the fourth parameter is activity. Since today we mainly talk about the process, we don't care about the others. When we enter the Instrumentation class, we can see that there are two execStartActivities in it. The difference between them is that the fourth parameter is activity and the other is Fragment. Today we will look at the execStartActivity that is activity.
        try {
            intent.setAllowFds(false);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        null, 0, token, target != null ? target.mEmbeddedID : null,
                        requestCode, false, false, null, null, false);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }

Let's take a look at ActivityManagerNative.getDefault()
    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

Get an IActivityManager, let's look at gDefault
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            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;
        }
    };

Finally, get IActivityManager from asInterface(b)
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

Now we can understand that the IActivityManager we need is actually ActivityManagerProxy, so ActivityManagerNative.getDefault().startActivity becomes ActivityManagerProxy.startActivity
    public int startActivity(IApplicationThread caller, Intent intent,
            String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
            IBinder resultTo, String resultWho,
            int requestCode, boolean onlyIfNeeded,
            boolean debug, String profileFile, ParcelFileDescriptor profileFd,
            boolean autoStopProfiler) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeTypedArray(grantedUriPermissions, 0);
        data.writeInt(grantedMode);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(onlyIfNeeded ? 1 : 0);
        data.writeInt(debug ? 1 : 0);
        data.writeString(profileFile);
        if (profileFd != null) {
            data.writeInt(1);
            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        data.writeInt(autoStopProfiler ? 1 : 0);
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

Obviously, this is a matter of the binder, which will be discussed later, not much to say here, just look at where START_ACTIVITY_TRANSACTION finally went, that is, in onTransact of our ActivityManagerNative
        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() == 1;
            String profileFile = data.readString();
            ParcelFileDescriptor profileFd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
            boolean autoStopProfiler = data.readInt() != 0;
            int result = startActivity(app, intent, resolvedType,
                    grantedUriPermissions, grantedMode, resultTo, resultWho,
                    requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }

And where is the startActivity here? This is in ActivityManagerService
    public final int startActivity(IApplicationThread caller,
            Intent intent, String resolvedType, Uri[] grantedUriPermissions,
            int grantedMode, IBinder resultTo,
            String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
            String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
        return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                grantedUriPermissions, grantedMode, resultTo, resultWho,
                requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
                null, null);
    }

Obviously, we smartly go to ActivityStack to see startActivityMayWait is a bunch of codes here, we still only look for what we care about
            int res = startActivityLocked(caller, intent, resolvedType,
                    grantedUriPermissions, grantedMode, aInfo,
                    resultTo, resultWho, requestCode, callingPid, callingUid,
                    onlyIfNeeded, componentSpecified, null);

That's it, let's look at startActivityLocked here is still a bunch of codes, in startActivityLocked we can find
        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
                intent, resolvedType, aInfo, mService.mConfiguration,
                resultRecord, resultWho, requestCode, componentSpecified);

By the way, the ActivityRecord of our activity is created here. ActivityRecord records the instance of the Activity subclass in the application process, which we call the Activity of the feature space. These Activity class instances are Activities placed on the application side for actual interaction. no more explanation
        err = startActivityUncheckedLocked(r, sourceRecord,
                grantedUriPermissions, grantedMode, onlyIfNeeded, true);

This place passes our ActivityRecord instance in, and there is still a bunch of code in startActivityUncheckedLocked, we only look at the part of our activity that starts normally
startActivityLocked(r, newTask, doResume, keepCurTransition);

The doResume here is true, we can see it from the above parameters, let's go to startActivityLocked to see, select the main one, and we will explain the others when we have the opportunity to explain WindowManagerService
        if (doResume) {
            resumeTopActivityLocked(null);
        }

And in resumeTopActivityLocked we end up walking into
startSpecificActivityLocked(next, true, true);

inside, let's go see
    private final 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);
        
        if (r.launchTime == 0) {
            r.launchTime = SystemClock.uptimeMillis();
            if (mInitialStartTime == 0) {
                mInitialStartTime = r.launchTime;
            }
        } else if (mInitialStartTime == 0) {
            mInitialStartTime = SystemClock.uptimeMillis();
        }
        
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.info.packageName);
                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);
    }

The key here is
realStartActivityLocked(r, app, andResume, checkConfig);

Alright, don’t explain too much, just intercept the code we need
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration),
                    r.compat, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);

Here app is ProcessRecord, app.thread is IApplicationThread, app.thread.scheduleLaunchActivity is ApplicationThread.scheduleLaunchActivity is the inner class of ActivityThread
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profileFile = profileName;
            r.profileFd = profileFd;
            r.autoStopProfiler = autoStopProfiler;

            updatePendingConfiguration(curConfig);

            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
        }

Obviously, the required parameters are finally transmitted by sending the H.LAUNCH_ACTIVITY message
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                } break;

Finally, the activity we are familiar with is about to appear, that is,
handleLaunchActivity(r, null);

so let's move on
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        if (r.profileFd != null) {
            mProfiler.setProfiler(r.profileFile, r.profileFd);
            mProfiler.startProfiling();
            mProfiler.autoStopProfiler = r.autoStopProfiler;
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);
        Activity a = performLaunchActivity(r, customIntent);

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

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out
                // paused, because it needs to be visible but isn't in the
                // foreground.  We accomplish this by going through the
                // normal startup (because activities expect to go through
                // onResume() the first time they run, before their window
                // is displayed), and then pausing it.  However, in this case
                // we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just
                // retain the current state it has.
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    // We need to keep around the original state, in case
                    // we need to be created again.
                    r.state = oldState;
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
    }

I posted all this code because this is very critical, first let's see
Activity a = performLaunchActivity(r, customIntent);

申请了一个activity,这个performLaunchActivity里面代码过长就不全部粘贴了
        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);
            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);
            }
        }

我们可以发现先去获取了一个activity对象,然后
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

创建我们的Application,接着
    ContextImpl appContext = new ContextImpl();
    appContext.init(r.packageInfo, r.token, this);
    appContext.setOuterContext(activity);
    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());

    activity.attach(appContext, this, getInstrumentation(), r.token,
            r.ident, app, r.intent, r.activityInfo, title, r.parent,
            r.embeddedID, r.lastNonConfigurationInstances, config);

这里就是我们最开始提到的ContextImpl,也就是我们当时为什么说ContextWrapper里面的mBase是ContextImpl的一个实例,也就是这样的,不行的可以去activity.attach里面看看,这里不再解释。接着
    int theme = r.activityInfo.getThemeResource();
    if (theme != 0) {
        activity.setTheme(theme);
    }

就是设置我们的主题了,接下来就是我们的重点了
mInstrumentation.callActivityOnCreate(activity, r.state);

我们进去看看
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        if (mWaitingActivities != null) {
            synchronized (mSync) {
                final int N = mWaitingActivities.size();
                for (int i=0; i<N; i++) {
                    final ActivityWaiter aw = mWaitingActivities.get(i);
                    final Intent intent = aw.intent;
                    if (intent.filterEquals(activity.getIntent())) {
                        aw.activity = activity;
                        mMessageQueue.addIdleHandler(new ActivityGoing(aw));
                    }
                }
            }
        }
        
        activity.performCreate(icicle);
        
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

看到这里我们大致可以知道,我们创建activity的时候啥时候走我们的OnCreate了,也就是这里了,接着我们进去Activity中看看
    final void performCreate(Bundle icicle) {
        bringUpThreadPriority();
        onCreate(icicle);
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
    }

这里就是onCreate调用的地方,当我们继承了Activity的时候,走的就是我们Activity的onCreate。现在,我们回到ActivityThread的performLaunchActivity中,接着个callActivityOnCreate往下看
        if (!r.activity.mFinished) {
            activity.performStart();
            r.stopped = false;
        }

很明显了,我们去activity中看看performStart
    final void performStart() {
        bringUpThreadPriority();
        mFragments.noteStateNotSaved();
        mCalled = false;
        mFragments.execPendingActions();
        mInstrumentation.callActivityOnStart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onStart()");
        }
        mFragments.dispatchStart();
        if (mAllLoaderManagers != null) {
            for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
                LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
                lm.finishRetain();
                lm.doReportStart();
            }
        }
    }

也就是mInstrumentation.callActivityOnStart(this);我们进去看看
    public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

这里就是我们onStart的调用的地方那个了,当我们走过onCreate之后就是onStart,也就是我们这里,当我们继承了activity的时候,走的就是我们的onStart。现在,我们回到ActivityThread的handleLaunchActivity中,刚才我们说了performLaunchActivity,现在接着看
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward);

现在我们看看handleResumeActivity,同样我们还截取我们关心的部分
        ActivityClientRecord r;
        try {
            r = performResumeActivity(token, clearHide);
        } catch (Exception e) {
            Log.e(TAG, "Exception in performResumeActivity: " + e.getMessage() + ", finish it!");
            e.printStackTrace();
            r = null;
        }

我们看看performResumeActivity
    public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide) {
        ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);
        if (r != null && !r.activity.mFinished) {
            if (clearHide) {
                r.hideForNow = false;
                r.activity.mStartedActivity = false;
            }
            try {
                if (r.pendingIntents != null) {
                    deliverNewIntents(r, r.pendingIntents);
                    r.pendingIntents = null;
                }
                if (r.pendingResults != null) {
                    deliverResults(r, r.pendingResults);
                    r.pendingResults = null;
                }
                r.activity.performResume();

                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
                        r.activity.getComponentName().getClassName());

                r.paused = false;
                r.stopped = false;
                r.state = null;
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                        "Unable to resume activity "
                        + r.intent.getComponent().toShortString()
                        + ": " + e.toString(), e);
                }
            }
        }
        return r;
    }

这里没也就是r.activity.performResume();句话了,r是ActivityClientRecord,r.activity就是Activity,r.activity.performResume就是Activity.performResume,我们进去看看
    final void performResume() {
        performRestart();
        
        mFragments.execPendingActions();
        
        mLastNonConfigurationInstances = null;
        
        mCalled = false;
        // mResumed is set by the instrumentation
        mInstrumentation.callActivityOnResume(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onResume()");
        }

        // Now really resume, and install the current status bar and menu.
        mCalled = false;
        
        mFragments.dispatchResume();
        mFragments.execPendingActions();
        
        onPostResume();
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onPostResume()");
        }
    }

这里面就是mInstrumentation.callActivityOnResume(this);了,mInstrumentation就是Instrumentation,mInstrumentation.callActivityOnResume就是
    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();
        
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

很明显了,这里就是activity.onResume();我们们onResume的调用的地方了,如果继承了Activity就是走我们子类的onResume。我们还回到ActivityThread的handleLaunchActivity中,我们刚才说了handleResumeActivity,我们接看看会发现,下面是做了一些保护了,不再赘述。
 
至此,activity的前半生已经讲解完毕,至于后半生,等以后有机会再做讲解,还是那句话,这些文章给大师做取乐,给后来者抛砖引玉,不要再背后骂我,就谢天谢地了。

Guess you like

Origin blog.csdn.net/zhiyuan263287/article/details/18552947
Recommended