[Android]从Launcher开始启动App流程源码分析

简介: 以下内容为原创,欢迎转载,转载请注明来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5017056.html从Launcher开始启动App流程源码分析com.


以下内容为原创,欢迎转载,转载请注明
来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5017056.html

从Launcher开始启动App流程源码分析

com.android.launcher.Launcher就是我们的Launcher页面了,可以看到Launcher其实也是一个Activity

public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener {
    // ...
}

既然是Activity,那当然也会有onCreateonResume等生命周期了,按照逻辑,应该会去加载所有App,以网格的布局显示在页面上,果然,在onResume看到了这个方法:

@Override
protected void onResume() {
    super.onResume();
    if (mRestoring) {
        startLoaders();
    }
    // ...
}

看方法名就可以猜到这个方法就是用来加载所有App信息的,进入这个方法:

private void startLoaders() {
    boolean loadApplications = sModel.loadApplications(true, this, mLocaleChanged);
    sModel.loadUserItems(!mLocaleChanged, this, mLocaleChanged, loadApplications);
    mRestoring = false;
}

这里调用sModelLauncherModel类型)的loadUserItems方法去加载数据了,sModel明显属于Model层,进入loadUserItems方法:

void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged,
            boolean loadApplications) {
    // ...
        mDesktopItemsLoaded = false;
        mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications,
                isLaunching);
        mDesktopLoaderThread = new Thread(mDesktopItemsLoader, "Desktop Items Loader");
        mDesktopLoaderThread.start();
    // ...
}

然后使用DesktopItemsLoadermDesktopLoaderThread线程中加载,:

private class DesktopItemsLoader implements Runnable {
    // ...
    public void run() {
        // ...
        final Cursor c = contentResolver.query(LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
        // ...
        final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
        final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
        final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
        final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
        final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
        final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
        final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
        final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
        final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
        final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);
        final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
        final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
        final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
        final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
        final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
        final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
        final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
        // ...
        // 通过launcher回调返回数据
        launcher.onDesktopItemsLoaded(uiDesktopItems, uiDesktopWidgets);
        // ...
    }
    // ...
}

然后我们回到LauncheronDesktopItemsLoaded方法:

void onDesktopItemsLoaded(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) {
    // ...
    bindDesktopItems(shortcuts, appWidgets);
}

继续进入bindDesktopItems方法:

private void bindDesktopItems(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) {
    // ...
    mBinder = new DesktopBinder(this, shortcuts, appWidgets, drawerAdapter);
    mBinder.startBindingItems();
}

进入startBindingItems方法:

public void startBindingItems() {
    // ...
    obtainMessage(MESSAGE_BIND_ITEMS, 0, mShortcuts.size()).sendToTarget();
}

这里使用了Handler发送消息,进入HandlerhandleMessage方法:

@Override
public void handleMessage(Message msg) {
    // ...
    switch (msg.what) {
        // ...
        case MESSAGE_BIND_ITEMS: {
            launcher.bindItems(this, mShortcuts, msg.arg1, msg.arg2);
            break;
        }
        // ...
    }
}

接收到消息之后调用bindItems方法:

private void bindItems(Launcher.DesktopBinder binder, ArrayList<ItemInfo> shortcuts, int start, int count) {
    // ...
    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
        final View shortcut = createShortcut((ApplicationInfo) item);
        workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1, !desktopLocked);
    // ...
}

这里我们只考虑app或者app快捷方式的情况,文件夹和widgets暂时不考虑。app或者app快捷方式实质上都是进入了这个逻辑中,调用createShortcut方法:

// 重载方法,最终都会调用这个方法
View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
    // ...
    TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
    // ...
    favorite.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
    favorite.setText(info.title);
    favorite.setTag(info);
    favorite.setOnClickListener(this);
    // ...
}

这里首先inflater出item的布局,然后设置textOnClickListener,还有tag,这个tag是ApplicationInfo,里面包含了各种App信息,是从App的AndroidManifest.xml<application>标签中解析出来的。既然设置了点击事件,显然,点击后应该会打开对应的App才对。所以继续看onClick方法:

public void onClick(View v) {
    Object tag = v.getTag();
    if (tag instanceof ApplicationInfo) {
        // Open shortcut
        final Intent intent = ((ApplicationInfo) tag).intent;
        startActivitySafely(intent);
    } else if (tag instanceof FolderInfo) {
        handleFolderClick((FolderInfo) tag);
    }
}

