Activity Startup过程分析

本文详细分析了Android中Activity的启动过程,从点击桌面图标开始,涉及Activity.startActivity、Activity.startActivityForResult、Instrumentation.execStartActivity等多个步骤,直到Activity的创建和显示。通过时序图和代码解析,阐述了Activity启动时涉及到的关键组件和方法,包括Launcher、Intent、ActivityManagerService等的交互细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Activity Startup

Contents

SequenceDiagram..4

Startfrom click shortcut on Launcher.4

Activity.startActivity.6

Activity.startActivityForResult.7

Instrumentation.execStartActivity.8

Step7: ActivityManagerService.startActivity.9

Step8: ActivityStack.startActivityMayWait.10

Step9: ActivityStack. startActivityLocked.12

Step10: ActivityStack.startActivityUncheckedLocked.17

Step11: ActivityStack. startActivityLocked.25

Step12: ActivityStack.resumeTopActivityLocked.28

Step13: ActivityStack.startPausingLocked.36

Step14: ApplicationThread. schedulePauseActivity.39

Step15: ActivityThread.queueOrSendMessage.39

Step16: ActivityThread.Handler.handleMessage.39

Step17: ActivityThread.handlePauseActivity.40

Step18: ActivityThread.performPauseActivity.41

Step19: ActivityManagerService.activityPaused().42

Step20: ActivityStack.activityPaused().42

Step21: ActivityStack.completePauseLocked().43

Step22: ActivityStack.resumeTopActivityLocked().44

Step23: ActivityStack.startSpecificActivityLocked ().44

Step24: ActivityManagerService. startProcessLocked().45

Step25: ActivityManagerService.startProcessLocked().47

Step27: ActivityThread.main.49

Step28: ActivityThread.attach(false).50

Step 29: ActivityManagerService.attachApplication.50

Step 30: ActivityManagerService.attachApplicationLocked.51

Step31: ActivityStack. realStartActivityLocked.56

Step32: ActivityThread.scheduleLaunchActivity.58

Step33: ActivityThread. queueOrSendMessage(H.LAUNCH_ACTIVITY, r);58

Step34: ActivityThread.Handler.handleMessage.58

ActivityThread.handleLaunchActivity(r, null).58

 

 


 

启动一个新Activity可以通过2种方式,通过点击桌面图标;或者调用startActivity()/StartActivityForResult()。这个文档里主要讨论通过点击桌面应用图标的方式启动Activity。

为了讲解方便,把要启动的Activity命名为MyActivity 。在AndroidManifest.xml文件中做如下配置:

<activity android:name=".MyActivity"   

     android:label="@string/app_name">   

      <intent-filter>   

        <actionandroid:name="android.intent.action.MAIN" />   

        <categoryandroid:name="android.intent.category.LAUNCHER" />   

   </intent-filter>   

</activity>

先看看时序图有个大概的印象,下面就具体详细分析每一步是如何实现的。

 


在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,就是我们所熟知的Home。其它的应用程序安装后,就会在Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会把对应的应用程序启动起来。

在onClick()方法中不仅需要处理某个应用的启动,还包括针对点击folder和AllAppsButton的处理。

http://opengrok.sonyericsson.net/jellybean/xref/jb-lagan/packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

1845    /**

1846     * Launches the intent referred by theclicked shortcut.

1847     *

1848     * @param vThe view representing the clicked shortcut.

1849     */

1850    public voidonClick(View v) {

...

//Tag:

Unlike IDs, tags are not used toidentify views. Tags are essentially an extra piece of information that can beassociated with a view. They are most often used as a convenience to store datarelated to views in the views themselves rather than by putting them in aseparate structure.

1861        Objecttag = v.getTag();

1862        if (taginstanceof ShortcutInfo) {

1863            //Open shortcut

1864            finalIntent intent = ((ShortcutInfo) tag).intent;

1865            int[]pos = new int[2];

1866           v.getLocationOnScreen(pos);

1867            intent.setSourceBounds(newRect(pos[0], pos[1],

1868                   pos[0] + v.getWidth(), pos[1] + v.getHeight()));

1869           //这个函数调用是Activity启动的入口

1870            boolean success =startActivitySafely(v, intent, tag);

1871        //设置图标被点击、选中的状态

1872            if(success && v instanceof BubbleTextView) {

1873               mWaitingForResume = (BubbleTextView) v;

1874                mWaitingForResume.setStayPressed(true);

1875            }

1876        } else if(tag instanceof FolderInfo) {

1877            if (vinstanceof FolderIcon) {

1878               FolderIcon fi = (FolderIcon) v;

1879               handleFolderClick(fi);

1880            }

1881        } else if(v == mAllAppsButton) {

1882            if(isAllAppsVisible()) {

1883               showWorkspace(true);

1884            }else {

1885               onClickAllAppsButton(v);

1886            }

1887        }

1888    }

 

2009    boolean startActivitySafely(View v, Intentintent, Object tag) {

2010        booleansuccess = false;

2011        try {

2012            success = startActivity(v, intent,tag);

2013        } catch(ActivityNotFoundException e) {

2014            Toast.makeText(this,R.string.activity_not_found, Toast.LENGTH_SHORT).show();

2015           Log.e(TAG, "Unable to launch. tag=" + tag + "intent=" + intent, e);

2016        }

2017        returnsuccess;

2018    }

下面继续看Launcher.startActivity()

1982    boolean startActivity(View v, Intentintent, Object tag) {

1983       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

1984

1985        try {

1986            //Only launch using the new animation if the shortcut has not opted out (this isa

1987            //private contract between launcher and may be ignored in the future).

1988           boolean useLaunchAnimation = (v != null) &&

1989                   !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);

//下面这段绿色部分是插入的注释

// useLaunchAnimation should betrue, because “INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION” is NOT set inpackages/apps/Launcher2/src/com/android/launcher2/LauncherProvider.java, 

483            if (version < 12) {

484                // Contact shortcuts need adifferent set of flags to be launched now

485                // The updateContactsShortcutschange is idempotent, so we can keep using it like

486                // back in the Donut days

487                updateContactsShortcuts(db);

488                version = 12;

489            }

 

1990            if(useLaunchAnimation) {

1991               ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,

1992                       v.getMeasuredWidth(), v.getMeasuredHeight());

1993

1994               startActivity(intent, opts.toBundle());

1995            }else {

1996               startActivity(intent);

1997            }

