Android App啟動(dòng)流程淺談(上)——Android 9.0

本文中的部分內(nèi)容分析的是舊版本的代碼,與Android 9.0有所出入,所以寫了一篇完整的9.0應(yīng)用啟動(dòng)流程分析,大家可以訪問我的博客查看。

這是博客地址
文章——》淺談App啟動(dòng)流程

系統(tǒng)在開機(jī)后的一系列行為中,最后一階段AMS會(huì)調(diào)用Launcher來展示所有已經(jīng)安裝的APP,那么當(dāng)我們點(diǎn)擊圖標(biāo)到APP啟動(dòng),最后app的一個(gè)activity展示到我們的眼前,這中間到底是如何工作的呢,本文會(huì)從源碼中的主干代碼從整體上理解代碼的執(zhí)行流程。

整個(gè)流程圖

這張圖看起來很復(fù)雜是不是,我們用文字來大致的跑一邊流程:

  1. 當(dāng)點(diǎn)擊桌面App的時(shí)候,發(fā)起進(jìn)程就是Launcher所在的進(jìn)程,啟動(dòng)遠(yuǎn)程進(jìn)程,利用Binder發(fā)送消息給system_server進(jìn)程
  2. 在system_server進(jìn)程中啟動(dòng)了N多服務(wù),例如ActiivityManagerService,WindowManagerService等。啟動(dòng)進(jìn)程的操作會(huì)先調(diào)用AMS.startProcessLocked方法,內(nèi)部調(diào)用 Process.start(android.app.ActivityThread);而后通過socket通信告知Zygote進(jìn)程fork子進(jìn)程,即app進(jìn)程。進(jìn)程創(chuàng)建后將ActivityThread加載進(jìn)去,執(zhí)行ActivityThread.main()方法
  3. 在app進(jìn)程中,main方法會(huì)實(shí)例化ActivityThread,同時(shí)創(chuàng)建ApplicationThread,Looper,Hander對(duì)象,調(diào)用attach方法進(jìn)行Binder通信,looper啟動(dòng)循環(huán)。attach方法內(nèi)部獲取ActivityManagerProxy對(duì)象,其實(shí)現(xiàn)了IActivityManager接口,作為客戶端調(diào)用attachApplication(mAppThread)方法,將thread信息告知AMS
  4. 在system_server進(jìn)程中,AMS中會(huì)調(diào)用ActivityManagerNative.onTransact方法,真正的邏輯在服務(wù)端AMS.attachApplication方法中,內(nèi)部調(diào)用AMS.attachApplicationLocked方法,方法的參數(shù)是IApplicationThread,在此處是ApplicationThreadProxy對(duì)象,用于跟前面通過Process.start()所創(chuàng)建的進(jìn)程中ApplicationThread對(duì)象進(jìn)行通信。
    attachApplicationLocked方法會(huì)處理Provider, Activity, Service, Broadcast相應(yīng)流程,調(diào)用ApplicationThreadProxy.bindApplication方法,通過Binder通信,傳遞給ApplicationThreadNative.onTransact方法
  5. 在app進(jìn)程中,真正的邏輯在ActivityThread.bindApplication方法中。bindApplication方法的主要功能是依次向主線程發(fā)送消息H.SET_CORE_SETTINGS 和H.BIND_APPLICATION。后續(xù)創(chuàng)建Application,Context等。Activity的回調(diào)也會(huì)是通過Binder通信,然后發(fā)送不同消息處理。
    這里我們?cè)谟靡粡垐D來總結(jié)一下這段話:

Luancher——AMS

調(diào)用過程分析

源碼地址
frameworks/base/services/core/java/com/android/server/am/

  • ActivityManagerService.java
  • ActivityStackSupervisor.java
  • ActivityStack.java
  • ActivityRecord.java
  • ProcessRecord.java

frameworks/base/core/java/android/app/

  • IActivityManager.java

  • ActivityManagerNative.java (內(nèi)含AMP)
    -ActivityManager.java

  • IApplicationThread.java

  • ApplicationThreadNative.java (內(nèi)含ATP)

  • ActivityThread.java (內(nèi)含ApplicationThread)

  • ContextImpl.java

