Android应用App启动流程

说来惭愧,开发了2-3年的Android,竟还不知道App的启动流程。趁着学习的Binder机制知识,顺便理清当我们点击桌面应用的图标来启动App的过程。

概述

App启动概述
当Launcher启动一个App,Launcher会通过IPC通知ActivityManagerService启动App,此时ActivityManagerService会先检测App启动了没。如果目标App没有启动,则通过socket方式通知Zygote孵化(fork)一个新的进程。Zygote创建完App进程后,在App进程调用ActivityThread的main方法进行初始化,把自己的代理对象绑定到ActivityManagerService,然后通过IPC告诉ActivityManagerService(App已经启动起来了)。ActivityManagerService就可以通过App进程的代理对象,对App进程进行一些“控制”(IPC通信),如让App进程创建其入口Activity,并执行生命周期方法onCreate,onStart等。

相关类

ActivityManagerService: AMS是Android中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要,它本身也是一个Binder的实现类。
ActivityThread: 应用的入口类,系统通过调用main函数,开启消息循环队列。ActivityThread所在线程被称为应用的主线程(UI线程)。
ApplicationThread: ApplicationThread提供Binder通讯接口,AMS则通过代理调用此App进程的本地方法。
ActivityManagerProxy: AMS服务在当前进程的代理类,负责与AMS通信。
ApplicationThreadProxy: ApplicationThread在AMS服务中的代理类,负责与ApplicationThread通信。

流程代码分析

先从Launcher启动目标App的入口Activity看起,代码:

intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className); 
startActivity(intent, optsBundle);

startActivity会调用Activity的startActivityForResult的方法:

//Activity类
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
 if (mParent == null) {
    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());
   } 
//...   
}else{
//...
}    

接着会调用Instrumentation类的execStartActivity方法,代码如下:

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

代码中,ActivityManagerNative.getDefault() 返回的就是 ActivityManagerProxy对象,这里就开始IPC,调用ActivityManagerService的startActivity方法了。

ActivityManagerProxy对象调用ActivityManagerService对象(运行在system_server进程)的startActivity方法以启动应用,startActivity方法接下来调用startActivityAsUser方法以启动应用。在startActivityAsUser方法里会调用ActivityStack的startActivityMayWait方法以启动应用,startActivityMayWait方法里启动应用时,需先根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,则会弹出ResolverActivity让用户选择合适的应用。

//ActivityStack类
final int startActivityMayWait(IApplicationThread caller, int callingUid,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId) {
    //…
    //根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
    //则会弹出ResolverActivity让用户选择合适的应用。
      ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                    profileFile, profileFd, userId);
    //…
    int res = startActivityLocked(caller, intent, resolvedType,
                        aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                        startFlags, options, componentSpecified, null);
    //…

在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUncheckedLocked方法启动Activity。接下来调用startActivityLocked将ActivityRecord加入到回退栈里:

//ActivityStack类
final int startActivityUncheckedLocked(ActivityRecord r,
          ActivityRecord sourceRecord, int startFlags, boolean doResume,
          Bundle options) {
    //...          
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    //...
}

在startActivityLocked里调用resumeTopActivityLocked显示栈顶Activity:

//ActivityStack类
private final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
    //...        
    if (doResume) {
        resumeTopActivityLocked(null);
    }  
}

resumeTopActivityLocked(null)会调用另一个resumeTopActivityLocked方法显示栈顶的acitivity:

//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    return resumeTopActivityLocked(prev, null);
}

因为应用还未启动过,所以调用startSpecificActivityLocked启动应用,执行逻辑如下:

//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    //...
    if (next.app != null && next.app.thread != null) {
        //…
    }else{
        //…
        startSpecificActivityLocked(next, true, true);
    }
    //...

在startSpecificActivityLocked里调用mService.startProcessLocked启动应用:

//ActivityStack类
private final void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
   ProcessRecord app = mService.getProcessRecordLocked(r.processName,
              r.info.applicationInfo.uid);
   //...
   mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
        "activity", r.intent.getComponent(), false, false);
}       

在ActivityManagerService的startProcessLocked方法里:

//ActivityManagerService类
final ProcessRecord startProcessLocked(String processName,
          ApplicationInfo info, boolean knownToBeDead, int intentFlags,
          String hostingType, ComponentName hostingName, boolean allowWhileBooting,
          boolean isolated) {
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(processName, info.uid);
    } else {
        //...
    }
    //...
    if (app == null) {
       app = newProcessRecordLocked(null, info, processName, isolated);
       if (app == null) {
           Slog.w(TAG, "Failed making new process record for "
                   + processName + "/" + info.uid + " isolated=" + isolated);
           return null;
       }
       mProcessNames.put(processName, app.uid, app);
       if (isolated) {
           mIsolatedProcesses.put(app.uid, app);
       }
     } else {
      //..
    }
    //...
    startProcessLocked(app, hostingType, hostingNameStr);
    //...
}

在startProcessLocked方法里:

//ActivityManagerService类
private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
    //...
    try {
        //...
        // Start the process.  It will either succeed and return a result containing
        // the PID of the new process, or else throw a RuntimeException.
        //Zygote孵化dalvik应用进程后,会执行android.app.ActivityThread类的main方法
        Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, null);
        //...    
    } catch (RuntimeException e) {
        //...
    }
}

在Process类的start方法里:

//Process类
public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String[] zygoteArgs) {
    try{                              
    startViaZygote(processClass, niceName, uid, gid, gids,
                   debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
    }catch (ZygoteStartFailedEx ex) {
      //...
    }                    
}         

在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。
至于Zygote怎么孵化新进程的代码比较底层,不做分析。我们接着分析,App进程创建后,初始化的过程。

(以下是重点)
Zygote孵化App进程后,App进程会导入ActivityThread类,并执行main方法:

//ActivityThread类
public static void main(String[] args) {
    //... 
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    AsyncTask.init();
    //...
    Looper.loop();
    //...
}

在main方法中,初始化了Looper,创建了Looper及其消息队列,然后调用attach方法将自己绑定到ActivityManagerService中,调用Looper.loop方法,不断地从MessageQueue中读取消息,此时主线程的消息机制已经形成。所有操作都要通过消息驱动的形式进行,也就是通过Handler分发消息,然后目标Handler处理消息。我们再来看看App进程怎么attach到ActivityManagerService中。
在ActivityThread的main方法里调用thread.attach,代码:

//ActivityThread类
private void attach(boolean system) {
    sThreadLocal.set(this);
    mSystemThread = system;
    if (!system) {
        //...
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //调用ActivityManagerService的attachApplication方法
            //将ApplicationThread对象绑定至ActivityManagerService,
            //这样ActivityManagerService就可以
            //通过ApplicationThread代理对象控制应用进程
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        //...
    }
    //... 
}

ActivityManagerService的attachApplication方法执行attachApplicationLocked(thread, callingPid)进行绑定。

//ActivityManagerService类
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) { 
    ProcessRecord app;
    //...     
    app.thread = thread; 
    //...  
    try {
        //...
        thread.bindApplication(processName, appInfo, providers,
                app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                app.instrumentationArguments, app.instrumentationWatcher, testMode,
                enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                mCoreSettingsObserver.getCoreSettingsLocked());
        //... 
    } catch (Exception e) {
        //...
    }
    //... 
    ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
    if (hr != null && normalMode) {
        if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                && processName.equals(hr.processName)) {
            try {
                if (mHeadless) {
                    Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
                } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                //mMainStack.realStartActivityLocked真正启动activity
                    didSomething = true;
                }
            } catch (Exception e) {
                //...
            }
        } else {
            //...
        }
    }
    //... 
    return true;
}

这段代码有两个重要的方法:thread.bindApplication和mMainStack.topRunningActivityLocked。
thread.bindApplication方法的作用是将ApplicationThread的代理对象绑定到ActivityManagerService中,也就是让ActivityManagerService获取ApplicationThread的代理对象,使ActivityManagerService能和App进程通信。
mMainStack.topRunningActivityLocked通知应用启动Activity。
thread.bindApplication代码:

//ApplicationThreadpublic final void bindApplication(String processName,
        ApplicationInfo appInfo, List<ProviderInfo> providers,
        ComponentName instrumentationName, String profileFile,
        ParcelFileDescriptor profileFd, boolean autoStopProfiler,
        Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
        int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
        boolean persistent, Configuration config, CompatibilityInfo compatInfo,
        Map<String, IBinder> services, Bundle coreSettings) {
    //...  
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.debugMode = debugMode;
    data.enableOpenGlTrace = enableOpenGlTrace;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfileFile = profileFile;
    data.initProfileFd = profileFd;
    data.initAutoStopProfiler = false;
    queueOrSendMessage(H.BIND_APPLICATION, data);
}

利用queueOrSendMessage可以发送消息到ActivityThread消息队列中,作用是BIND_APPLICATION。ActivityThread的消息队列收到消息后,Handler就会处理消息(BIND_APPLICATION):

//ActivityThread类
private void handleBindApplication(AppBindData data) {
  //...  
  ApplicationInfo instrApp = new ApplicationInfo();
  instrApp.packageName = ii.packageName;
  instrApp.sourceDir = ii.sourceDir;
  instrApp.publicSourceDir = ii.publicSourceDir;
  instrApp.dataDir = ii.dataDir;
  instrApp.nativeLibraryDir = ii.nativeLibraryDir;
  LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
        appContext.getClassLoader(), false, true);
  ContextImpl instrContext = new ContextImpl();
  instrContext.init(pi, null, this);
  //... 
  if (data.instrumentationName != null) {
       //...
  } else {
       //注意Activity的所有生命周期方法都会被Instrumentation对象所监控,
       //也就说执行Activity的生命周期方法前后一定会调用Instrumentation对象的相关方法
       //并不是说只有跑单测用例才会建立Instrumentation对象,
       //即使不跑单测也会建立Instrumentation对象
       mInstrumentation = new Instrumentation();
  }
  //... 
  try {
     //...
     Application app = data.info.makeApplication(data.restrictedBackupMode, null);
     mInitialApplication = app;
     //...         
     try {
          mInstrumentation.onCreate(data.instrumentationArgs);
      }catch (Exception e) {
             //...
      }
      try {
           //这里会调用Application的onCreate方法
           //故此Applcation对象的onCreate方法会比ActivityThread的main方法后调用
           //但是会比这个应用的所有activity先调用
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
           //...
        }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

mMainStack.realStartActivityLocked会调用scheduleLaunchActivity启动activity,代码:

//ActivityStack类
final boolean realStartActivityLocked(ActivityRecord r,
        ProcessRecord app, boolean andResume, boolean checkConfig)
        throws RemoteException {

    //...  
    try {
        //...
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info,
                new Configuration(mService.mConfiguration),
                r.compat, r.icicle, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profileFile, profileFd,
                profileAutoStop);

        //...
    } catch (RemoteException e) {
        //...
    }
    //...    
    return true;
}