1998           return true;

1999        } catch(SecurityException e) {

2000           Toast.makeText(this, R.string.activity_not_found,Toast.LENGTH_SHORT).show();

2001           Log.e(TAG, "Launcher does not have the permission to launch "+ intent +

2002                   ". Make sure to create a MAIN intent-filter for the correspondingactivity " +

2003                    "or use the exportedattribute for this activity. "

2004                   + "tag="+ tag + " intent=" + intent, e);

2005        }

2006        returnfalse;

2007    }

Activity.startActivity

这个函数里面直接调用startActivityForResult(),其中requestCode=-1表示不需要返回结果。

Activity.java

public void startActivity(Intentintent, Bundle options) {

        if (options!= null) {

            startActivityForResult(intent, -1, options);

        } else {

            // Notewe want to go through this call for compatibility with

            //applications that may have overridden the method.

           startActivityForResult(intent, -1);

        }

    }

Activity.startActivityForResult

这里的mMainThread是ActivityThread类型的Activity类成员变量,它代表的是应用程序的主线程,也就是Launcher应用程序运行的进程。这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个 Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。

这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。它在attch()方法中被赋值。

public void startActivityForResult(Intent intent, intrequestCode, Bundle options) {

        if (mParent== null) {// mParent == null表示启动的不是sub-activity

           Instrumentation.ActivityResult ar =

                mInstrumentation.execStartActivity(

                    this,mMainThread.getApplicationThread(), mToken, this,

                    intent, requestCode,options);

            if (ar !=null) {

               mMainThread.sendActivityResult(

                   mToken, mEmbeddedID, requestCode, ar.getResultCode(),

                   ar.getResultData());

            }

            if(requestCode >= 0) {

                // Ifthis start is requesting a result, we can avoid making

                //the activity visible until the result is received.  Setting

                //this code during onCreate(Bundle savedInstanceState) or onResume() will keepthe

                //activity hidden during this time, to avoid flickering.

                //This can only be done when a result is requested because

                //that guarantees we will get information back when the

                //activity is finished, no matter what happens to it.

               mStartedActivity = true;

            }

        } else {

            if(options != null) {

               mParent.startActivityFromChild(this, intent, requestCode, options);

            } else {

                //Note we want to go through this method for compatibility with

                //existing applications that may have overridden it.

               mParent.startActivityFromChild(this, intent, requestCode);

            }

        }

    }

Instrumentation.execStartActivity

Instrumentation.java中相同名字的函数一共有2个,一个是为了启动Activity,另外一个是在Fragment中启动Activty

检查mActivityMonitors列表中是否已经有该Activity对象了,如果存在而且该对象处于block状态,则不启动该Activity

调用AMS.execStartActivity()把启动新Activity的任务通过IPC交给AMS来完成。至此程序的运行已经脱离了Launcher当前运行的进程,进入到AMS的线程中去了。

调用checkStartActivityResult检查异常返回结果。

Instrumentation.java

public ActivityResult execStartActivity(

            Contextwho, IBinder contextThread, IBinder token,Activity target,

            Intentintent, int requestCode, Bundle options) {

       IApplicationThread whoThread = (IApplicationThread) contextThread;

//首先检查启动队列中是否已经包含了相同的启动任务,如果已经存在就不需要再启动新的了

        if(mActivityMonitors != null) {

           synchronized (mSync) {

                finalint N = mActivityMonitors.size();

                for(int i=0; i<N; i++) {

                   final ActivityMonitor am = mActivityMonitors.get(i);

                   if (am.match(who, null, intent)) {

                       am.mHits++;

                       if (am.isBlocking()) {

                           return requestCode >= 0 ? am.getResult() : null;

                       }

                       break;

                    }

                }

            }

        }

        try {

           intent.setAllowFds(false);

           intent.migrateExtraStreamToClipData();

            int result =ActivityManagerNative.getDefault()

                .startActivity(whoThread,intent,

                       intent.resolveTypeIfNeeded(who.getContentResolver()),

                        token, target != null ?target.mEmbeddedID : null,

                        requestCode, 0, null,null, options);

           checkStartActivityResult(result, intent);

        } catch(RemoteException e) {

        }

        return null;

    }

Step 7: ActivityManagerService.startActivity

此处传入的参数列表:

IApplicationThread caller:

ApplicationThread类型的Binder实体

int callingUid:

-1

Intent intent:

 

String resolvedType:

这里的intent.resolveTypeIfNeeded返回这个intent的MIME类型,在这个例子中,没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。

 IBinder resultTo:

一个代表发出启动新Activity请求的Activity token

String resultWho:

target != null ? target.mEmbeddedID : null

这里的target不为null,但是target.mEmbddedID为null

 int requestCode:

 -1

int startFlags:

0

String profileFile:

null

ParcelFileDescriptor profileFd:

null

WaitResult outResult:

null

Configuration config:

null

Bundle options:

 

这个函数所做的主要工作:

通过调用enforceNotIsolatedCaller()判断当前的请求者Binder.getCallingUid()是否允许启动Activity

ActivityManagerService.java