當(dāng)我們點(diǎn)擊桌面上的圖標(biāo)是,App就由Luancher開始啟動(dòng),Luancher也是一個(gè)應(yīng)用程序,繼承于Activity。Luancher也實(shí)現(xiàn)了點(diǎn)擊、長(zhǎng)按等回調(diào)接口,所以當(dāng)我們點(diǎn)擊圖標(biāo)時(shí),Luancher會(huì)捕捉點(diǎn)擊事件,然后startActivity(intent),是不是跟我們普通activity的使用差不多呢:
App圖標(biāo)的點(diǎn)擊事件會(huì)從Launcher.java中調(diào)用onClick方法:

public void onClick(View v) {
    ...
    Object tag = v.getTag();
    if (tag instanceof ShortcutInfo) {
        // 從快捷方式圖標(biāo)啟動(dòng)
        onClickAppShortcut(v);
    } else if (tag instanceof FolderInfo) {
        // 文件夾
        if (v instanceof FolderIcon) {
           onClickFolderIcon(v);
        }
    } else if (v == mAllAppsButton) {
        // “所有應(yīng)用”按鈕
        onClickAllAppsButton(v);
    } else if (tag instanceof AppInfo) {
        // 從“所有應(yīng)用”中啟動(dòng)的應(yīng)用
        startAppShortcutOrInfoActivity(v);
    } else if (tag instanceof LauncherAppWidgetInfo) {
        // 組件
        if (v instanceof PendingAppWidgetHostView) {
            onClickPendingWidget((PendingAppWidgetHostView) v);
        }
    }
}

1. Launcher.onClickAppShortcut

我們這里先分析從快捷圖標(biāo)點(diǎn)進(jìn)去的代碼

/**
     * Event handler for an app shortcut click.
     *
     * @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
     */
    protected void onClickAppShortcut(final View v) {
       
        Object tag = v.getTag();
        if (!(tag instanceof ShortcutInfo)) {
            throw new IllegalArgumentException("Input must be a Shortcut");
        }

        // Open shortcut
        final ShortcutInfo shortcut = (ShortcutInfo) tag;

        if (shortcut.isDisabled != 0) {
            if ((shortcut.isDisabled &
                    ~ShortcutInfo.FLAG_DISABLED_SUSPENDED &
                    ~ShortcutInfo.FLAG_DISABLED_QUIET_USER) == 0) {
                //如果應(yīng)用程序僅因上述標(biāo)志而被禁用,則無論如
                //何都會(huì)啟動(dòng)活動(dòng)。框架將告訴用戶應(yīng)用程序暫停的原因。
               
            } else {
                if (!TextUtils.isEmpty(shortcut.disabledMessage)) {
                    // Use a message specific to this shortcut, if it has one.
                    Toast.makeText(this, shortcut.disabledMessage, Toast.LENGTH_SHORT).show();
                    return;
                }
                // Otherwise just use a generic error message.
                int error = R.string.activity_not_available;
                if ((shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_SAFEMODE) != 0) {
                    error = R.string.safemode_shortcut_error;
                } else if ((shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_BY_PUBLISHER) != 0 ||
                        (shortcut.isDisabled & ShortcutInfo.FLAG_DISABLED_LOCKED_USER) != 0) {
                    error = R.string.shortcut_not_available;
                }
                Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
                return;
            }
        }

        // Check for abandoned promise
        if ((v instanceof BubbleTextView) && shortcut.isPromise()) {
            String packageName = shortcut.intent.getComponent() != null ?
                    shortcut.intent.getComponent().getPackageName() : shortcut.intent.getPackage();
            if (!TextUtils.isEmpty(packageName)) {
                onClickPendingAppItem(v, packageName,
                        shortcut.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE));
                return;
            }
        }

        // 啟動(dòng)Activity
        startAppShortcutOrInfoActivity(v);
    }

忽略前面的代碼,我們發(fā)現(xiàn)在onClickAppShortcut方法里又調(diào)用了 startAppShortcutOrInfoActivity方法。那我們繼續(xù)再看:

private void startAppShortcutOrInfoActivity(View v) {
        ItemInfo item = (ItemInfo) v.getTag();
        Intent intent = item.getIntent();
        if (intent == null) {
            throw new IllegalArgumentException("Input must have a valid intent");
        }
        boolean success = startActivitySafely(v, intent, item);
        getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115

        if (success && v instanceof BubbleTextView) {
            mWaitingForResume = (BubbleTextView) v;
            mWaitingForResume.setStayPressed(true);
        }
    }

這里又調(diào)用了startActivitySafely方法:

public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        ······
        //啟動(dòng)新的任務(wù)棧
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            ······
            if (user == null || user.equals(Process.myUserHandle())) {
                // 啟動(dòng)活動(dòng)
                startActivity(intent, optsBundle);
            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
           ······
        }
        return false;
    }

這里的代碼比較長(zhǎng),我們分別來看,去除前面的一些判斷,我們看到intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)這行代碼。說到應(yīng)用程序的Activity,他默認(rèn)是MainActivity,就是你在AndroidManifest.xml文件里配置的Activity:

<activity android:name=".MainActivity"  
      android:label="@string/app_name">  
       <intent-filter>  
        <action android:name="android.intent.action.MAIN" />  
        <category android:name="android.intent.category.LAUNCHER" />  
    </intent-filter>  
</activity>

所以這個(gè)intent包含的信息為action = "android.intent.action.Main",category="android.intent.category.LAUNCHER", cmp="shy.luo.activity/.MainActivity",他表示要啟動(dòng)的Activity為shy.luo.MainActivity.這里的Intent.FLAG_ACTIVITY_NEW_TASK表示要在一個(gè)新的Task中來啟動(dòng)這個(gè)Activity,這個(gè)Task是Android中的概念,簡(jiǎn)單地說,他是一個(gè)Activity的集合,這個(gè)集合是一個(gè)堆棧的形式,遵循先進(jìn)后出。再看startActivity方法。

2. Activity.startActivity

站在巨人的肩膀上:startActivity啟動(dòng)分析移步這里

Launcher繼承于Activity類,而Activity類實(shí)現(xiàn)了startActivity函數(shù),因此,這里就調(diào)用了Activity.startActivity函數(shù),它實(shí)現(xiàn)在frameworks/base/core/java/android/app/Activity.java文件中:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {
    ......
 
    @Override
    public void startActivity(Intent intent) {
        startActivityForResult(intent, -1);
    }
    ......
}

這個(gè)函數(shù)實(shí)現(xiàn)很簡(jiǎn)單,它調(diào)用startActivityForResult來進(jìn)一步處理,第二個(gè)參數(shù)傳入-1表示不需要這個(gè)Actvity結(jié)束后的返回結(jié)果.

3. Activity.startActivityForResult

public void startActivityForResult(Intent intent, int requestCode) {
        //mParent是當(dāng)前Acitivity的父類,此時(shí)條件成立
        if (mParent == null) {
        // 調(diào)用 Instrumentation 的 execStartActivity 方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode);
            if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        //此時(shí)requestCode =-1
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
         cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
}
public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        ...
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        ...
    }

  • mInstrumentation: Activity類的成員變量,類型是Intrumentation,用來監(jiān)控應(yīng)用程序和系統(tǒng)的交互。
  • mMainThread:Activity類的成員變量,類型是ActivityThread,它代表的是應(yīng)用程序的主線程,通過mMainThread.getApplicationThread獲得它里面的ApplicationThread成員變量,是一個(gè)Binder對(duì)象,后面我們會(huì)看到,ActivityManagerService會(huì)使用它來和ActivityThread來進(jìn)行進(jìn)程間通信。這里我們需注意的是,這里的mMainThread代表的是Launcher應(yīng)用程序運(yùn)行的進(jìn)程
  • mToken:Activity類的成員變量,類型為IBinder,一個(gè)Binder對(duì)象的遠(yuǎn)程接口。

Instrumentation這個(gè)類里面的方法大多數(shù)和Application和Activity有關(guān),這個(gè)類就是完成對(duì)Application和Activity初始化和生命周期的工具類。Instrumentation這個(gè)類很重要,對(duì)Activity生命周期方法的調(diào)用根本就離不開他,每個(gè)Activity都持有Instrumentation對(duì)象的一個(gè)引用,但是整個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象.ActivityThread,依賴于UI線程。App和AMS是通過Binder傳遞信息的,那么ActivityThread就是專門完成與AMS的外交工作的

Instrumentation.execStartActivity

Instrumentation調(diào)用ActivityManagerService的startActivity