点击App就会通过startActivitySafely方法使用刚才设置的tag,也就是ApplicationInfo中的intent进行跳转:

void startActivitySafely(Intent intent) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    // ...
    startActivity(intent);
    // ...
}



然后我们来看看打开某个app的时候整个流程是怎么走的。接着上面的的startActivity()方法走:

public void startActivity(Intent intent, @Nullable Bundle options) {
    // ...
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
    // ...
}

可以看到,不管你是调用了startActivity还是startActivityForResult方法,startActivityForResult方法,并且如果是调用的startActivity,则默认requestCode就是-1,所以如果你想调用startActivityForResult的时候,注意不能把requestCode设置为-1,否则它的效果就跟startActivity一样了,不会再回调onActivityResult!,再看看startActivityForResult的实现:

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

可以看到,Activity内部是使用mInstrumentationInstrumentation类型)执行execStartActivity方法来实现Activity跳转的,执行完毕后会返回一个Instrumentation.ActivityResult

然后查看Instrumentation::execStartActivity

public ActivityResult execStartActivity(
    // ...
    int result = ActivityManagerNative.getDefault()
        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);
    // ...
}

首先通过ActivityManagerNative.getDefault()获得一个IActivityManager的实现类:

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

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        // 通过Binder IPC获取ActivityManager(IBinder)
        IBinder b = ServiceManager.getService("activity");
        // ...
        IActivityManager am = asInterface(b);
        // ...
        return am;
    }
};

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

先通过Binder IPC的方式从服务端获取一个Activity Manager,然后通过ActivityManagernative封装成一个代理ActivityManagerProxy对象,然后调用startActivity也是使用了Binder IPC进行与服务器端的通信,(整个Android系统的通信机制使用了大量的Binder IPC,这个以后再专门讨论这个吧),接着,我们进入到了com.android.server.am.ActivityManagerServicestartActivity方法:

@Override
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options, UserHandle.getCallingUserId());
}

接下来的调用链:

-> startActivityAsUser
-> startActivityMayWait
-> startActivityLocked
-> startActivityUncheckedLocked
-> targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)
-> mStackSupervisor.resumeTopActivitiesLocked(this, r, options)
-> resumeTopActivityInnerLocked(prev, options);
-> mStackSupervisor.startSpecificActivityLocked(next, true, true)

startSpecificActivityLocked方法如下:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    // ...
    if (app != null && app.thread != null) {
        // ...
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
    }
    // ...
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);
}

首先从mService找出对应需要启动Activity的进程(通过进程名字和uid,进程名字可以在AndroidManifest.xml中配置)如果可以获取到,说明这个Activity所属的进程已经存在了,也就是说app已经在运行了,那就会调用realStartActivityLocked,否则,如果该Activity所在的App是第一次启动,则会调用mService.startProcessLocked方法:

final ProcessRecord startProcessLocked(/*...*/){
    // ...
    startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    // ...
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    // ...
    app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
    // ...
    if (app == null) {
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
    }
    // ...
}

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    // ...
    // entryPoint表示一个类,它用来作为新创建的进程的主入口,会调用这个类的静态main方法,这个参数在startProcessLocked方法中会被检查重置,如果是null的话,就默认是android.app.ActivityThread。
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    // ...
    Process.ProcessStartResult startResult = Process.start(entryPoint,
            app.processName, uid, uid, gids, debugFlags, mountExternal,
            app.info.targetSdkVersion, app.info.seinfo, requiredAbi, 
            instructionSet, app.info.dataDir, entryPointArgs);
    // ...  
}

这3个重载方法做的事情就是,先根据进程名字调用getProcessRecordLocked()获取ProcessRecord,如果ProcessRecord不存在,则调用newProcessRecordLocked()方法建立一个ProcessRecord,并且新的ProcessRecord绑定了ApplicationInfouid等信息,但后进入第三个重载方法,执行新建、启动进程。

再看Process::start的实现:

public static final ProcessStartResult start(/*...*/){
    // ...
    return startViaZygote(processClass, niceName, uid, gid, gids,
              debugFlags, mountExternal, targetSdkVersion, seInfo,
              abi, instructionSet, appDataDir, zygoteArgs);
    // ...
}