public final int startActivity(IApplicationThread caller,

            Intent intent, String resolvedType, IBinderresultTo,

            StringresultWho, int requestCode, int startFlags,

            StringprofileFile, ParcelFileDescriptor profileFd, Bundle options) {

       enforceNotIsolatedCaller("startActivity");//安全检查,用户是否已经被隔离,这里的用户id是通过Binder.getCallingUid()取得的

        int userId =0;

        if(intent.getCategories() != null &&intent.getCategories().contains(Intent.CATEGORY_HOME)) {

            //Requesting home, set the identity to the current user

            // HACK!

            userId =mCurrentUserId;

        } else {

            // TODO:Fix this in a better way - calls coming from SystemUI should probably carry

            // thecurrent user's userId

            if(Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {

               userId = 0;

            } else {

               userId = Binder.getOrigCallingUser();

            }

        }

        returnmMainStack.startActivityMayWait(caller, -1, intent, resolvedType,

                resultTo, resultWho,requestCode, startFlags, profileFile, profileFd,

                null, null, options, userId);

    }

 

Step 8: ActivityStack.startActivityMayWait

此处传入的参数列表:

IApplicationThread caller:

ApplicationThread类型的Binder实体

int callingUid:

-1

Intent intent:

 

String resolvedType:

这里的intent.resolveTypeIfNeeded返回这个intent的MIME类型,在这个例子中,没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。

 IBinder resultTo:

一个代表发出启动新Activity请求的Activity token

String resultWho:

target != null ? target.mEmbeddedID : null

这里的target不为null,但是target.mEmbddedID为null

 int requestCode:

 -1

int startFlags:

0

String profileFile:

null

ParcelFileDescriptor profileFd:

null

WaitResult outResult:

null

Configuration config:

null

Bundle options:

 

int userId:

Binder.getOrigCallingUser()

这个函数所做的主要工作:

调用resolveActivity()从PackageMangerService那里获取activity信息aInfo

 通过调用ActivityManagementService.startActivityMayWait()获取于此Activity相关的Application信息,并且保存在aInfo.applicationInfo中

final int startActivityMayWait(IApplicationThread caller,int callingUid,

            Intentintent, String resolvedType, IBinder resultTo,

            StringresultWho, int requestCode, int startFlags, String profileFile,

           ParcelFileDescriptor profileFd, WaitResult outResult, Configurationconfig,

            Bundle options, int userId) {

        // Refusepossible leaked file descriptors

        if (intent !=null && intent.hasFileDescriptors()) {

            throw newIllegalArgumentException("File descriptors passed in Intent");

        }

        booleancomponentSpecified = intent.getComponent() != null; // componentSpecified=true

 

        // Don'tmodify the client's object!

        intent = newIntent(intent);

 

        // Collectinformation about the target of the Intent.

        ActivityInfoaInfo = resolveActivity(intent, resolvedType, startFlags,

               profileFile, profileFd, userId);

        if (aInfo !=null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo)){

            userId =0;

        }

        aInfo =mService.getActivityInfoForUser(aInfo, userId);

 

        synchronized(mService) {

            intcallingPid;

//传入的参数callingUid=-1

            if(callingUid >= 0) {

               callingPid = -1;

            } else if(caller == null) {

               callingPid = Binder.getCallingPid();

               callingUid = Binder.getCallingUid();

            } else {

               callingPid = callingUid = -1;

            }

            //传入参数config=null,所以mConfigWillChange=false

           mConfigWillChange = config != null

                   && mService.mConfiguration.diff(config) != 0;

            if(DEBUG_CONFIGURATION) Slog.v(TAG,

                   "Starting activity when config will change = " +mConfigWillChange);

            //http://blog.chinaunix.net/uid-12469487-id-3050585.html

            finallong origId = Binder.clearCallingIdentity();

            //对于这个判断(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0,因为aInfo.applicationInfo.flags中不包含ApplicationInfo.FLAG_CANT_SAVE_STATE标志,所以它的值=false

//下面这段不会执行

            if(mMainStack && aInfo != null &&

                   (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE)!= 0) {

                …

            }

           

            int res =startActivityLocked(caller, intent, resolvedType,

                    aInfo, resultTo, resultWho,requestCode, callingPid, callingUid,

                    startFlags, options,componentSpecified, null);

           

            if(mConfigWillChange && mMainStack) { // mConfigWillChange=false

                // Ifthe caller also wants to switch to a new configuration,

                // do so now.  This allows a clean switch, as we are waiting

                //for the current activity to pause (so we will not destroy

                //it), and have not yet started the next activity.

               mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,

                       "updateConfiguration()");

               mConfigWillChange = false;

                if(DEBUG_CONFIGURATION) Slog.v(TAG,

                       "Updating to new configuration after starting activity.");

               mService.updateConfigurationLocked(config, null, false, false);

            }

           

           Binder.restoreCallingIdentity(origId);

           

            if(outResult != null) {  //outResult=null

                outResult.result = res;

                if(res == ActivityManager.START_SUCCESS) {

                   mWaitingActivityLaunched.add(outResult);

                   do {

                       try {

                           mService.wait();

                       } catch (InterruptedException e) {

                       }

                    }while (!outResult.timeout && outResult.who == null);

                }else if (res == ActivityManager.START_TASK_TO_FRONT) {

                    ActivityRecordr = this.topRunningActivityLocked(null);

                   if (r.nowVisible) {

                       outResult.timeout = false;

                       outResult.who = new ComponentName(r.info.packageName, r.info.name);

                        outResult.totalTime = 0;

                       outResult.thisTime = 0;

                    }else {

                       outResult.thisTime = SystemClock.uptimeMillis();

                       mWaitingActivityVisible.add(outResult);

                        do {

                           try {

                               mService.wait();

                           } catch (InterruptedException e) {

                           }

                       } while (!outResult.timeout && outResult.who == null);

                    }

                }

            }

           

            returnres;

        }

    }

Step 9: ActivityStack. startActivityLocked

这个函数所做的主要工作:

从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了。

前面说过,参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个启动者Activity的相关信息,保存在sourceRecord变量中。

通过launchFlags = intent.getFlags()获取launchFlags信息,对launchFlags中的各种flag进行判断和处理。针对当前场景下,我们只设置了NEW_TASK标志,所以这里的判断和检查都不适用。

判断callingPid和callingUid是否有权限启动新的Activity。