同样app.thread也只是ApplicationThread对象在ActivityManagerService的一个代理对象而已,最终会调用ApplicationThread的scheduleLaunchActivity方法。

//ApplicationThread类
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
        Bundle state, List<ResultInfo> pendingResults,
        List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
        String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    ActivityClientRecord r = new ActivityClientRecord();
    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;
    r.startsNotResumed = notResumed;
    r.isForward = isForward;
    r.profileFile = profileName;
    r.profileFd = profileFd;
    r.autoStopProfiler = autoStopProfiler;
    updatePendingConfiguration(curConfig);
    queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}

这里调用了queueOrSendMessage往ActivityThread的消息队列发送了消息,消息的用途是启动Activity,接下来ActivityThread的handler便会处理该消息。看看ActivityThread处理启动Activity的消息代码:

//ActivityThread类
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //... 
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        //...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);
        //...
    } else {
        //...
    }
}

这段代码又有2个重要的方法:performLaunchActivity和handleResumeActivity。
performLaunchActivity会调用Activity的onCreate,onStart,onResotreInstanceState方法。
handleResumeActivity会调用Activity的onResume方法。
performLaunchActivity代码:

//ActivityThread类
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        //...
    } catch (Exception e) {
        //...
    }
    try {
        //r.packageInfo.makeApplication实际并未创建Application对象,
        //因为bindApplication过程已经创建了Application对象,
        //makeApplication方法会返回已创建的Application对象
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        //...         
        if (activity != null) {
            //...
            //将application对象,appContext对象绑定到新建的activity对象
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config);
            //... 
            //会调用Activity的onCreate方法             
            mInstrumentation.callActivityOnCreate(activity, r.state);
            //...
            //...
            //调用Activity的onStart方法
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }              
            if (!r.activity.mFinished) {
                if (r.state != null) {
                    //会调用Activity的onRestoreInstanceState方法
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                mInstrumentation.callActivityOnPostCreate(activity, r.state);
                //...
            }
        }
        //...
    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        //...
    }
    return activity;
}

handleResumeActivity代码:

//ActivityThread类
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
        boolean reallyResume) {
    //...
    //performResumeActivity最终会调用Activity的onResume方法 
    ActivityClientRecord r = performResumeActivity(token, clearHide);
    if (r != null) {
        final Activity a = r.activity;
        //... 
        //显示界面
        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);
            }
           //...         
        } else if (!willBeVisible) {
             //...
        }
        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
            }
        }

    } else {
         //...
    }
}
public final ActivityClientRecord performResumeActivity(IBinder token,
        boolean clearHide) {
    ActivityClientRecord r = mActivities.get(token);
    //...
    if (r != null && !r.activity.mFinished) {
         //...
        try {
            //... 
            //会调用Activity的onResume方法 
            r.activity.performResume();
            //...
        } catch (Exception e) {
            //...
        }
    }
    return r;
}

App启动流程代码到这里也就结束了,看到这里,相信你对App启动流程也有一个大概的认识了。
其实我还看到一个资料,是关于App启动的 Luancher进程 - System进程 - App进程 流程的关系,直接上图:
Luancher进程 - System进程 - App进程

在查阅资料过程中,还知道些关于Zygote进程,这里也copy过来。
Zygote 的中文意思是受精卵,从这个意思里也可以看出 Zygote 进程是用来分裂复制(fork)的,实际上所有的 App 进程都是通过对 Zygote 进程的 Fork 得来的。当 app_process 启动 Zygote 时,Zygote 会在其启动后,预加载必要的 Java Classes(相关列表查看 预加载文件) 和 Resources,并启动 System Server ,并打开 /dev/socket/zygote socket 去监听启动应用程序的请求,日后。在下面的代码中,显示了 Zygote 进程如何启动,和加载 System Server 的。
Zygote进程

参考资料

深入理解Activity启动流程(一)–Activity启动的概要流程
深入理解Activity启动流程(三)–Activity启动的详细流程1
深入理解Activity启动流程(三)–Activity启动的详细流程2
分析Android中应用的启动流程
Android 应用进程启动流程

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值