接下来就是通过Zygote进程fork一个新的进程作为app的进程。这里要需要讲的一个参数是processClass,这个参数表示一个类,它用来作为新创建的进程的主入口,会调用这个类的静态main方法,这个参数在startProcessLocked方法中会被检查重置,如果是null的话,就默认是android.app.ActivityThread

现在App的进程也创建成功了,就会进入android.app.ActivityThread的静态的main中:

public static void main(String[] args) {
    // ...
    // 初始化主线程Looper
    Looper.prepareMainLooper();
    // ...
    ActivityThread thread = new ActivityThread();
    thread.attach(false);   
    // ...
    // 启动消息循环
    Looper.loop()
    // ...
}

然后创建了一个ActivityThread,说明每当一个新的app进程被创建,都会对应一个新的ActivityThread实例,然后调用它的attach方法:

private void attach(boolean system) {
    // ...
    if (!system) {
        // ...
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        // ...
        mgr.attachApplication(mAppThread);
        // ...
    }else{
        // ...
    }
    // ...
}

然后再次通过Binder IPC调用ActivityManagerProxyattachApplication,传入的ApplicationThread(Binder)参数用于在服务端进行回调通信。最后进入ActivityManagerService::attachApplication,再调用attachApplicationLocked(thread, callingPid)

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    // ...
    app = mPidsSelfLocked.get(pid);
    // ...
    app.makeActive(thread, mProcessStats);
    app.curAdj = app.setAdj= -100;
    app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
    app.forcingToForeground = null;
    updateProcessForegroundLocked(app, false, false);
    app.hasShownUi = false;
    app.debugging = false;
    app.cached = false;
    app.killedByAm = false;
    // ...
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked());
    // ...
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    // ...
}

首先,通过pid获取刚刚创建的进程,然后对app进行一些初始化工作,然后调用bindApplication远程调用客户端ActivityThread::bindApplication,再通过Handler调用到ActivityThread::handleBindApplication方法:

private void handleBindApplication(AppBindData data) {
    // ...
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    if (data.instrumentationName != null) {
        // ...
        mInstrumentationPackageName = ii.packageName;
        mInstrumentationAppDir = ii.sourceDir;
        mInstrumentationSplitAppDirs = ii.splitSourceDirs;
        mInstrumentationLibDir = ii.nativeLibraryDir;
        mInstrumentedAppDir = data.info.getAppDir();
        mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
        mInstrumentedLibDir = data.info.getLibDir();

        ApplicationInfo instrApp = new ApplicationInfo();
        instrApp.packageName = ii.packageName;
        instrApp.sourceDir = ii.sourceDir;
        instrApp.publicSourceDir = ii.publicSourceDir;
        instrApp.splitSourceDirs = ii.splitSourceDirs;
        instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
        instrApp.dataDir = ii.dataDir;
        instrApp.nativeLibraryDir = ii.nativeLibraryDir;
        LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                appContext.getClassLoader(), false, true, false);
        ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
        // ...
java.lang.ClassLoader cl = instrContext.getClassLoader();
        mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        mInstrumentation.init(this, instrContext, appContext, new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
        // ...
    }else{
        mInstrumentation = new Instrumentation();
    }
    // ...
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;
    // ...
    mInstrumentation.callApplicationOnCreate(app);
    // ...
}

首先,创建一个当前App的Context,然后如果data.instrumentationName != null,则初始化Instrumentation相关的变量,并创建InstrumentationApplicationInfo等对象来创建InstrumentationContext,然后创建Instrumentation对象,并调用它的init方法进行初始化。如果data.instrumentationName == null,则new一个Instrumentation(在一个进程中只会有一个Instrumentation实例)然后创建Application对象,并调用它的onCreate方法,这样Application就会被回调了。

然后我们回到ActivityManagerService::attachApplicationLocked方法,远程执行完thread.bindApplication方法之后,接下来会调用mStackSupervisor.attachApplicationLocked(app)方法:

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    // ...
    ActivityRecord hr = stack.topRunningActivityLocked(null);
    // ...
    realStartActivityLocked(hr, app, true, true)
    // ...
}

先通过topRunningActivityLocked从堆栈顶端获取要启动的Activity,然后realStartActivityLocked(hr, app, true, true)

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
    // ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
    // ...
}