创建即将要启动的Activity的相关信息,并保存在(ActivityRecord)r变量中

如果有pending activities需要先处理,调用mService.doPendingActivityLaunchesLocked(),在doPendingActivityLaunchesLocked() 中会调用startActivityUncheckedLocked()进一步处理,也就是先启动pending acitivies。

上面的事情做完后,才执行startActivityUncheckedLocked()启动我们要启动的Activity。

2403    final intstartActivityLocked(IApplicationThread caller,

2404            Intent intent, String resolvedType,ActivityInfo aInfo, IBinder resultTo,

2405            String resultWho, int requestCode,

2406            int callingPid, int callingUid, intstartFlags, Bundle options,

2407            boolean componentSpecified,ActivityRecord[] outActivity) {

2408

2409        int err =ActivityManager.START_SUCCESS;

2410

2411       ProcessRecord callerApp = null;

//从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了。

2412        if(caller != null) {

2413           callerApp = mService.getRecordForAppLocked(caller);

2414            if(callerApp != null) {

2415               callingPid = callerApp.pid;

2416                callingUid= callerApp.info.uid;

2417            }else {

2418               Slog.w(TAG, "Unable to find app for caller " + caller

2419                     + " (pid=" + callingPid + ") when starting: "

2420                     + intent.toString());

2421                err =ActivityManager.START_PERMISSION_DENIED;

2422            }

2423        }

2424

2425        if (err== ActivityManager.START_SUCCESS) {

2426            finalint userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0;

2427           Slog.i(TAG, "START {" + intent.toShortString(true, true, true,false)

2428                   + " u=" + userId + "} from pid " + (callerApp !=null ? callerApp.pid : callingPid));

//更新env环境变量信息env->ReleaseStringUTFChars(activity, actStr);

2429           mActivityTrigger.activityStartTrigger(intent);

2430        }

2431

2432       ActivityRecord sourceRecord = null;

2433       ActivityRecord resultRecord = null;

//前面说过,参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。

2434        if(resultTo != null) {    //resultTo !=null

2435            intindex = indexOfTokenLocked(resultTo);

2436            if(DEBUG_RESULTS) Slog.v(

2437               TAG, "Will send result to " + resultTo + " (index "+ index + ")");

2438            if(index >= 0) {

2439               sourceRecord = mHistory.get(index);

//resultCode=-1

2440               if (requestCode >= 0 && !sourceRecord.finishing) {

2441                   resultRecord = sourceRecord;

2442                }

2443            }

2444        }

2445

2446        intlaunchFlags = intent.getFlags();

2447      //条件不满足

2448        if((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0

2449               && sourceRecord != null) {

2464        }

2465    //条件不满足

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

2467            // We couldn't find a class that canhandle the given Intent.

2468            //That's the end of that!

2469            err =ActivityManager.START_INTENT_NOT_RESOLVED;

2470        }

2471 //ainfo != null

2472        if (err== ActivityManager.START_SUCCESS && aInfo == null) {

2473            // Wecouldn't find the specific class specified in the Intent.

2474            //Also the end of the line.

2475            err =ActivityManager.START_CLASS_NOT_FOUND;

2476        }

2477 //条件不满足

2478        if (err!= ActivityManager.START_SUCCESS) {

2479            if(resultRecord != null) {

2480               sendActivityResultLocked(-1,

2481                   resultRecord, resultWho, requestCode,

2482                   Activity.RESULT_CANCELED, null);

2483            }

2484           mDismissKeyguardOnNextActivity = false;

2485           ActivityOptions.abort(options);

2486           return err;

2487        }

2488 //此处的启动当然有权限

2489        final intstartAnyPerm = mService.checkPermission(

2490               START_ANY_ACTIVITY, callingPid, callingUid);

2491        final intcomponentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,

2492               callingUid, aInfo.applicationInfo.uid, aInfo.exported);

2493        if (startAnyPerm != PERMISSION_GRANTED&& componentPerm != PERMISSION_GRANTED) {

2494            if(resultRecord != null) {

2495               sendActivityResultLocked(-1,

2496                   resultRecord, resultWho, requestCode,

2497                    Activity.RESULT_CANCELED, null);

2498            }

2499           mDismissKeyguardOnNextActivity = false;

2500           String msg;

2501            if(!aInfo.exported) {

2502               msg = "Permission Denial: starting " + intent.toString()

2503                       + " from " + callerApp + " (pid=" + callingPid

2504                       + ", uid=" + callingUid + ")"

2505                       + " not exported from uid " + aInfo.applicationInfo.uid;

2506            }else {

2507                msg = "Permission Denial:starting " + intent.toString()

2508                       + " from " + callerApp + " (pid=" + callingPid

2509                       + ", uid=" + callingUid + ")"

2510                       + " requires " + aInfo.permission;

2511            }

2512           Slog.w(TAG, msg);

2513            thrownew SecurityException(msg);

2514        }

2515

2516        if(mMainStack) {

2517            if(mService.mController != null) {

2518               boolean abort = false;

2519               try {

2520                   // The Intent we give to the watcher has the extra data

2521                   // stripped off, since it can contain private information.

2522                   Intent watchIntent = intent.cloneFilter();

//mService.mController.activityStarting() always return true

2523                   abort = !mService.mController.activityStarting(watchIntent,

2524                           aInfo.applicationInfo.packageName);

2525                }catch (RemoteException e) {

2526                   mService.mController = null;

2527                }

2528

2529               if (abort) {

2530                   if (resultRecord != null) {

2531                       sendActivityResultLocked(-1,

2532                           resultRecord, resultWho,requestCode,

2533                           Activity.RESULT_CANCELED, null);

2534                   }

2535                   // We pretend to the caller that it was really started, but

2536                   // they will just get a cancel result.

2537                   mDismissKeyguardOnNextActivity = false;

2538                   ActivityOptions.abort(options);

2539                   return ActivityManager.START_SUCCESS;

2540                }

2541            }

2542        }