public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {

    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...

    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    //當(dāng)該monitor阻塞activity啟動(dòng),則直接返回
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //檢查activity是否啟動(dòng)成功
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

Activity的startActivity會(huì)調(diào)用startActivityForResult。當(dāng)應(yīng)用已經(jīng)啟動(dòng)時(shí),會(huì)先調(diào)用startActivityFromChild。但是無論應(yīng)用是否啟動(dòng),最后都會(huì)調(diào)用Instrumentation.execStartActivity。
正如前面所說,ActivityManagerService實(shí)現(xiàn)了IActivityManager.aidl接口,提供了應(yīng)用進(jìn)程調(diào)用系統(tǒng)服務(wù)的方法,而Instrumentation包裝了ActivityManagerService的調(diào)用。

在看startActivity方法前,我們看看這里的ActivityManager.getService()方法做了什么。這里返回的是一個(gè)AMP對(duì)象,根據(jù)IPC我們知道當(dāng)服務(wù)端和客戶端通信時(shí),需要一個(gè)代理類來根據(jù)是否在同一個(gè)進(jìn)程,來實(shí)現(xiàn)通信的方式(需不需要跨進(jìn)程),而Luancher App所在的進(jìn)程和AMS所在進(jìn)程顯然不同,所以返回了包裝Binder的代理對(duì)象AMP。

Android IPC機(jī)制在整個(gè)啟動(dòng)流程源碼中使用了很多,對(duì)于IPC機(jī)制還不了解的可以先看看這篇IPC基礎(chǔ)速成,之后再去仔細(xì)學(xué)習(xí)。

 @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

IActivityManagerSingleton是一個(gè)靜態(tài)變量:

@UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                 // 向 ServiceManager 查詢一個(gè) key 為 Context.ACTIVITY_SERVICE" 的引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

ServiceManager 是 Binder IPC 通信過程的核心,是上下文的管理者,Binder 服務(wù)端必須先向 ServerManager 注冊(cè)才能夠?yàn)榭蛻舳颂峁┓?wù),Binder 客戶端在與服務(wù)端通信之前需要從 ServerManager 中查找并獲取 Binder 服務(wù)端的引用。

這里通過 "Context.ACTIVITY_SERVICE" 這個(gè)名字向 ServiceManager 查詢 AMS 的引用,獲取 AMS 的引用后,調(diào)用 asInterface 方法:

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    // 根據(jù) descriptor 查詢 obj 是否為 Binder 本地對(duì)象(是否在同一進(jìn)程)
    IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    // 如果 obj 不是 Binder 本地對(duì)象,則將其包裝成代理對(duì)象并返回
    return new ActivityManagerProxy(obj);
}

所以最終返回了AMP這個(gè)代理類,再往下看:

AMP.startActivity方法參數(shù)傳遞的每一項(xiàng)對(duì)應(yīng)值:

  • caller: 當(dāng)前應(yīng)用的ApplicationThread對(duì)象mAppThread,他是一個(gè)Binder實(shí)體;
  • callingPackage:調(diào)用當(dāng)前ContextImpl.getBasePackageName(),獲取當(dāng)前Activity所在包名;
  • intent: 這便是啟動(dòng)Activity時(shí),傳遞過來的參數(shù);
  • resolvedType: 調(diào)用intent.resolveTypeIfNeeded而獲取;
  • resultTo: 來自于當(dāng)前Activity.mToken
  • resultWho: 來自于當(dāng)前Activity.mEmbeddedID
  • requestCode = -1;
  • startFlags = 0;
  • profilerInfo = null;
  • options = null;

AMP.startActivity

class ActivityManagerProxy implements IActivityManager
{
   public ActivityManagerProxy(IBinder remote)
   {
       mRemote = remote;
   }

   public IBinder asBinder()
   {
       return mRemote;
   }

  public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(caller != null ? caller.asBinder() : null);
       data.writeString(callingPackage);
       intent.writeToParcel(data, 0);
       data.writeString(resolvedType);
       data.writeStrongBinder(resultTo);
       data.writeString(resultWho);
       data.writeInt(requestCode);
       data.writeInt(startFlags);
       if (profilerInfo != null) {
           data.writeInt(1);
           profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
       } else {
           data.writeInt(0);
       }
       if (options != null) {
           data.writeInt(1);
           options.writeToParcel(data, 0);
       } else {
           data.writeInt(0);
       }
       //調(diào)用號(hào)為START_ACTIVITY_TRANSACTION
       mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
       reply.readException();
       int result = reply.readInt();
       reply.recycle();
       data.recycle();
       return result;
   }
   ...
}

AMP經(jīng)過binder IPC,進(jìn)入ActivityManagerNative(簡(jiǎn)稱AMN)。接下來程序進(jìn)入了system_servr進(jìn)程,開始繼續(xù)執(zhí)行。