继续通过Binder IPC远程调用scheduleLaunchActivity方法,然后进入ActivityThreadscheduleLaunchActivity方法中,然后通过Handler进入handleLaunchActivity方法:

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

先调用performLaunchActivity方法返回一个Activity,然后调用handleResumeActivity方法让该Activity进入onResume状态。所以很显然在performLaunchActivity中肯定是生成了Activity实例,并调用了onCreate方法了,来看下代码:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // ...
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    // ...
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
    // ...
    Context appContext = createBaseContextForActivity(r, activity);
    // ...
    activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor);
    // ...
    if (r.isPersistable()) {
     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    // ...
    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState);
    // ...
    mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
    // ...
}

首先,初始化LoadedApk,然后通过Instrumentation来创建一个Activity实例,通过createBaseContextForActivity方法创建一个Activity Context,调用activityattach方法,然后依次触发该ActivityonCreateonRestoreInstanceStateonPostCreate等生命周期方法。

createBaseContextForActivity方法如下:

private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
    // ...
    ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, displayId, r.overrideConfig);
    appContext.setOuterContext(activity);
    Context baseContext = appContext;
    // ...
}

通过ContextImpl::createActivityContext创建的Context对象,可以发现,不论是System Context/App Context/Activity Context,这些Context都是通过ContextImpl生成的,具体这里再挖个坑先。

再继续进入Activity::attach方法:

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    // ...
    mMainThread = aThread;
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    mParent = parent;
    mEmbeddedID = id;
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    // ...
}

上面对ActivityActivityThreadInstrumentation等进行了绑定,所以说每个Activity都含有一个ActivityThread引用和一个Instrumentation引用,而ActivityThread实例和Instrumentation实例在一个进程中都只有一个实例,因为ActivityThread是在进程被创建成功后,进入ActivityThreadstatic main()时才会被创建,而Instrumentation则是在ActivityThread被创建后进行attach的之后被创建。