2543  //创建即将要启动的Activity的相关信息,并保存在r变量中

2544       ActivityRecord r = new ActivityRecord(mService, this, callerApp,callingUid,

2545               intent, resolvedType, aInfo, mService.mConfiguration,

2546               resultRecord, resultWho, requestCode, componentSpecified);

2547        if(outActivity != null) {

2548           outActivity[0] = r;

2549        }

2550 // 此场景下 条件不满足,因为mService.checkAppSwitchAllowedLocked() should  return true

2551        if(mMainStack) {

2552            if(mResumedActivity == null

2553                   || mResumedActivity.info.applicationInfo.uid != callingUid) {

2554               if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,"Activity start")) {

2555                   PendingActivityLaunch pal = new PendingActivityLaunch();

2556                   pal.r = r;

2557                   pal.sourceRecord = sourceRecord;

2558                   pal.startFlags = startFlags;

2559                   mService.mPendingActivityLaunches.add(pal);

2560                    mDismissKeyguardOnNextActivity = false;

2561                   ActivityOptions.abort(options);

2562                   return ActivityManager.START_SWITCHES_CANCELED;

2563                }

2564            }

2565//是否允许Activity switch,这个变量在ActivityManagerService.java.stopAppSwitches()中被设置成false,与之个的一个变量是APP_SWITCH_DELAY_TIME,关于它的解释如下:

// Amount of time after a call to stopAppSwitches() duringwhich we will prevent further untrusted switches from happening.

2566            if(mService.mDidAppSwitch) {

2567               // This is the second allowed switch since we stopped switches,

2568               // so now just generally allow switches. Use case: user presses

2569               // home (switches disabled, switch to home, mDidAppSwitch now true);

2570               // user taps a home icon (coming from home so allowed, we hit here

2571               // and now allow anyone to switch again).

2572               mService.mAppSwitchesAllowedTime = 0;

2573            }else {

2574               mService.mDidAppSwitch = true;

2575            }

2576  //如果有pending activities需要先处理

2577           mService.doPendingActivityLaunchesLocked(false);

2578        }

2579

2580        err = startActivityUncheckedLocked(r,sourceRecord,

2581                startFlags, true, options);

2582        if(mDismissKeyguardOnNextActivity && mPausingActivity == null) {

2583            //Someone asked to have the keyguard dismissed on the next

2584            //activity start, but we are not actually doing an activity

2585            //switch...  just dismiss the keyguard now,because we

2586            //probably want to see whatever is behind it.

2587           mDismissKeyguardOnNextActivity = false;

2588           mService.mWindowManager.dismissKeyguard();

2589        }

2590        returnerr;

2591    }

 

Step 10: ActivityStack.startActivityUncheckedLocked

这个函数所做的主要工作:

这个函数的最重要工作就是确定Activity运行的Task,各种情况判断比较多,但是对于本文涉及的场景就简单些,因为我们的Activity在开始阶段的launcher.startActivity中就已经为intent设置了FLAG_ACTIVITY_NEW_TASK标志,所以最终就会创建一个新的Task。

首先获得intent的标志值,保存在launchFlags变量中。

根据Activity.launchMode来判断是否需要给当前Activity. launchFlags添加Intent.FLAG_ACTIVITY_NEW_TASK标志。为(target activity)r.launchFlags添加FLAG_ACTIVITY_NEW_TASK标志的条件包括:

1)sourceRecord == null

2)sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE

3)r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK

 

满足(r.resultTo != null &&(launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0)条件,立刻返回结果给调用者。因为startActivityForResult()是不能跨越不同task的。

调用findTaskLocked()搜索当前有没有Task可以用来执行这个Activity。由于r.launchMode的值不为ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task。如果是第一次运行,返回的结果是null,(只有当目标Activity存在而且在task顶端才满足查找条件)即taskTop为null,因此,需要创建一个新的Task来启动这个Activity。

检查需要启动的Activity与现在的topactivity是否相同?不同,因此不需要执行resume top activtity,进一步分析:resume top activity还必须满足其他条件:launchMode中还必须设置了FLAG_ACTIVITY_SINGLE_TOP或者.LAUNCH_SINGLE_TOP或者LAUNCH_SINGLE_TASK。

如果没有可以可用的task,给当前的Activity创建和赋值一个task.

r.setTask(new TaskRecord(mService.mCurTask, r.info, intent),null, true);

调用startActivityLocked(r, newTask,doResume, keepCurTransition, options)继续执行。

 

2603    final intstartActivityUncheckedLocked(ActivityRecord r,

2604            ActivityRecord sourceRecord, intstartFlags, boolean doResume,

2605            Bundle options) {

//doReume=true

2606        finalIntent intent = r.intent;

2607        final intcallingUid = r.launchedFromUid;

2608        final intuserId = r.userId;

2609 //函数首先获得intent的标志值,保存在launchFlags变量中。

2610        intlaunchFlags = intent.getFlags();

2611 //这个intent的标志值的位Intent.FLAG_ACTIVITY_NO_USER_ACTION没有置位,因此 ,成员变量mUserLeaving的值为true。

2612        // We'llinvoke onUserLeaving before onPause only if the launching

2613        //activity did not explicitly state that this is an automated launch.

2614       mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) ==0; // mUserLeaving=true

2615        if(DEBUG_USER_LEAVING) Slog.v(TAG,

2616               "startActivity() => mUserLeaving=" + mUserLeaving);

2617

2618        // If thecaller has asked not to resume at this point, we make note

2619        // ofthis in the record so that we can skip it when trying to find

2620        // thetop running activity.

2621        if(!doResume) {

2622           r.delayedResume = true;

2623        }

2624     //没有设置这个标志,所以notTop=null

2625       ActivityRecord notTop =(launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)

2626               != 0 ? r : null;

2627 //startFlags = 0 这个参数是从上面一路传下来的

2628        // If theonlyIfNeeded flag is set, then we can do this if the activity

2629        // beinglaunched is the same as the one making the call...  or, as

2630        // aspecial case, if we do not know the caller then we count the

2631        //current top activity as the caller.

2632        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)!= 0) {

2633           ActivityRecord checkedCaller = sourceRecord;

2634            if(checkedCaller == null) {

2635               checkedCaller = topRunningNonDelayedActivityLocked(notTop);

2636            }

2637            if(!checkedCaller.realActivity.equals(r.realActivity)) {

2638               // Caller is not the same as launcher, so always needed.

2639               startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;

2640            }

2641        }