可以看到,AMP 里面將客戶端的請(qǐng)求通過 mRemote.transact 進(jìn)行轉(zhuǎn)發(fā),mRemote 對(duì)象正是 Binder 驅(qū)動(dòng)返回來的 Binder Proxy 對(duì)象,通過 Binder Proxy,Binder 驅(qū)動(dòng)最終將調(diào)用處于 Binder Server 端 AMN 中的 onTransact 方法:

AMN.onTransact

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
   switch (code) {
   case START_ACTIVITY_TRANSACTION:
   {
     data.enforceInterface(IActivityManager.descriptor);
     IBinder b = data.readStrongBinder();
     IApplicationThread app = ApplicationThreadNative.asInterface(b);
     String callingPackage = data.readString();
     Intent intent = Intent.CREATOR.createFromParcel(data);
     String resolvedType = data.readString();
     IBinder resultTo = data.readStrongBinder();
     String resultWho = data.readString();
     int requestCode = data.readInt();
     int startFlags = data.readInt();
     ProfilerInfo profilerInfo = data.readInt() != 0
             ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
     Bundle options = data.readInt() != 0
             ? Bundle.CREATOR.createFromParcel(data) : null;
     //又出現(xiàn)了startActivity方法,進(jìn)去看看
     int result = startActivity(app, callingPackage, intent, resolvedType,
             resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
     reply.writeNoException();
     reply.writeInt(result);
     return true;
   }
   ...
   }    }

AMN 是一個(gè)抽象類,它的 startActivity 為抽象方法,具體的實(shí)現(xiàn)在AMS里.

小結(jié):

從 Launcher App 到 AMS 的調(diào)用過程中使用了 Binder IPC 機(jī)制,調(diào)用方 Launcher App 相當(dāng)于 AIDL 過程中的 Activity 所在的 App,充當(dāng) Clinent 的角色;AMS 相當(dāng)于遠(yuǎn)程 Service 的角色,充當(dāng) Server 端角色,他們的調(diào)用過程總體上都是一樣的。

從 Launcher App 到 AMS 的時(shí)序圖如下:

AMS——zygote調(diào)用過程分析

AMS.startActivity


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

public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    //mActivityStarter的數(shù)據(jù)類型為ActivityStarter
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, options, false, userId, null, null);
}

ActivityStarter.startActivityMayWait

當(dāng)程序運(yùn)行到這里時(shí), AS.startActivityMayWait的主要參數(shù)取值如下:

  • caller = ApplicationThreadProxy, 用于跟調(diào)用者進(jìn)程ApplicationThread進(jìn)行通信的binder代理類.
  • callingPackage = ContextImpl.getBasePackageName(),獲取調(diào)用者Activity所在包名
  • intent: 這是啟動(dòng)Activity時(shí)傳遞過來的參數(shù)
  • resolvedType = intent.resolveTypeIfNeeded
  • resultTo = Activity.mToken, 其中Activity是指調(diào)用者所在Activity, mToken對(duì)象保存自己所處的ActivityRecord信息
  • resultWho = Activity.mEmbeddedID, 其中Activity是指調(diào)用者所在Activity
  • userId = AMS.handleIncomingUser, 當(dāng)調(diào)用者userId跟當(dāng)前處于同一個(gè)userId,則直接返回該userId;當(dāng)不相等時(shí)則根據(jù)調(diào)用者userId來決定是否需要將callingUserId轉(zhuǎn)換為mCurrentUserId

在上源碼:

final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) {
    ...
    boolean componentSpecified = intent.getComponent() != null;
    //創(chuàng)建新的Intent對(duì)象,即便intent被修改也不受影響
    intent = new Intent(intent);

    //收集Intent所指向的Activity信息, 當(dāng)存在多個(gè)可供選擇的Activity,則直接向用戶彈出resolveActivity 
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

    ActivityContainer container = (ActivityContainer)iContainer;
    synchronized (mService) {
        ···
        //調(diào)用startActivityLocked方法
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);

        Binder.restoreCallingIdentity(origId);
        ···
        return res;
    }
}