启动应用流程所有方法链调用总结:

  • Activity::startActivity

  • Activity::startActivityForResult

  • Instrumentation::execStartActivity
    携带参数:
  1. who:from的Context
  2. contextThread:from的ActivityThreadApplicationThreadApplicationThread中可以通过Binder IPC提供给服务端回调Activity生命周期等操作(from的主线程)。
  3. mTokenBinder类型,用来标识from的Activity,可能为null。
  4. target:from的Activity(所以是用来接收跳转结果的),如果不是从Activity跳转则为null。
  5. intent:跳转Intent。
  6. requestCode:如果是startActivity,则为-1。
  7. options:额外Bundle数据。
  • ActivityManagerProxy::startActivity()
    携带参数:
  1. caller:上面的contextThread,from主线程。
  2. callingPackage:from的Context包名。
  3. intent:跳转Intent。
  4. resolvedType:跳转Intent的MIME类型。
  5. resultTo:上面的tokenBinder类型,用来标识from的Activity。
  6. resultWho:from的Activity的mEmbeddedID(唯一标示字符串)
  7. requestCode:如果是startActivity,则为-1。
  8. startFlags:默认传入为0。
  9. profilerInfo:默认传入为null。
  10. options:额外Bundle数据。
  • ActivityManagerService::startActivity()(通过Binder IPC调用):
    携带参数跟上面一样。

  • ActivityManagerService::startActivityAsUser
    携带参数包括ActivityManagerService::startActivity()所有的参数,最再加一个:
  1. userId:userId,根据给当前进程分配的Linux UID(这个UID可以用来让上层系统服务进行身份识别和权限检查)得到一个userId(如果不是多用户,则直接返回0)。
  • ActivityStackSupervisor::startActivityMayWait()
    参数:
  1. caller:上面的caller/contextThread,from主线程。
  2. callingUid:调用用户uid。
  3. callingPackage:from的Context包名。
  4. intent:跳转Intent。
  5. resolvedType:跳转Intent的MIME类型。
  6. voiceSession:传null。
  7. voiceInteractor:传null。
  8. resultTo:上面的resultTo/tokenBinder类型,用来标识from的Activity。
  9. resultWho:from的Activity的mEmbeddedID(唯一标示字符串)
  10. requestCode:如果是startActivity,则为-1。
  11. startFlags:传null。
  12. profilerInfo:传null。
  13. outResult:传null。
  14. config:传null。
  15. options:额外数据。
  16. ignoreTargetSecurity:false。
  17. userId:上面的userId,根据给当前进程分配的Linux UID(这个UID可以用来让上层系统服务进行身份识别和权限检查)得到一个userId(如果不是多用户,则直接返回0)。
  18. iContainer:传null。
  19. inTask:null。
  • ActivityStackSupervisor::startActivityLocked()
    参数:
  1. caller:上面的caller/contextThread,from主线程。
  2. intent:跳转Intent。
  3. resolvedType:跳转Intent的MIME类型。
  4. aInfoActivityInfo类型,解析from的Activity的Intent信息。
  5. voiceSession:传null。
  6. voiceInteractor:传null。
  7. resultTo:上面的resultTo/tokenBinder类型,用来标识from的Activity。
  8. resultWho:from的Activity的mEmbeddedID(唯一标示字符串)
  9. requestCode:如果是startActivity,则为-1。
  10. callingPackage:from的Context包名。
  11. startFlags:传null。
  12. options:额外数据。
  13. ignoreTargetSecurity:false。
  14. componentSpecified:是否显示指定了component
  15. outActivity:传null。
  16. container:上面的iContainer,转型成了ActivityContainer,还是null。
  17. inTask:null。
    在这个方法中,通过ProcessRecord callerApp = mService.getRecordForAppLocked(caller);获取到之前创建的ProcessRecord,然后从Activity栈中根据resultTo/token获取到对应from Activity的ActivityRecord(sourceRecord),然后__创建将要跳转的Activity的ActivityRecord对象__(Token也是在这个时候生成的)。
  • ActivityStackSupervisor::startActivityUncheckedLocked()
    参数:
  1. rActivityRecord类型,就是ActivityStackSupervisor::startActivityLocked()中创建的将要跳转的Activity的ActivityRecord对象。
  2. sourceRecord:就是ActivityStackSupervisor::startActivityLocked()方法获取的from Activity的sourceRecord
  3. voiceSession:传null。
  4. voiceInteractor:传null。
  5. startFlags:传null。
  6. doResume:传true。
  7. options:额外数据。
  8. inTask:null。
    这个方法中有大量的代码来处理task/stack等方面的逻辑,以后再仔细深入这个方法。
  • ActivityStrack::startActivityLocked()
    方法调用者:ActivityStack类型,
    targetStack:在ActivityStackSupervisor::startActivityUncheckedLocked()中确定的需要添加到的ActivityStack
    参数:
  1. rActivityRecord类型,就是ActivityStackSupervisor::startActivityLocked()中创建的跳转的Activity的ActivityRecord对象。
  2. newTask:是否Intent是否设置了Intent.FLAG_ACTIVITY_NEW_TASK
  3. doResume:传true。
  4. keepCurTransition:这个具体后面再研究,跟Intent的flag有关。
  5. options:额外数据。
    同样,这个方法中有大量的代码来处理task/stack等方面的逻辑,以后再仔细深入这个方法__(执行完这个方法后,ActivityRecord就会被真正加入到ActivityStack中)__。
  • ActivityStackSupervisor::resumeTopActivitiesLocked()
    参数:
  1. targetStack:在ActivityStackSupervisor::startActivityUncheckedLocked()中确定的需要添加到的ActivityStack
  2. targetActivityRecord类型,就是ActivityStackSupervisor::startActivityLocked()中创建的跳转的Activity的ActivityRecord对象。
  3. targetOptions:额外数据。
  • ActivityStack::resumeTopActivityLocked()
    参数:
  1. prevActivityRecord类型,就是ActivityStackSupervisor::startActivityLocked()中创建的跳转的Activity的ActivityRecord对象。
  2. options:额外数据。
  • ActivityStack::resumeTopActivityInnerLocked()
    参数:
  1. prevActivityRecord类型,就是ActivityStackSupervisor::startActivityLocked()中创建的跳转的Activity的ActivityRecord对象。
  2. options:额外数据。
  • ActivityStackSupervisor::startSpecificActivityLocked()
    参数:
  1. r:最顶部没有处于finishing的Activity,就是刚刚在startActivityLocked中加入的将要跳转的ActivityRecord,通过topRunningActivityLocked(null)查找
  2. andResume:传true
  3. checkConfig:传true
  • ActivityManagerService::startProcessLocked()
    参数:
  1. processName:创建进程的名称,就是ActivityStack::startSpecificActivityLocked()中的r.processName
  2. infoApplicationInfo,也是r.info.applicaitonInfo,具体可以查看ActivityStackSupervisor::startActivityLocked()中创建ActivityRecord的代码。
  3. knownToBeDead:传true。
  4. intentFlags:传0。
  5. hostingType:传字符串“activity”。
  6. hostingNameComponentName类型,intent中的Componentname
  7. allowWhileBooting:传false。
  8. isolated:传false
  9. keepIfLarge传true
  • ActivityManagerService::startProcessLocked()(重载方法):
    参数包含上面所有,多了以下几个:
  1. isolatedUid:传0
  2. abiOverride:传null
  3. entryPoint:传null
  4. entryPointArgs传null
  5. crashHandler传null
    注意:在这个方法中,会创建新进程的ProcessRecord对象,并绑定ApplicationInfo等信息,这样,启动进程后进行bindApplicaiton的时候就可以根据进程PID获取到所有的ApplicationInfo信息了。
  • ActivityManagerService::startProcessLocked()(重载方法):
    参数:
  1. appProcessRecord类型,创建的进程。
  2. hostingType:传字符串“activity”。
  3. hostingNameStr:通过hostingName生成的字符串(包名 + "/" + 类的简单类名)
  4. abiOverride:传null
  5. entryPoint:传null
  6. entryPointArgs传null
  • Process.start()
    参数(省略部分参数):
  1. processClass:上面的entryPoint,但是并不是null了,而是android.app.ActivityThread,因为在ActivityManagerService::startProcessLocked()中被设置默认值了,它表示一个类,用来作为新创建的进程的主入口,会调用这个类的静态main方法。所以启动完这个进程就会进入ActivityThreadstatic main()方法。
  2. zygoteArgs:fork zygote进程时的参数。
  • ActivityThread::main()

  • ActivityThread::attach()

  • ActivityManagerProxy::attachApplication()
    参数:
  1. mAppThreadApplicationThread()类型,Binder,用来提供给AMS调用。
  • ActivityManagerService::attachApplication()
    参数:
  1. mAppThreadApplicationThread()类型,Binder,用来提供给AMS调用。
  • ActivityManagerService::attachApplicationLocked()
    参数:
  1. threadApplicationThread()类型,Binder,用来提供给AMS调用。上面的mAppThread
  2. pid:当前调用的进程PID。
  • IApplicationThread::bindApplication()
    方法调用调用者:上面的thread/mAppThread,Binder,用来提供给AMS调用。
    参数(省略部分参数):
  1. packageName:用的进程名字processName
  2. infoApplicationInfo类型,从ProcessRecord中的instrumentationInfo或者info,这个ApplicationInfo是在建立ProcessRecord时就保存了。
  • ActivityThread::bindApplication()
    参数:同上

  • ActivityThread::handleBindApplication()
    通过Handler调用。
    参数:
  1. dataAppBindData类型,里面包含的类型processNameprovidersinstrumentationNameinstrumentationArgsinstrumentationWatcherinstrumentationUiAutomationConnectionconfig等数据。


  • ActivityManagerService中的ActivityThread::bindApplication()执行完毕之后

  • ActivityStackSupervisor::attachApplicationLocked()
    参数:
  1. app:新建的进程绑定的ProcessRecord
  • ActivityStackSupervisor::realStartActivityLocked()
    参数:
  1. rActivityRecord类型,topRunningActivityLocked从堆栈顶端获取要启动的Activity。
  2. app:新建的进程绑定的ProcessRecord
  3. andResume:传入true
  4. checkConfig:传入true
  • IApplicationThread::scheduleLaunchActivity()
    参数(部分):
  1. intent:将要启动的ActivityRecord中的intent
  2. token:将要启动的ActivityRecord中的token
  3. info:将要启动的ActivityRecord中的ApplicationInfo
  • ActivityThread::scheduleLaunchActivity()
    Binder IPC调用,参数与IApplicationThread::scheduleLaunchActivity()相同。

  • ActivityThread::handleLaunchActivity()
    该方法通过Handler调用,参数同上。
  1. rActivityClientRecord类型,在ActivityThread::scheduleLaunchActivity()中封装,包括的数据有token, ident, intent, activityInfo等等,但是LoadedApk是这时根据包名从ActivityThread中弱引用缓存中获取的的。
  2. customIntent:null
  • ActivityThread::performLaunchActivity()
    参数与ActivityThread::handleLaunchActivity()相同。

  • Activity::attach()
    参数(部分):
  1. contextActivityThread::performLaunchActivity()中创建的Activity Context
  2. aThreadActivityThread类型,主线程,一个进程都共用一个。
  3. token:构建ActivityRecord时生成的token
  4. applicationApplication第一次的时候创建一遍。
  5. intent:将要启动的ActivityRecord中的intent。
  6. infoActivityInfo类型,将要启动的ActivityRecord中的ActivityInfo
  • Instrumentation::callActivityOnCreate()
    参数(部分):
  1. activityActivityThread::performLaunchActivity()中创建的Activity
  • Activity::performCreate()

  • Activity::onCreate()