2642

2643        if(sourceRecord == null) {

2644            //This activity is not being started from another...  in this

2645            //case we -always- start a new task.

2646            if((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {

2647               Slog.w(TAG, "startActivity called from non-Activity context;forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "

2648                     + intent);

2649               launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;

2650            }

2651        } else if(sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {

2652            //The original activity who is starting us is running as a single

2653            //instance...  this new activity it isstarting must go on its

2654            // own task.

2655           launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;

2656        } else if(r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE

2657               || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {

2658            //The activity being started is a single instance...  it always

2659            //gets launched into its own task.

2660           launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;

2661        }

2662//我们刚好满足了下面这个条件,所以launcher就会通过onActivityResult()收到启动新activity结果的回调

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

2664            //For whatever reason this activity is being launched into a new

2665            // task...  yet the caller has requested a resultback.  Well, that

2666            // ispretty messed up, so instead immediately send back a cancel

2667            //and let the new task continue launched as normal without a

2668            //dependency on its originator.

2669           Slog.w(TAG, "Activity is launching as a new task, so cancellingactivity result.");

2670           sendActivityResultLocked(-1,

2671                   r.resultTo, r.resultWho, r.requestCode,

2672               Activity.RESULT_CANCELED, null);

2673           r.resultTo = null;

2674        }

2675

2676        booleanaddingToTask = false;

2677        booleanmovedHome = false;

2678       TaskRecord reuseTask = null;

//在要启动new Activity之初的Launcher.startActivity中,Intent.FLAG_ACTIVITY_NEW_TASK就已经被设置了,因此下面的语句将被执行

//  这段代码的逻辑是,当前有没有Task可以用来执行这个Activity。由于r.launchMode的值不为 ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task, 这里返回的结果是null,即taskTop为null,因此,需要创建一个新的Task来启动这个Activity。

2679        if(((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&

2680               (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)

2681               || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK

2682               || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {

2683            // If bring to front is requested,and no result is requested, and

2684            // we can find a task that wasstarted with this same

2685            // component, then instead oflaunching bring that one to the front.

2686            if (r.resultTo == null) {

2687                // See if there is a task tobring to the front.  If this is

2688                // a SINGLE_INSTANCE activity,there can be one and only one

2689                // instance of it in thehistory, and it is always in its own

2690                // unique task, so we do aspecial search.

2691               ActivityRecord taskTop = r.launchMode !=ActivityInfo.LAUNCH_SINGLE_INSTANCE

2692                       ? findTaskLocked(intent, r.info)//条件是只有当目标Activity存在而且在task顶端。请牢记这个条件,只有这样后续的moveTaskToFrontLocked()才会成立

2693                       : findActivityLocked(intent, r.info);

2694               if (taskTop != null) { //当前场景中,我们假设这是第一次启动,所以taskTop=null

2695                   if (taskTop.task.intent == null) {

2696                       // This task was started because of movement of

2697                       // the activity based on affinity... now that we

2698                       // are actually launching it, we can assign the

2699                        // base intent.

2700                       taskTop.task.setIntent(intent, r.info);

2701                   }

2702                   // If the target task is not in the front, then we need

2703                   // to bring it to the front... except...  well, with

2704                   // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like

2705                   // to have the same behavior as if a new instance was

2706                   // being started, which means not bringing it to the front

2707                   // if the caller is not itself in the front.

2708                   ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);

2709                   if (curTop != null && curTop.task != taskTop.task) {//如果当前最顶端运行的activity.task不是我们要恢复的task

2710                       r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);

2711                       boolean callerAtFront = sourceRecord == null

2712                                || curTop.task== sourceRecord.task;

2713                       if (callerAtFront) {//如果是调用者在最顶端

2714                            // We really dowant to push this one into the

2715                            // user's face,right now.

2716                            movedHome = true;

2717                           moveHomeToFrontFromLaunchLocked(launchFlags);

2718                           moveTaskToFrontLocked(taskTop.task, r, options);

2719                            options = null;

2720                       }

2721                    }

2722                   // If the caller has requested that the target task be

2723                   // reset, then do so.

2724                   if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {

2725                       taskTop =resetTaskIfNeededLocked(taskTop, r);

2726                   }

2727                   if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {

2728                       // We don't need to start a new activity, and

2729                        // the client said not to doanything if that

2730                       // is the case, so this is it! And for paranoia, make

2731                       // sure we have correctly resumed the top activity.

2732                       if (doResume) {

2733                           resumeTopActivityLocked(null, options);

2734                       } else {

2735                           ActivityOptions.abort(options);

2736                       }

2737                       return ActivityManager.START_RETURN_INTENT_TO_CALLER;

2738                   }

2739                   if ((launchFlags &

2740                           (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))

2741                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)){

2742                       // The caller has requested to completely replace any

2743                       // existing task with its new activity. Well that should

2744                       // not be too hard...

2745                       reuseTask = taskTop.task;

2746                       performClearTaskLocked(taskTop.task.taskId);

2747                       reuseTask.setIntent(r.intent, r.info);

2748                   } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0

2749                            || r.launchMode ==ActivityInfo.LAUNCH_SINGLE_TASK

2750                            || r.launchMode ==ActivityInfo.LAUNCH_SINGLE_INSTANCE) {

2751                       // In this situation we want to remove all activities

2752                       // from the task up to the one being started.  In most

2753                       // cases this means we are resetting the task to its

2754                       // initial state.

2755                        ActivityRecord top =performClearTaskLocked(

2756                               taskTop.task.taskId, r, launchFlags);

2757                       if (top != null) {

2758                            if(top.frontOfTask) {

2759                                // Activity aliases may meanwe use different

2760                                // intents forthe top activity, so make sure

2761                                // the task nowhas the identity of the new

2762                                // intent.

2763                               top.task.setIntent(r.intent, r.info);

2764                            }

2765                           logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);

2766                            top.deliverNewIntentLocked(callingUid,r.intent);

2767                       } else {

2768                            // A special case:we need to

2769                            // start theactivity because it is not currently

2770                            // running, and thecaller has asked to clear the

2771                            // current task tohave this activity at the top.

2772                            addingToTask =true;

2773                            // Now pretend likethis activity is being started

2774                            // by the top ofits task, so it is put in the

2775                            // right place.

2776                            sourceRecord =taskTop;

2777                       }

2778                   } else if (r.realActivity.equals(taskTop.task.realActivity)) {

2779                       // In this case the top activity on the task is the

2780                       // same as the one being launched, so we take that

2781                       // as a request to bring the task to the foreground.

2782                       // If the top activity in the task is the root

2783                       // activity, deliver this new intent to it if it

2784                       // desires.

2785                       if((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0

2786                                &&taskTop.realActivity.equals(r.realActivity)) {

2787                           logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);

2788                            if (taskTop.frontOfTask) {

2789                               taskTop.task.setIntent(r.intent, r.info);

2790                            }

2791                           taskTop.deliverNewIntentLocked(callingUid, r.intent);

2792                        } else if(!r.intent.filterEquals(taskTop.task.intent)) {

2793                            // In this case weare launching the root activity

2794                            // of the task, butwith a different intent.  We

2795                           // should start a newinstance on top.

2796                            addingToTask =true;

2797                            sourceRecord =taskTop;

2798                       }

2799                   } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)== 0) {

2800                       // In this case an activity is being launched in to an

2801                       // existing task, without resetting that task.  This

2802                       // is typically the situation of launching an activity

2803                       // from a notification or shortcut. We want to place

2804                       // the new activity on top of the current task.

2805                       addingToTask = true;

2806                       sourceRecord = taskTop;

2807                   } else if (!taskTop.task.rootWasReset) {

2808                       // In this case we are launching in to an existing task

2809                       // that has not yet been started from its front door.

2810                       // The current task has been brought to the front.

2811                       // Ideally, we'd probably like to place this new task

2812                       // at the bottom of its stack, but that's a little hard

2813                        // to do with the currentorganization of the code so

2814                       // for now we'll just drop it.

2815                       taskTop.task.setIntent(r.intent, r.info);

2816                   }

2817                   if (!addingToTask && reuseTask == null) {

2818                       // We didn't do anything...  butit was needed (a.k.a., client

2819                       // don't use that intent!)  Andfor paranoia, make

2820                       // sure we have correctly resumed the top activity.

2821                       if (doResume) {

2822                           resumeTopActivityLocked(null, options);

2823                       } else {

2824                           ActivityOptions.abort(options);

2825                        }

2826                       return ActivityManager.START_TASK_TO_FRONT;

2827                   }

2828                }

2829            }