該過程主要功能:通過resolveActivity來獲取ActivityInfo信息, 然后再進(jìn)入ActivityStarter.startActivityLocked(),之后會(huì)依次調(diào)用(具體源碼就不貼了,走個(gè)大致流程):

  • ActivityStarter.doPendingActivityLaunchesLocked()
  • ActivityStarter.startActivityUnchecked()
  • ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()
  • ActivityStack.resumeTopActivityUncheckedLocked()
  • ActivityStack.resumeTopActivityInnerLocked()
  • ActivityStackSupervisor.startSpecificActivityLocked()

這里我們需要看看最后一個(gè)流程,ActivityStackSupervisor.startSpecificActivityLocked()里做了什么:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // 當(dāng)前 Activity 附屬的 Application
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    r.task.stack.setLaunchTime(r);
    // 如果 Application 已經(jīng)運(yùn)行
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
    }
    // 啟動(dòng)新進(jìn)程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

首先,在方法中獲取了當(dāng)前 Activity 附屬的 Application,如果已經(jīng)在運(yùn)行了,說明這個(gè) App 是已經(jīng)被啟動(dòng)過了的,這時(shí)候調(diào)用 realStartActivityLocked 方法就可以進(jìn)入下一步的流程了,同一個(gè) App 中不同 Activity 的相互啟動(dòng)就是走的這個(gè)流程。當(dāng) Application 沒有運(yùn)行的時(shí)候,就需要調(diào)用 AMS 的 startProcessLocked 方法啟動(dòng)一個(gè)進(jìn)程去承載它然后完成后續(xù)的工作,順便鋪墊一下,當(dāng)新進(jìn)程被啟動(dòng)完成后還會(huì)調(diào)用回到這個(gè)方法,查看 AMS 的 startProcessLocked方法

ActivityManagerService.startProcessLocked

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

這里調(diào)用了AMS的另一個(gè)startProcessLocked重載方法,看源碼:

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs){
    ...
    try {
        ...
        boolean isActivityProcess = (entryPoint == null);            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
        // 調(diào)用 Process 的 start 方法
        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);
        ...
    } catch (RuntimeException e) {
        ...
    }
}

AMS有四個(gè)startProcessLocked重載方法,最后這里調(diào)用了Process.start方法,其中這里有個(gè)entryPoint字段,這個(gè)參數(shù)是什么呢,這就是一個(gè)ActivityThread。這個(gè)參數(shù)傳進(jìn)來的目的,我們先不說,后面再談。

Process.start

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 abi,
                              String instructionSet,
                              String appDataDir,
                              String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
      ...
    }
}

start函數(shù)中只調(diào)用了startViaZygote方法:

private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
        /**
        * 1
        */
            ArrayList<String> argsForZygote = new ArrayList<String>();
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
          ...
            if (gids != null && gids.length > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append("--setgroups=");

                int sz = gids.length;
                for (int i = 0; i < sz; i++) {
                    if (i != 0) {
                        sb.append(',');
                    }
                    sb.append(gids[i]);
                }

                argsForZygote.add(sb.toString());
            }
         ...
            argsForZygote.add(processClass);
            if (extraArgs != null) {
                for (String arg : extraArgs) {
                    argsForZygote.add(arg);
                }
            }
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

在注釋1處創(chuàng)建了字符串列表argsForZygote ,并將啟動(dòng)應(yīng)用進(jìn)程的啟動(dòng)參數(shù)保存在argsForZygote中,函數(shù)的最后會(huì)調(diào)用zygoteSendArgsAndGetResult函數(shù),需要注意的是,zygoteSendArgsAndGetResult函數(shù)中第一個(gè)參數(shù)中調(diào)用了openZygoteSocketIfNeeded函數(shù),而第二個(gè)參數(shù)是保存應(yīng)用進(jìn)程的啟動(dòng)參數(shù)的argsForZygote。zygoteSendArgsAndGetResult函數(shù)如下

private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;
            writer.write(Integer.toString(args.size()));
            writer.newLine();
            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }
            writer.flush();
            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

zygoteSendArgsAndGetResult函數(shù)主要做的就是將傳入的應(yīng)用進(jìn)程的啟動(dòng)參數(shù)argsForZygote,寫入到ZygoteState中,結(jié)合上文我們知道ZygoteState其實(shí)是由openZygoteSocketIfNeeded函數(shù)返回的,那么我們接著來看openZygoteSocketIfNeeded函數(shù),代碼如下所示