相关文章
|
数据可视化
Matrix源码分析系列-如何计算App启动耗时(二)
Matrix源码分析系列-如何计算App启动耗时
167 0
Matrix源码分析系列-如何计算App启动耗时(二)
|
监控 Java 测试技术
Matrix源码分析系列-如何计算App启动耗时(一)
Matrix源码分析系列-如何计算App启动耗时
188 0
Matrix源码分析系列-如何计算App启动耗时(一)
|
JavaScript 测试技术 Android开发
干货|app自动化测试之Appium 源码分析
干货|app自动化测试之Appium 源码分析
|
4天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
23 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
8天前
|
安全 JavaScript 前端开发
小游戏源码开发之可跨app软件对接是如何设计和开发的
小游戏开发团队常需应对跨平台需求,为此设计了成熟的解决方案。流程涵盖游戏设计、技术选型、接口设计等。首先明确游戏功能与特性,选择合适的技术架构和引擎(如Unity或Cocos2d-x)。接着设计通用接口,确保与不同App的无缝对接,并制定接口规范。开发过程中实现游戏逻辑和界面,完成登录、分享及数据对接功能。最后进行测试优化,确保兼容性和性能,发布后持续维护更新。
|
10天前
|
前端开发 Java 测试技术
语音app系统软件源码开发搭建新手启蒙篇
在移动互联网时代,语音App已成为生活和工作的重要工具。本文为新手开发者提供语音App系统软件源码开发的启蒙指南,涵盖需求分析、技术选型、界面设计、编码实现、测试部署等关键环节。通过明确需求、选择合适的技术框架、优化用户体验、严格测试及持续维护更新,帮助开发者掌握开发流程,快速搭建功能完善的语音App。
|
11天前
|
机器学习/深度学习 存储 人工智能
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
MNN-LLM App 是阿里巴巴基于 MNN-LLM 框架开发的 Android 应用,支持多模态交互、多种主流模型选择、离线运行及性能优化。
884 14
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
|
11天前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
141 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
12天前
|
供应链 数据挖掘 API
1688APP 原数据 API 接口的开发、应用与收益
1688作为阿里巴巴旗下的B2B平台,汇聚海量供应商和商品资源。其APP原数据API接口为开发者提供获取商品详细信息的强大工具,涵盖商品标题、价格、图片等。通过注册开放平台账号、申请API权限并调用接口,开发者可构建比价工具、供应链管理及自动化上架工具等应用,提升用户体验与运营效率,创造新的商业模式。示例代码展示了如何使用Python调用API并解析返回结果。
68 8

热门文章

最新文章

  • 1
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
  • 2
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
  • 4
    【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
  • 5
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 6
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 7
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 8
    【Azure Logic App】使用MySQL 新增行触发器遇见错误 :“Unknown column 'created_at' in 'order clause'”
  • 9
    阿里云APP备案流程图以及备案所需材料整理,跟着教程一步步操作
  • 10
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 1
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    34
  • 2
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 3
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 4
    【Azure Function】Function App门户上的Test/Run返回错误:Failed to fetch
    31
  • 5
    陪玩APP推送配置:陪玩系统手机锁屏收不到推送?可能是这些原因!解决方案来了!
    34
  • 6
    小游戏源码开发之可跨app软件对接是如何设计和开发的
    33
  • 7
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
    135
  • 8
    PiliPala:开源项目真香,B站用户狂喜!这个开源APP竟能自定义主题+去广告?PiliPala隐藏功能大揭秘
    60
  • 9
    语音app系统软件源码开发搭建新手启蒙篇
    44
  • 10
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
    884