2830        }

2831

2832        //Stringuri = r.intent.toURI();

2833        //Intentintent2 = new Intent(uri);

2834       //Slog.i(TAG, "Given intent: " + r.intent);

2835       //Slog.i(TAG, "URI is: " + uri);

2836       //Slog.i(TAG, "To intent: " + intent2);

2837

2838        if(r.packageName != null) {

2839            // Ifthe activity being launched is the same as the one currently

2840            // atthe top, then we need to check if it should only be launched

2841            //once.

2842           ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);

2843            if(top != null && r.resultTo == null) {

2844               if (top.realActivity.equals(r.realActivity) && top.userId ==r.userId) {//需要启动的Activity与现在的topactivity不同,因此不需要执行resume top activtity,进一步分析:resume top activity还必须满足其他条件:launchMode中还必须设置了FLAG_ACTIVITY_SINGLE_TOP或者.LAUNCH_SINGLE_TOP或者LAUNCH_SINGLE_TASK

2845                   if (top.app != null && top.app.thread != null) {

2846                       if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0

2847                            || r.launchMode ==ActivityInfo.LAUNCH_SINGLE_TOP

2848                            || r.launchMode ==ActivityInfo.LAUNCH_SINGLE_TASK) {

2849                           logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);

2850                            // For paranoia, makesure we have correctly

2851                            // resumed the topactivity.

2852                            if (doResume) {

2853                               resumeTopActivityLocked(null);

2854                            }

2855                            ActivityOptions.abort(options);

2856                            if((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {

2857                                // We don'tneed to start a new activity, and

2858                               // the client said not todo anything if that

2859                                // is the case,so this is it!

2860                                returnActivityManager.START_RETURN_INTENT_TO_CALLER;

2861                            }

2862                            top.deliverNewIntentLocked(callingUid,r.intent);

2863                            returnActivityManager.START_DELIVERED_TO_TOP;

2864                       }

2865                   }

2866                }

2867            }

2868

2869        } else {

2870            if(r.resultTo != null) {

2871               sendActivityResultLocked(-1,

2872                       r.resultTo, r.resultWho, r.requestCode,

2873                   Activity.RESULT_CANCELED, null);

2874            }

2875            ActivityOptions.abort(options);

2876           return ActivityManager.START_CLASS_NOT_FOUND;

2877        }

2878

2879        booleannewTask = false;

2880        booleankeepCurTransition = false;

2881

2882        // Shouldthis be considered a new task?

