美文网首页
Activity启动流程-2.3

Activity启动流程-2.3

作者: 海在路上 | 来源:发表于2022-04-15 16:38 被阅读0次

    Android 系统源代码情景分析,学习记录
    情景是启动未启动的应用的Activity


    startActivity.drawio.png

    Activity#startActivity

        @Override
        public void startActivity(Intent intent) {
            startActivityForResult(intent, -1);
        }
    
        public void startActivityForResult(Intent intent, int requestCode) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
            }
        }
    

    Instrumentation#execStartActivity

        public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
    
            try {
                int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            null, 0, token, target != null ? target.mEmbeddedID : null,
                            requestCode, false, false);
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
            }
            return null;
        }
    

    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) {
                // grantedUriPermissions = null; onlyIfNeeded = false;
                // debug = false; grantedMode = 0; 
            return mMainStack.startActivityMayWait(caller, intent, resolvedType,
                    grantedUriPermissions, grantedMode, resultTo, resultWho,
                    requestCode, onlyIfNeeded, debug, null, null);
        }
    

    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) {
                // grantedUriPermissions = null; 
                // outResult = null ; config = null
                // onlyIfNeeded = false;  debug = false;
            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) {
                aInfo = null;
            }
    
    
            synchronized (mService) {
                final long origId = Binder.clearCallingIdentity();
    
                int res = startActivityLocked(caller, intent, resolvedType,
                        grantedUriPermissions, grantedMode, aInfo,
                        resultTo, resultWho, requestCode, callingPid, callingUid,
                        onlyIfNeeded, componentSpecified);
                
                Binder.restoreCallingIdentity(origId);
    
                return res;
            }
        }
    

    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) {
                // grantedUriPermissions = null; 
                // outResult = null ; config = null
                // onlyIfNeeded = false;  debug = false;
                // grantedMode = 0;
    
            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 (DEBUG_RESULTS) Slog.v(
                    TAG, "Sending result to " + resultTo + " (index " + index + ")");
                if (index >= 0) {
                    sourceRecord = (ActivityRecord)mHistory.get(index);
                    if (requestCode >= 0 && !sourceRecord.finishing) {
                        resultRecord = sourceRecord;
                    }
                }
            }
    
            
            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);
        }
    

    ActivityStack#startActivityUncheckedLocked

        final int startActivityUncheckedLocked(ActivityRecord r,
                ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
                int grantedMode, boolean onlyIfNeeded, boolean doResume) {
                // grantedUriPermissions = null; grantedMode = 0; 
                // onlyIfNeeded = false; doResume = true;
            final Intent intent = r.intent;
            final int callingUid = r.launchedFromUid;
            
            int launchFlags = intent.getFlags();
            
            ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                    != 0 ? r : null;
    
            // 省略代码:是否需要 Intent.FLAG_ACTIVITY_NEW_TASK
    
            boolean addingToTask = false;
    
            // 确定要启动Activity的task
            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)) {
                        if (top.app != null && top.app.thread != null) {
                            if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                                logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
                                // For paranoia, make sure we have correctly
                                // resumed the top activity.
                                if (doResume) {
                                    resumeTopActivityLocked(null);
                                }
                                
                                top.deliverNewIntentLocked(callingUid, r.intent);
                                return START_DELIVERED_TO_TOP;
                            }
                        }
                    }
                }
    
            }
    
            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);
                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                        + " in new task " + r.task);
                newTask = true;
                if (mMainStack) {
                    mService.addRecentTaskLocked(r.task);
                }
                
            } else if (sourceRecord != null) {
                
                // An existing activity is starting this new activity, so we want
                // to keep the new one in the same task as the one that is starting
                // it.
                r.task = sourceRecord.task;
    
            }
    
            
            startActivityLocked(r, newTask, doResume);
            return START_SUCCESS;
        }
    

    ActivityStack#startActivityLocked

        private final void startActivityLocked(ActivityRecord r, boolean newTask,
                boolean doResume) {
                // newTask = true;  doResume = true;
            final int NH = mHistory.size();
    
            int addPos = -1;
    
            // Place a new activity at top of stack, so it is next to interact
            // with the user.
            if (addPos < 0) {
                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 (doResume) {
                resumeTopActivityLocked(null);
            }
        }
    
    

    ActivityStack#resumeTopActivityLocked

        final boolean resumeTopActivityLocked(ActivityRecord prev) {
            // prev == null;
            // 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) {
                // There are no more activities!  Let's just start up the
                // Launcher...
                if (mMainStack) {
                    return mService.startHomeActivityLocked();
                }
            }
    
            next.delayedResume = false;
            
            // If the top activity is the resumed one, nothing to do.
            if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                mService.mWindowManager.executeAppTransition();
                mNoAnimActivities.clear();
                return false;
            }
    
            // 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) {
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                mService.mWindowManager.executeAppTransition();
                mNoAnimActivities.clear();
                return false;
            }
            
            // The activity may be waiting for stop, but that is no longer
            // appropriate for it.
            mStoppingActivities.remove(next);
            mWaitingVisibleActivities.remove(next);
    
            if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
    
            // If we are currently pausing an activity, then don't do anything
            // until that is done.
            if (mPausingActivity != null) {
                if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
                return false;
            }
            
            // We need to start pausing the current activity so the top one
            // can be resumed...
            if (mResumedActivity != null) {
                if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
                startPausingLocked(userLeaving, false);
                return true;
            }
    
            return true;
        }
    

    ActivityStack#startPausingLocked

        private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
        // uiSleeping = false;
    
            ActivityRecord prev = mResumedActivity;
            
            mResumedActivity = null;
            mPausingActivity = prev;
            mLastPausedActivity = prev;
            prev.state = ActivityState.PAUSING;
            prev.task.touchActiveTime();
    
            mService.updateCpuStats();
            
            if (prev.app != null && prev.app.thread != null) {
                try {
                    
                    prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
                            prev.configChangeFlags);
                    if (mMainStack) {
                        mService.updateUsageStats(prev, false);
                    }
                } catch (Exception e) {
                    // Ignore exception, if process died other code will cleanup.
                    Slog.w(TAG, "Exception thrown during pause", e);
                    mPausingActivity = null;
                    mLastPausedActivity = null;
                }
            }
    
            // If we are not going to sleep, we want to ensure the device is
            // awake until the next activity is started.
            if (!mService.mSleeping && !mService.mShuttingDown) {
                mLaunchingActivity.acquire();
                if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
                    // To be safe, don't allow the wake lock to be held for too long.
                    Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
                    mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
                }
            }
    
    
            if (mPausingActivity != null) {
                // Have the window manager pause its key dispatching until the new
                // activity has started.  If we're pausing the activity just because
                // the screen is being turned off and the UI is sleeping, don't interrupt
                // key dispatch; the same activity will pick it up again on wakeup.
                if (!uiSleeping) {
                    prev.pauseKeyDispatchingLocked();
                } else {
                    if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
                }
    
                // Schedule a pause timeout in case the app doesn't respond.
                // We don't give it much time because this directly impacts the
                // responsiveness seen by the user.
                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
                msg.obj = prev;
                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
                if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
            }
        }
        
    

    ActivityThread#ApplicationThread#schedulePauseActivity

            public final void schedulePauseActivity(IBinder token, boolean finished,
                    boolean userLeaving, int configChanges) {
                queueOrSendMessage(
                        finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                        token,
                        (userLeaving ? 1 : 0),
                        configChanges);
            }
    
                    case PAUSE_ACTIVITY:
                        handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
                        maybeSnapshot();
                        break;
    

    ActivityThread#handlePauseActivity

        private final void handlePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges) {
            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;
                Bundle state = performPauseActivity(token, finished, true);
    
                // Make sure any pending writes are now committed.
                QueuedWork.waitToFinish();
                
                // Tell the activity manager we have paused.
                try {
                    ActivityManagerNative.getDefault().activityPaused(token, state);
                } catch (RemoteException ex) {
                }
            }
        }
    

    ActivityManagerService#activityPaused

        public final void activityPaused(IBinder token, Bundle icicle) {
            // Refuse possible leaked file descriptors
            if (icicle != null && icicle.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Bundle");
            }
    
            final long origId = Binder.clearCallingIdentity();
            mMainStack.activityPaused(token, icicle, false);
            Binder.restoreCallingIdentity(origId);
        }
    

    ActivityStack#activityPaused

        final void activityPaused(IBinder token, Bundle icicle, boolean timeout) {
            if (DEBUG_PAUSE) Slog.v(
                TAG, "Activity paused: token=" + token + ", icicle=" + icicle
                + ", timeout=" + timeout);
    
            ActivityRecord r = null;
    
            synchronized (mService) {
                int index = indexOfTokenLocked(token);
                if (index >= 0) {
                    r = (ActivityRecord)mHistory.get(index);
                    if (!timeout) {
                        r.icicle = icicle;
                        r.haveState = true;
                    }
                    mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
                    if (mPausingActivity == r) {
                        r.state = ActivityState.PAUSED;
                        completePauseLocked();
                    }
                }
            }
        }
    

    ActivityStack#completePauseLocked

        private final void completePauseLocked() {
            ActivityRecord prev = mPausingActivity;
            
            if (prev != null) {
                
                mPausingActivity = null;
            }
    
            if (!mService.mSleeping && !mService.mShuttingDown) {
                resumeTopActivityLocked(prev);
            } else {
                
            }
        }
    

    ActivityStack#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) {
                // There are no more activities!  Let's just start up the
                // Launcher...
                if (mMainStack) {
                    return mService.startHomeActivityLocked();
                }
            }
    
            next.delayedResume = false;
            
            
            // The activity may be waiting for stop, but that is no longer
            // appropriate for it.
            mStoppingActivities.remove(next);
            mWaitingVisibleActivities.remove(next);
    
    
            if (next.app != null && next.app.thread != null) {
                // 应用已启动的情况
    
            } else {
             // 应用未启动的情况。
                // Whoops, need to restart this activity!
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else {
                    if (SHOW_APP_STARTING_PREVIEW) {
                        mService.mWindowManager.setAppStartingWindow(
                                next, next.packageName, next.theme,
                                next.nonLocalizedLabel,
                                next.labelRes, next.icon, null, true);
                    }
                    
                }
                startSpecificActivityLocked(next, true, true);
            }
    
            return true;
        }
    

    ActivityStack#startSpecificActivityLocked

        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 (app != null && app.thread != null) {
                try {
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }
    
            }
    
            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false);
        }
    

    ActivityManagerService#startProcessLocked

        final ProcessRecord startProcessLocked(String processName,
                ApplicationInfo info, boolean knownToBeDead, int intentFlags,
                String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
            ProcessRecord app = getProcessRecordLocked(processName, info.uid);
            
            String hostingNameStr = hostingName != null
                    ? hostingName.flattenToShortString() : null;
            
            if (app == null) {
                app = newProcessRecordLocked(null, info, processName);
                mProcessNames.put(processName, info.uid, app);
            } else {
                // If this is a new package in the process, add the package to the list
                app.addPackage(info.packageName);
            }
    
            startProcessLocked(app, hostingType, hostingNameStr);
            return (app.pid != 0) ? app : null;
        }
    

    ActivityManagerService#startProcessLocked

        private final void startProcessLocked(ProcessRecord app,
                String hostingType, String hostingNameStr) {
            if (app.pid > 0 && app.pid != MY_PID) {
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.remove(app.pid);
                    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
                }
                app.pid = 0;
            }
    
            mProcessesOnHold.remove(app);
    
            updateCpuStats();
            
            System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);
            mProcDeaths[0] = 0;
            
            try {
                int uid = app.info.uid;
                int[] gids = null;
                try {
                    gids = mContext.getPackageManager().getPackageGids(
                            app.info.packageName);
                } catch (PackageManager.NameNotFoundException e) {
                    Slog.w(TAG, "Unable to retrieve gids", e);
                }
                
                int pid = Process.start("android.app.ActivityThread",
                        mSimpleProcessManagement ? app.processName : null, uid, uid,
                        gids, debugFlags, null);
                
                if (app.persistent) {
                    Watchdog.getInstance().processStarted(app.processName, pid);
                }
                
                
                if (pid == 0 || pid == MY_PID) {
                    ...
                } else if (pid > 0) {
                    app.pid = pid;
                    app.removed = false;
                    synchronized (mPidsSelfLocked) {
                        this.mPidsSelfLocked.put(pid, app);
                        Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
                        msg.obj = app;
                        mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
                    }
                } else {....}
            } catch (RuntimeException e) {....}
        }
    
    

    ActivityThread#main

        public static final void main(String[] args) {
            SamplingProfilerIntegration.start();
    
            Process.setArgV0("<pre-initialized>");
    
            Looper.prepareMainLooper();
            if (sMainThreadHandler == null) {
                sMainThreadHandler = new Handler();
            }
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            Looper.loop();
    
            thread.detach();
            String name = (thread.mInitialApplication != null)
                ? thread.mInitialApplication.getPackageName()
                : "<unknown>";
            Slog.i(TAG, "Main thread of " + name + " is now exiting");
        }
    
        private final void attach(boolean system) {
            sThreadLocal.set(this);
            mSystemThread = system;
            if (!system) {
                
                IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                }
            }
            
        }
    

    ActivityManagerService#attachApplication

        public final void attachApplication(IApplicationThread thread) {
            synchronized (this) {
                int callingPid = Binder.getCallingPid();
                final long origId = Binder.clearCallingIdentity();
                attachApplicationLocked(thread, callingPid);
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    ActivityManagerService#attachApplicationLocked

        private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid) {
    
            // Find the application record that is being attached...  either via
            // the pid if we are running in multiple processes, or just pull the
            // next app record if we are emulating process with anonymous threads.
            ProcessRecord app;
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);
                }
            }
    
            String processName = app.processName;
            try {
                thread.asBinder().linkToDeath(new AppDeathRecipient(
                        app, pid, thread), 0);
            } catch (RemoteException e) {
                
            }
            
            app.thread = thread;
            app.curAdj = app.setAdj = -100;
            app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
            app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
            app.forcingToForeground = null;
            app.foregroundServices = false;
            app.debugging = false;
    
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
    
            boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
            List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
            
            
            try {
                ensurePackageDexOpt(app.instrumentationInfo != null
                        ? app.instrumentationInfo.packageName
                        : app.info.packageName);
                if (app.instrumentationClass != null) {
                    ensurePackageDexOpt(app.instrumentationClass.getPackageName());
                }
                // 程序启动的的初始化,Application的创建和生成
                thread.bindApplication(processName, app.instrumentationInfo != null
                        ? app.instrumentationInfo : app.info, providers,
                        app.instrumentationClass, app.instrumentationProfileFile,
                        app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                        isRestrictedBackupMode || !normalMode,
                        mConfiguration, getCommonServicesLocked());
                updateLruProcessLocked(app, false, true);
                app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
            } catch (Exception e) {
                
            }
    
            boolean badApp = false;
            boolean didSomething = false;
    
            // See if the top visible activity is waiting to run in this process...
            ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
            if (hr != null && normalMode) {
                if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (Exception e) {
                       ...
                    }
                } else {
                    mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
                }
            }
    
            return true;
        }
    

    ActivityStack#realStartActivityLocked

        final boolean realStartActivityLocked(ActivityRecord r,
                ProcessRecord app, boolean andResume, boolean checkConfig)
                throws RemoteException {
    
            r.startFreezingScreenLocked(app, 0);
            mService.mWindowManager.setAppVisibility(r, true);
    
            r.app = app;
    
            int idx = app.activities.indexOf(r);
            if (idx < 0) {
                app.activities.add(r);
            }
            mService.updateLruProcessLocked(app, true, true);
    
            try {
                
                List<ResultInfo> results = null;
                List<Intent> newIntents = null;
                if (andResume) {
                    results = r.results;
                    newIntents = r.newIntents;
                }
                
                
                mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                        System.identityHashCode(r),
                        r.info, r.icicle, results, newIntents, !andResume,
                        mService.isNextTransitionForward());
                
                
            } catch (RemoteException e) {
                
            }
    
            if (andResume) {
                // As part of the process of launching, ActivityThread also performs
                // a resume.
                r.state = ActivityState.RESUMED;
                r.icicle = null;
                r.haveState = false;
                r.stopped = false;
                mResumedActivity = r;
                r.task.touchActiveTime();
                completeResumeLocked(r);
                pauseIfSleepingLocked();                
            } else {
                
            }
            
            return true;
        }
    

    ApplicationThread#scheduleLaunchActivity

            // we use token to identify this activity without having to send the
            // activity itself back to the activity manager. (matters more with ipc)
            public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                    ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
                    List<Intent> 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);
            }
    
            case LAUNCH_ACTIVITY: {
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;
    
                r.packageInfo = getPackageInfoNoCheck(
                      r.activityInfo.applicationInfo);
                handleLaunchActivity(r, null);
            } break;
    

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

    ActivityThread#performLaunchActivity

        private final 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,
                        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;
                    
                }
                r.paused = true;
    
                mActivities.put(r.token, r);
    
            } catch (SuperNotCalledException e) {
                ...
            } catch (Exception e) {
                ...
            }
    
            return activity;
        }
    
    

    ActivityThread# handleResumeActivity

        final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
            
    
            ActivityClientRecord r = performResumeActivity(token, clearHide);
    
            if (r != null) {
                final Activity a = r.activity;
    
                final int forwardBit = isForward ?
                        WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
    
                // If the window hasn't yet been added to the window manager,
                // and this guy didn't finish itself or start another activity,
                // then go ahead and add the window.
                boolean willBeVisible = !a.mStartedActivity;
                if (!willBeVisible) {
                    try {
                        willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                                a.getActivityToken());
                    } catch (RemoteException e) {
                    }
                }
                if (r.window == null && !a.mFinished && willBeVisible) {
                    r.window = r.activity.getWindow();
                    View decor = r.window.getDecorView();
                    decor.setVisibility(View.INVISIBLE);
                    ViewManager wm = a.getWindowManager();
                    WindowManager.LayoutParams l = r.window.getAttributes();
                    a.mDecor = decor;
                    l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                    l.softInputMode |= forwardBit;
                    if (a.mVisibleFromClient) {
                        a.mWindowAdded = true;
                        wm.addView(decor, l);
                    }
    
                // If the window has already been added, but during resume
                // we started another activity, then don't yet make the
                // window visible.
                } else if (!willBeVisible) {
                    if (localLOGV) Slog.v(
                        TAG, "Launch " + r + " mStartedActivity set");
                    r.hideForNow = true;
                }
    
                // The window is now visible if it has been added, we are not
                // simply finishing, and we are not starting another activity.
                if (!r.activity.mFinished && willBeVisible
                        && r.activity.mDecor != null && !r.hideForNow) {
                    if (r.newConfig != null) {
                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                                + r.activityInfo.name + " with newConfig " + r.newConfig);
                        performConfigurationChanged(r.activity, r.newConfig);
                        r.newConfig = null;
                    }
                    if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                            + isForward);
                    WindowManager.LayoutParams l = r.window.getAttributes();
                    if ((l.softInputMode
                            & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                            != forwardBit) {
                        l.softInputMode = (l.softInputMode
                                & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                                | forwardBit;
                        if (r.activity.mVisibleFromClient) {
                            ViewManager wm = a.getWindowManager();
                            View decor = r.window.getDecorView();
                            wm.updateViewLayout(decor, l);
                        }
                    }
                    r.activity.mVisibleFromServer = true;
                    mNumVisibleActivities++;
                    if (r.activity.mVisibleFromClient) {
                        r.activity.makeVisible();
                    }
                }
    
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
    
            } else {
                // If an exception was thrown when trying to resume, then
                // just end this activity.
                try {
                    ActivityManagerNative.getDefault()
                        .finishActivity(token, Activity.RESULT_CANCELED, null);
                } catch (RemoteException ex) {
                }
            }
        }
    
    

    相关文章

      网友评论

          本文标题:Activity启动流程-2.3

          本文链接:https://www.haomeiwen.com/subject/fkeysrtx.html