private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);//1
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }
    if (primaryZygoteState.matches(abi)) {//2
        return primaryZygoteState;
    }
    // The primary zygote didn't match. Try the secondary.
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
        secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);//3
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }

    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }

    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
  • 注釋1處會(huì)調(diào)用ZygoteState的connect函數(shù)與名稱為ZYGOTE_SOCKET的Socket建立連接,這里ZYGOTE_SOCKET的值為“zygote”,這是因?yàn)閆ygote進(jìn)程啟動(dòng)過程時(shí),在Zygote的main函數(shù)中會(huì)創(chuàng)建name為“zygote”的Server端Socket。
  • 注釋2處如果連接name為“zygote”的Socket返回的primaryZygoteState與當(dāng)前的abi不匹配,則會(huì)在注釋3處連接name為“zygote_secondary”的Socket。這兩個(gè)Socket區(qū)別就是:name為”zygote”的Socket是運(yùn)行在64位Zygote進(jìn)程中的,而name為“zygote_secondary”的Socket則運(yùn)行在32位Zygote進(jìn)程中。既然應(yīng)用程序進(jìn)程是通過Zygote進(jìn)程fock產(chǎn)生的,當(dāng)要連接Zygote中的Socket時(shí),也需要保證位數(shù)的一致。

Zygote——ActivityThread

Socket進(jìn)行連接成功并匹配abi后會(huì)返回ZygoteState類型對(duì)象,我們?cè)诜治鰖ygoteSendArgsAndGetResult函數(shù)中講過,會(huì)將應(yīng)用進(jìn)程的啟動(dòng)參數(shù)argsForZygote寫入到ZygoteState中,這樣Zygote進(jìn)程就會(huì)收到一個(gè)創(chuàng)建新的應(yīng)用程序進(jìn)程的請(qǐng)求,我們回到ZygoteInit的main函數(shù),如下所示。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
       ...
        try {
         ...       
            //注冊(cè)Zygote用的Socket
            registerZygoteSocket(socketName);//1
           ...
           //預(yù)加載類和資源
           preload();//2
           ...
            if (startSystemServer) {
            //啟動(dòng)SystemServer進(jìn)程
                startSystemServer(abiList, socketName);//3
            }
            Log.i(TAG, "Accepting command socket connections");
            //等待客戶端請(qǐng)求
            runSelectLoop(abiList);//4
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }
  • 注釋1處通過registerZygoteSocket函數(shù)來創(chuàng)建一個(gè)Server端的Socket,這個(gè)name為”zygote”的Socket用來等待ActivityManagerService來請(qǐng)求Zygote來創(chuàng)建新的應(yīng)用程序進(jìn)程
  • 注釋2處用來預(yù)加載類和資源。
  • 注釋3處用來啟動(dòng)SystemServer進(jìn)程,這樣系統(tǒng)的關(guān)鍵服務(wù)也會(huì)由SystemServer進(jìn)程啟動(dòng)起來。
  • 注釋4處調(diào)用runSelectLoop函數(shù)來等待ActivityManagerService的請(qǐng)求,我們就來查看runSelectLoop:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();//2
        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);
        while (true) {
        ...
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce();//1
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

當(dāng)有ActivityManagerService的請(qǐng)求數(shù)據(jù)到來時(shí)會(huì)調(diào)用注釋1處的代碼,結(jié)合注釋2處的代碼,我們得知注釋1處的代碼其實(shí)是調(diào)用ZygoteConnection的runOnce函數(shù)來處理請(qǐng)求的數(shù)據(jù):

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            args = readArgumentList();//1
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            Log.w(TAG, "IOException on command socket " + ex.getMessage());
            closeSocket();
            return true;
        }
...
        try {
            parsedArgs = new Arguments(args);//2
        ...
        /**
        * 3 
        */
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
        } catch (ErrnoException ex) {
          ....
        }
       try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

在注釋1處調(diào)用readArgumentList函數(shù)來獲取應(yīng)用程序進(jìn)程的啟動(dòng)參數(shù),并在注釋2處將readArgumentList函數(shù)返回的字符串封裝到Arguments對(duì)象parsedArgs中。注釋3處調(diào)用Zygote的forkAndSpecialize函數(shù)來創(chuàng)建應(yīng)用程序進(jìn)程,參數(shù)為parsedArgs中存儲(chǔ)的應(yīng)用進(jìn)程啟動(dòng)參數(shù),返回值為pid。forkAndSpecialize函數(shù)主要是通過fork當(dāng)前進(jìn)程來創(chuàng)建一個(gè)子進(jìn)程的,如果pid等于0,則說明是在新創(chuàng)建的子進(jìn)程中執(zhí)行的,就會(huì)調(diào)用handleChildProc函數(shù)來啟動(dòng)這個(gè)子進(jìn)程也就是應(yīng)用程序進(jìn)程,如下所示

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
      ...
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }

handleChildProc函數(shù)中調(diào)用了RuntimeInit的zygoteInit函數(shù),如下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);//2
    }

注釋1處會(huì)在新創(chuàng)建的應(yīng)用程序進(jìn)程中創(chuàng)建Binder線程池,在注釋2處調(diào)用了applicationInit函數(shù):

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
 ...
        final Arguments args;
        try {
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());       
            return;
        }
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        invokeStaticMain(args.startClass, args.startArgs, classLoader);//1
    }

在applicationInit中會(huì)在注釋1處調(diào)用invokeStaticMain函數(shù),需要注意的是第一個(gè)參數(shù)args.startClass,這里指的就是前文提到的參數(shù):android.app.ActivityThread。接下來我們查看invokeStaticMain函數(shù)。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
    try {
        cl = Class.forName(className, true, classLoader);//1
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });//2
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
                "Missing static main on " + className, ex);
    }
    ...
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
}

可以看到注釋1處通過反射來獲得android.app.ActivityThread類,接下來在注釋2處來獲得ActivityThread的main函數(shù),并將main函數(shù)傳入到注釋3處的ZygoteInit中的MethodAndArgsCaller類的構(gòu)造函數(shù)中,MethodAndArgsCaller類內(nèi)部會(huì)通過反射調(diào)用ActivityThread的main函數(shù),前文ZygoteInit.main中會(huì)捕獲該異常,調(diào)用caller.run方法,這樣應(yīng)用程序進(jìn)程就創(chuàng)建完成了,使用拋出捕獲異常來調(diào)用,主要是為了把當(dāng)前線程堆棧的信息給置空。

ActivityThread.main

從 ActivityThread 的main方法開始,應(yīng)用進(jìn)入 java 層,應(yīng)用在main里面的關(guān)鍵代碼:

public static void main(String[] args) {
        ... ...
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);
        ... ...
        Looper.loop();
    }

主要的三件事:

  • 調(diào)用Looper.prepareMainLooper 創(chuàng)建mainLooper并賦值給Loop (這個(gè)looper的MessageQueue不能quit)靜態(tài)變量 sMainLooper ,這樣應(yīng)用可以在任何地方拿到主線程的Looper
  • 創(chuàng)建ActivityThread實(shí)例,并調(diào)用attach,這兩步很關(guān)鍵,首先,ActivityThread對(duì)象創(chuàng)建時(shí),會(huì)創(chuàng)建ResourcesManager的單例對(duì)象,還會(huì)創(chuàng)建 ApplicationThread 對(duì)象作為匿名Binder服務(wù)端用以跟system_server進(jìn)程通信,在thread.attach(false) 中通過AMP把 這個(gè)對(duì)象注冊(cè)到AMS:

看看thread.attach方法做了什么:

 @UnsupportedAppUsage
    private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ···
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }else{
        ···
        }
    }

AMS 對(duì)各應(yīng)用組件的生命周期管理就是通過這個(gè)對(duì)象實(shí)現(xiàn)的,AMS會(huì)通過這個(gè)ApplicationThread 對(duì)象遠(yuǎn)程調(diào)用應(yīng)用進(jìn)程的方法從而實(shí)現(xiàn)管理。
另外在attach 方法里ActivityThread對(duì)象會(huì)把自己賦值給靜態(tài)變量sCurrentActivityThread,在應(yīng)用開發(fā)中可以通過反射ActivityThread 直接拿到這個(gè)靜態(tài)變量對(duì)象或反射后調(diào)用靜態(tài)方法 currentActivityThread()拿到應(yīng)用的ActivityThread 對(duì)象,從而可以拿到其成員變量mAppThread,mInstrumentation,插件化方案可能需要hook這兩個(gè)對(duì)象

  • 主線程啟動(dòng)loop,進(jìn)入循環(huán),等待其他線程往消息隊(duì)列里發(fā)消息

站在巨人們的肩膀上

Android應(yīng)用進(jìn)程啟動(dòng)過程

慕課網(wǎng)應(yīng)用啟動(dòng)流程

應(yīng)用啟動(dòng)流程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評(píng)論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評(píng)論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,160評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容