2883        if(r.resultTo == null && !addingToTask

2884               && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {

2885            if(reuseTask == null) {

2886               // todo: should do better management of integers.

2887                mService.mCurTask++;

2888               if (mService.mCurTask <= 0) {

2889                   mService.mCurTask = 1;

2890                }

//在这里给activity创建了一个新task,保存在r.task

2891               r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null,true);

2892               if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r

2893                       + " in new task " + r.task);

2894            }else {

2895               r.setTask(reuseTask, reuseTask, true);

2896            }

2897           newTask = true;

2898            if(!movedHome) {//这段代码被执行,但是launchFlags中并没有设置FLAG_ACTIVITY_TASK_ON_HOME

2899               moveHomeToFrontFromLaunchLocked(launchFlags);

2900            }

2901

2902        } else if(sourceRecord != null) {

2903            if(!addingToTask &&

2904                   (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {

2905               // In this case, we are adding the activity to an existing

2906               // task, but the caller has asked to clear that task if the

2907               // activity is already running.

2908               ActivityRecord top = performClearTaskLocked(

2909                       sourceRecord.task.taskId, r, launchFlags);

2910               keepCurTransition = true;

2911               if (top != null) {

2912                   logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);

2913                   top.deliverNewIntentLocked(callingUid, r.intent);

2914                   // For paranoia, make sure we have correctly

2915                   // resumed the top activity.

2916                    if (doResume) {

2917                       resumeTopActivityLocked(null);

2918                   }

2919                   ActivityOptions.abort(options);

2920                   return ActivityManager.START_DELIVERED_TO_TOP;

2921                }

2922            }else if (!addingToTask &&

2923                   (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {

2924               // In this case, we are launching an activity in our own task

2925               // that may already be running somewhere in the history, and

2926               // we want to shuffle it to the front of the stack if so.

2927               int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);

2928               if (where >= 0) {

2929                   ActivityRecord top = moveActivityToFrontLocked(where);

2930                   logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);

2931                   top.updateOptionsLocked(options);

2932                   top.deliverNewIntentLocked(callingUid, r.intent);

2933                   if (doResume) {

2934                       resumeTopActivityLocked(null);

2935                   }

2936                   return ActivityManager.START_DELIVERED_TO_TOP;

2937                }

2938            }

2939            // Anexisting activity is starting this new activity, so we want

2940            // tokeep the new one in the same task as the one that is starting

2941            //it.

2942           r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);

2943            if(DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r

2944                   + " in existing task " + r.task);

2945

2946        } else {

2947            //This not being started from an existing activity, and not part

2948            // ofa new task...  just put it in the toptask, though these days

2949            //this case should never happen.

2950            finalint N = mHistory.size();

2951           ActivityRecord prev =

2952                N> 0 ? mHistory.get(N-1) : null;

2953           r.setTask(prev != null

2954                   ? prev.task

2955                   : new TaskRecord(mService.mCurTask, r.info, intent), null, true);

2956            if(DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r

2957                   + " in new guessed " + r.task);

2958        }

2959

2960       mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,

2961               intent, r.getUriPermissionsLocked());

2962

2963        if(newTask) {

2964           EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId);

2965        }

2966       logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);

2967        startActivityLocked(r, newTask,doResume, keepCurTransition, options);

2968        returnActivityManager.START_SUCCESS;

2969    }

 

Step 11: ActivityStack.startActivityLocked

传入参数:

newTask=true

doResume=true

keepCurTransition = false;

此时要启动的activity已经被插入到了mHistory中,调用resumeTopActivityLocked()启动该activity.

    private final voidstartActivityLocked(ActivityRecord r, boolean newTask,

            booleandoResume, boolean keepCurTransition, Bundle options) {

        final int NH= mHistory.size();

 

        int addPos =-1;

       

        if (!newTask){

            // Ifstarting in an existing task, find where that is...

            booleanstartIt = true;

            for (inti = NH-1; i >= 0; i--) {

               ActivityRecord p = mHistory.get(i);

                if(p.finishing) {

                   continue;

                }

                if(p.task == r.task) {

                   // Here it is!  Now, if this isnot yet visible to the

                   // user, then just add it without starting; it will

                   // get started when the user navigates back to it.

                   addPos = i+1;

                   if (!startIt) {

                       if (DEBUG_ADD_REMOVE) {

                           RuntimeException here = new RuntimeException("here");

                           here.fillInStackTrace();

                           Slog.i(TAG, "Adding activity " + r + " to stack at "+ addPos,

                                    here);

                       }

                       mHistory.add(addPos, r);

                       r.putInHistory();

                       mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,

                               r.info.screenOrientation, r.fullscreen);

                       if (VALIDATE_TOKENS) {

                           validateAppTokensLocked();

                       }

                       ActivityOptions.abort(options);

                       return;

                    }

                   break;

                }

                if(p.fullscreen) {

                   startIt = false;

                }

            }

        }

 

        // Place anew activity at top of stack, so it is next to interact

        // with theuser.

        if (addPos< 0) {

            addPos =NH;

        }

       

        // If we arenot placing the new activity frontmost, we do not want

        // to deliverthe onUserLeaving callback to the actual frontmost

        // activity

        if (addPos< NH) {

           mUserLeaving = false;

            if(DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front,mUserLeaving=false");

        }

       

        // Slot theactivity into the history stack and proceed

        if(DEBUG_ADD_REMOVE) {

           RuntimeException here = new RuntimeException("here");

           here.fillInStackTrace();

           Slog.i(TAG, "Adding activity " + r + " to stack at "+ addPos, here);

        }

       mHistory.add(addPos, r);

       r.putInHistory();

        r.frontOfTask= newTask;

        if (NH >0) {

            // Wewant to show the starting preview window if we are

            //switching to a new task, or the next activity's process is

            // notcurrently running.

            booleanshowStartingIcon = newTask;

           ProcessRecord proc = r.app;

            if (proc== null) {

                proc= mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);

            }

            if (proc== null || proc.thread == null) {

                if(!newTask && mResumedActivity == null) {

                   // This is a special case when stressing the framework

                   // by starting many activities fast in the same task.

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值