SystemServer及AMS
- uboot 在引導(dǎo) os 啟動(dòng),然后加載 kernel;當(dāng) kernel 加載完成后,進(jìn)入 init 進(jìn)程,fork 出 zygote,然后由 zygote 去啟動(dòng) SystemServer;
- 在SystemServer中執(zhí)行run方法,啟動(dòng)AMS,并通過(guò)將SystemServer進(jìn)程可加到AMS中調(diào)度管理
mActivityManagerService.setSystemProcess();
AMS. setSystemProcess方法代碼
public void setSystemProcess() {
// 將服務(wù)加入到ServiceManager中
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
// 設(shè)置application info LoadedApkinfo 有關(guān) framework-res.apk
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
//給SystemServer進(jìn)程創(chuàng)建ProcessRecord,adj值,就是將SystemServer進(jìn)程加入到AMS進(jìn)程管理機(jī)制中,跟應(yīng)用進(jìn)程一致
synchronized (this) {
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
}
通過(guò)上面步驟,我們知道了AMS的啟動(dòng)及應(yīng)用進(jìn)程信息的收集存儲(chǔ),那么我們就可以繼續(xù)往下了解Activity的啟動(dòng)過(guò)程
Activity的啟動(dòng)應(yīng)該分為四個(gè)過(guò)程
向
AMS發(fā)起啟動(dòng)Activity請(qǐng)求AMS接收后通過(guò)socket方式發(fā)送fork進(jìn)程的參數(shù)給到Zygote進(jìn)程Zygote進(jìn)程接收后fork出應(yīng)用進(jìn)程并返回進(jìn)程的pid應(yīng)用進(jìn)程通過(guò)反射調(diào)用
ActivityThread中的main方法啟動(dòng)ActivityThread線程

相關(guān)類(lèi)說(shuō)明
-
Instrumentation:這個(gè)類(lèi)就是完成對(duì)Application和Activity初始化和生命周期的工具類(lèi)。每個(gè)Activity都持有Instrumentation對(duì)象的一個(gè)引用,但是整個(gè)進(jìn)程只會(huì)存在一個(gè)Instrumentation對(duì)象,這個(gè)Instrumentation對(duì)象存放在ActivityThread中。 -
ActivityManager:此類(lèi)提供有關(guān)活動(dòng),服務(wù)和包含過(guò)程的信息和交互。 -
IActivityManager:用于與ActivityManagerService交談的系統(tǒng)專(zhuān)用API。 提供了從應(yīng)用程序返回到活動(dòng)管理器的調(diào)用。 -
ActivityThread:管理應(yīng)用程序進(jìn)程中主線程的執(zhí)行,根據(jù)ActivityManager請(qǐng)求調(diào)度和執(zhí)行Activitys、broadcasts和其他操作。 -
ApplicationThread:ActivityThread內(nèi)部類(lèi),IApplicationThread.aidl的具體實(shí)現(xiàn),提供給ActivityManager,ActivityManager通過(guò)它告知應(yīng)用程序?qū)⒁龅氖隆?/li> - H:繼承Handler,ActivityThread內(nèi)部類(lèi),是應(yīng)用程序進(jìn)程中主線程的消息管理類(lèi)。(是
hook的一個(gè)點(diǎn)) -
ActivityManagerService:負(fù)責(zé)系統(tǒng)中四大組件的啟動(dòng)、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作。 -
ActivityStarter:用于解釋如何啟動(dòng)活動(dòng)的控制器。此類(lèi)收集用于確定如何將意圖和標(biāo)志轉(zhuǎn)變?yōu)榛顒?dòng)以及相關(guān)任務(wù)和堆棧的所有邏輯。 -
ActivityStack: 單個(gè)活動(dòng)棧的狀態(tài)和管理。 -
ActivityStackSupervisor:Activity棧管理。
LAUNCHER
上圖是startActivity的啟動(dòng)流程,通常我們點(diǎn)擊app啟動(dòng)的時(shí)候,會(huì)先執(zhí)行如下
/packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener,LauncherModel.Callbacks,
View.OnTouchListener {
......
public void onClick(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
return;
}
if (!mWorkspace.isFinishedSwitchingState()) {
return;
}
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
......
} else if (v == mAllAppsButton) {
......
}
}
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
......
}
return success;
}
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
// Only launch using the new animation if the shortcut has not opted out (this is a
// private contract between launcher and may be ignored in the future).
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
LauncherApps launcherApps = (LauncherApps)
this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
if (useLaunchAnimation) {
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
v.getMeasuredWidth(), v.getMeasuredHeight());
if (user == null || user.equals(android.os.Process.myUserHandle())) {
// Could be launching some bookkeeping activity
startActivity(intent, opts.toBundle());
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
} else {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent);
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(), null);
}
}
return true;
} catch (SecurityException e) {
......
}
return false;
}
因?yàn)閘auncher繼承于Activity,因此上面的startActivity最終都會(huì)調(diào)到Activity.startActivity,它實(shí)現(xiàn)如下:
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback {
......
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable 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());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
....
}
}
}
startActivityForResult方法
最終調(diào)用Instrumentation的execStartActivity來(lái)啟動(dòng)應(yīng)用
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
//...
options = transferSpringboardActivityOptions(options);
//這里調(diào)用instrumentation的execStartActivity()方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
} else {
//...
}
}
execStartActivity()方法
如下 ActivityManager.getService().startActivity涉及到了與AMS通信,通過(guò)getService()獲取到了遠(yuǎn)程對(duì)象引用(IActivityManager接口對(duì)象),這里是一個(gè)hook activity的關(guān)鍵點(diǎn),如果我們想啟動(dòng)一個(gè)沒(méi)有注冊(cè)的activity,那我們可以hook掉IActivityManager接口對(duì)象通過(guò)動(dòng)態(tài)代理的方式截取startActivity方法,從而將已注冊(cè)的代理activity傳入,這樣就可以讓AMS檢查activity為注冊(cè)文件中的activity。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//主要是這段代碼,可以看出這里會(huì)獲取Service,然后調(diào)用startActivity方法
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
最終通過(guò)ActivityStarter、ActivityStack等相關(guān)類(lèi)后,走到startSpecificActivityLocked方法
startSpecificActivityLocked方法
先從圖一啟動(dòng)activity,在startSpecificActivityLocked中會(huì)根據(jù)app的processName、uid來(lái)判斷是否已存在(即是否處于running狀態(tài)),若是則進(jìn)入realStartActivityLocked(即圖二 5),否則則進(jìn)入startProcessLocked方法通過(guò)socket與Zygote進(jìn)程通信,由Zygote進(jìn)程fork應(yīng)用進(jìn)程,在從應(yīng)用進(jìn)程中啟動(dòng)ActivityThread線程即app主線程,從而進(jìn)入圖二流程
r.info.flags&ActivityInfo.FLAG_MULTIPROCESS這個(gè)是有何用圖呢?
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
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);
}
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
Zygote進(jìn)程
Zygote進(jìn)程又稱(chēng)受精卵進(jìn)程,zygote進(jìn)程由init通過(guò)fork而來(lái),由app_process啟動(dòng),Zygote進(jìn)程最大意義是作為一個(gè)Socket的Server端,接收著各方的進(jìn)程創(chuàng)建請(qǐng)求,Android中所有的應(yīng)用進(jìn)程的創(chuàng)建都是一個(gè)應(yīng)用進(jìn)程通過(guò)Binder請(qǐng)求SystemServer進(jìn)程,SystemServer進(jìn)程發(fā)送socket消息給Zygote進(jìn)程,統(tǒng)一由Zygote進(jìn)程創(chuàng)建出來(lái)的。典型的C/S架構(gòu)。
進(jìn)程的啟動(dòng)流程:Init進(jìn)程-->Zygote進(jìn)程-->SystemServer進(jìn)程-->應(yīng)用進(jìn)程
進(jìn)程知識(shí)點(diǎn)
init:是linux系統(tǒng)中用戶(hù)空間的第一個(gè)進(jìn)程。由于Android是基于linux內(nèi)核的,所以init也是Android系統(tǒng)中用戶(hù)空間的第一個(gè)進(jìn)程,它的進(jìn)程號(hào)是1。
SystemServer:是由Zygote通過(guò)Zygote.forkSystemServer函數(shù)fork出來(lái)的。
應(yīng)用進(jìn)程:是Zygote通過(guò)fork創(chuàng)建的子進(jìn)程
zygote進(jìn)程將ZygoteInit作為啟動(dòng)類(lèi),會(huì)執(zhí)行它的main方法,先注冊(cè)ZygoteSocket,然后調(diào)用runSelectLoop方法,runSelectLoop方法會(huì)調(diào)用方法在ZygoteSocket上監(jiān)聽(tīng)請(qǐng)求,如果別的進(jìn)程通過(guò)ZygoteSocket請(qǐng)求孵化進(jìn)程,則孵化進(jìn)程。
Zygote進(jìn)程孵化出應(yīng)用進(jìn)程后,會(huì)通過(guò)反射調(diào)用ActivityThread中的main方法啟動(dòng)ActivityThread線程,main方法中會(huì)先開(kāi)啟Looper和消息隊(duì)列,然后調(diào)用attach方法將應(yīng)用進(jìn)程綁定到AMS,然后進(jìn)入loop循環(huán),不斷地讀取消息隊(duì)列里的消息,并分發(fā)消息。
ActivityThread
ui線程又稱(chēng)為主線程,應(yīng)用程序的入口 當(dāng)啟動(dòng)應(yīng)用程序時(shí)會(huì)由ActivityMangerService孵化一個(gè)進(jìn)程,并且實(shí)例化一個(gè)ActivityThread對(duì)象,該類(lèi)為final類(lèi)型,并不是一個(gè)線程類(lèi)
從圖一的activity啟動(dòng)流程最終由Zygote進(jìn)程孵化出應(yīng)用進(jìn)程后,通過(guò)反射調(diào)用ActivityThread中的main方法啟動(dòng)ActivityThread線程從而進(jìn)入圖二流程,如下圖

關(guān)鍵方法講解
attachApplicationLocked
關(guān)鍵代碼:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
····················
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
····················
mStackSupervisor.attachApplicationLocked(app)
}
通過(guò)圖二我們知道,首先會(huì)通過(guò)ActivityThread main()方法通過(guò)thread.attach(false)綁定應(yīng)用進(jìn)程。涉及到了一次IPC過(guò)程,通過(guò)將ApplicationThread實(shí)例化的對(duì)象(即thread對(duì)象 該對(duì)象其實(shí)就是一個(gè)binder對(duì)象)給AMS,然后調(diào)用AMS中的attachApplicationLocked方法,該方法有兩個(gè)關(guān)鍵方法,依次調(diào)用順序如下:
1) thread.bindApplication(processName, appInfo, providers, app.instrumentationClass...)方法
thread對(duì)象為上面?zhèn)魅氲膶?duì)象,該方法是創(chuàng)建Application的關(guān)鍵,該方法是ActivityThread的內(nèi)部類(lèi),通過(guò)發(fā)送消息給到前面提到的ActivityThread創(chuàng)建的Handler接收,接收消息后執(zhí)行handleBindApplication方法進(jìn)行application綁定,然后由LoadeApk對(duì)象調(diào)用其方法makeApplication。
makeApplication方法中依次執(zhí)行了兩個(gè)關(guān)鍵方法:
- mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext); - instrumentation.callApplicationOnCreate(app)
看到這里我們明白了application的創(chuàng)建及其onCreate方法的調(diào)用過(guò)程
2) mStackSupervisor.attachApplicationLocked(app)方法
看完上面執(zhí)行完thread.bindApplication(processName, appInfo, providers, app.instrumentationClass...)方法后,執(zhí)行第二個(gè)方法mStackSupervisor.attachApplicationLocked,該方法是啟動(dòng)Activity的關(guān)鍵,我們知道StackSupervisor是用來(lái)管理ActivityStack(Activity棧管理),從而走到了下面的attachApplicationLocked方法,詳情請(qǐng)繼續(xù)往下看
ActivityThread main()方法
AMS遠(yuǎn)程調(diào)用圖二 6 scheduleLaunchActivity方法后,會(huì)發(fā)送LAUNCH_ACTIVITY消息,還記得在execStartActivity()方法中,我們說(shuō)過(guò)我們可以通過(guò)hook IActivityManager接口對(duì)象實(shí)現(xiàn)動(dòng)態(tài)代理從而截取startActivity方法,將已注冊(cè)的代理activity傳入,但是在ActivityThread中main會(huì)開(kāi)啟消息循環(huán),這個(gè)時(shí)候會(huì)讀取到我們傳來(lái)LAUNCH_ACTIVITY消息,而消息中的activity仍是我們hook掉后替換的代理activity,所以我們還需要進(jìn)行一次hook,將main方法中的handler對(duì)象替換成我們自定義的,然后獲取到消息后,將代理activity替換成我們想啟動(dòng)的activity,從而完美繞過(guò)activity注冊(cè)檢測(cè)機(jī)制
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
attachApplicationLocked方法
該方法主要判斷是否需要開(kāi)啟新進(jìn)程
ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
//當(dāng)前應(yīng)用的整個(gè)activity堆信息
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
final ActivityRecord top = stack.topRunningActivityLocked();
final int size = mTmpActivityList.size();
for (int i = 0; i < size; i++) {
final ActivityRecord activity = mTmpActivityList.get(i);
if (activity.app == null && app.uid == activity.info.applicationInfo.uid
&& processName.equals(activity.processName)) {
try {
//如果應(yīng)用進(jìn)程與activity進(jìn)程名稱(chēng)相等則進(jìn)入,從而調(diào)起ActivityThread中的scheduleLaunchActivity方法
if (realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
didSomething = true;
}
} catch (RemoteException e) {
}
}
}
}
}
if (!didSomething) {
//如果應(yīng)用進(jìn)程與activity進(jìn)程名稱(chēng)不相等則進(jìn)入如下方法即圖一流程第1.9步,
//然后由SystemServer進(jìn)程與Zygote進(jìn)程通過(guò)socket通信,開(kāi)啟新的進(jìn)程
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
realStartActivityLocked方法
進(jìn)入realStartActivityLocked方法后,調(diào)用app.thread.scheduleLaunchActivity方法進(jìn)入ThreadActivity中的scheduleLaunchActivity方法,開(kāi)始發(fā)送LAUNCH_ACTIVITY消息
注意:如下的ProcessRecord app對(duì)象是怎么來(lái)的呢
通過(guò)看上面的attachApplicationLocked方法,我們知道其方法內(nèi)會(huì)先從mPidsSelfLocked容器中根據(jù)pid獲取
app = mPidsSelfLocked.get(pid);
該容器里的數(shù)據(jù)又是怎么來(lái)的呢?
追溯到本文開(kāi)頭AMS中的setSystemProcess方法進(jìn)行存儲(chǔ)的
ActivityStackSupervisor.java
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,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
····
}
scheduleLaunchActivity方法
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
//更新runtime中的進(jìn)程狀態(tài)
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
//組裝handler消息發(fā)送
sendMessage(H.LAUNCH_ACTIVITY, r);
}
ActivityThread中消息循環(huán)接收LAUNCH_ACTIVITY
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
getPackageInfo方法
該方法由getPackageInfoNoCheck方法內(nèi)部調(diào)起,主要作用是獲取Package信息,其中LoadedApk對(duì)象是APK文件在內(nèi)存中的表示。 Apk文件的相關(guān)信息,諸如Apk文件的代碼和資源,甚至代碼里面的Activity,Service等組件的信息我們都可以通過(guò)此對(duì)象獲取。
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
// Caching not supported across users
ref = null;
} else if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
: "Loading resource-only package ") + aInfo.packageName
+ " (in " + (mBoundApplication != null
? mBoundApplication.processName : null)
+ ")");
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
performLaunchActivity方法
該方法由handleLaunchActivity方法內(nèi)部調(diào)起,主要邏輯類(lèi)加載器創(chuàng)建Activity的實(shí)例對(duì)象
相關(guān)方法
isPersistable()方法: 多了個(gè)PersistableBundle參數(shù),作用在于當(dāng)Activity從意外結(jié)束恢復(fù)時(shí),傳遞結(jié)束前保存的Activity歷史數(shù)據(jù),從而恢復(fù)現(xiàn)場(chǎng)。
mInstrumentation.newActivity方法:調(diào)起loadClass從而加載對(duì)應(yīng)的classloader
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
·····
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//重點(diǎn) 將Activity類(lèi)文件加載到內(nèi)存中,創(chuàng)建Activity實(shí)例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
if (r.isPersistable()) {
//調(diào)起activity onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
try {
//創(chuàng)建application對(duì)象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
}
·····
}
Hook 掉Activity
看到這里,不得不提下插件化的一些原理知識(shí),在稍后章節(jié)也會(huì)做詳細(xì)剖析。
通常我們?cè)诓寮臅r(shí)候,需要寫(xiě)一些新的Activity,那這個(gè)時(shí)候你不可能說(shuō)在主apk中也同時(shí)注冊(cè)進(jìn)去吧?這樣顯然不可行,那肯定需要繞過(guò)AMS這個(gè)檢查機(jī)制,實(shí)現(xiàn)無(wú)需在AndroidManifest.xml中注冊(cè)也能運(yùn)行。
小編目前想到的三個(gè)hook點(diǎn)
- hook Instrumentation
重寫(xiě)Instrumentation中的execStartActivity方法,將已注冊(cè)的代理activity傳入
重寫(xiě)newActivity,在ActivityThread到handler啟動(dòng)Activity過(guò)程會(huì)調(diào)用newActivity,這個(gè)時(shí)候取出真正需要啟動(dòng)的activity - hook AMS和ActivityThread中的handler.callback
通過(guò)hook掉AMS中的IActivityManager接口,實(shí)現(xiàn)動(dòng)態(tài)代理,截取startActivity方法,將已注冊(cè)的代理activity傳入
再hook掉ActivityThread中的handler,替換成自定義的handler,在自定義的handler中接收LAUNCH_ACTIVITY消息,將真正需要啟動(dòng)的activity傳入
因?yàn)锳ctivityThread中的handler接收到LAUNCH_ACTIVITY消息后,需要將傳入的intent中包含的activity信息通過(guò)performLaunchActivity方法實(shí)例化activity對(duì)象
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
- hook PackageInfo
通過(guò)看上文提到的getPackageInfo方法,你會(huì)發(fā)現(xiàn)ActivityThread中消息循環(huán)接收LAUNCH_ACTIVITY時(shí),會(huì)先去調(diào)用getPackageInfo方法獲取Package信息,而Package信息有進(jìn)行緩存,即保存在mPackages容器中,你可以通過(guò)hook 往mPackages容器中放入擬定的數(shù)據(jù)
除了hook外,你也可以在宿主項(xiàng)目中預(yù)先在注冊(cè)文件中加入需要啟動(dòng)的插件activity,如:
<activity android:name="com.shengyuan.pulgin1.MainActivity2"/>
其實(shí)看完源碼你就會(huì)發(fā)現(xiàn)hook activity并不復(fù)雜,下面針對(duì)第二個(gè)方法點(diǎn)列出關(guān)鍵代碼
關(guān)鍵代碼
第一步hook AMS中的IActivityManager
替換系統(tǒng)的IActivityManager,主要采取動(dòng)態(tài)代理的技術(shù)構(gòu)造IActivityManager
注意:在android8.0上字段名稱(chēng)變更了
public void hookIActivityManager() throws Exception {
Log.i(TAG, "start hookIActivityManager");
Class<?> activityManagerNativeClass;
Field gDefaultFile;
/**
* 核心
* 由于IActivityManagerSingleton是單例模式,可以拿到系統(tǒng)該單例對(duì)象并且修改該對(duì)象
* 只有系統(tǒng)單例的對(duì)象修改才有效果
*/
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){
//反射獲取類(lèi)
activityManagerNativeClass = Class.forName("android.app.ActivityManager");
//獲取類(lèi)中的字段
gDefaultFile = activityManagerNativeClass.getDeclaredField("IActivityManagerSingleton");
}else {
//反射獲取類(lèi)
activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
//獲取類(lèi)中的字段
gDefaultFile = activityManagerNativeClass.getDeclaredField("gDefault");
}
//設(shè)置字段可訪問(wèn)
gDefaultFile.setAccessible(true);
//獲取反射字段的值,靜態(tài)方法,不需要傳入對(duì)象,所以對(duì)象為null
Object gDefaultFileValue = gDefaultFile.get(null);
//獲取gDefault.get()的值,主要在Singleton中
Class<?> singletonClass = Class.forName("android.util.Singleton");
Field mInstanceFile = singletonClass.getDeclaredField("mInstance");
mInstanceFile.setAccessible(true);
//非靜態(tài)方法,需要傳入對(duì)象,獲取系統(tǒng)的IActivityManager
Object IActivityManager = mInstanceFile.get(gDefaultFileValue);
//獲取IActivityManager接口
Class<?> IActivityManagerClass = Class.forName("android.app.IActivityManager");
//接下來(lái)需要?jiǎng)?chuàng)建鉤子,替換系統(tǒng)的IActivityManager,主要采取動(dòng)態(tài)代理的技術(shù)構(gòu)造IActivityManager
ProxyIActivityManager proxyIActivityManager= new ProxyIActivityManager(IActivityManager);
Object proxy = Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{IActivityManagerClass},
proxyIActivityManager);
//hook 就是為了替換IActivityManager的值,以下就是替換操作
mInstanceFile.set(gDefaultFileValue, proxy);
/////////到這里為止,已經(jīng)實(shí)現(xiàn)了用代理Activity來(lái)替換未注冊(cè)的Activity,通過(guò)PackageManagerService校驗(yàn)////////////
//接下來(lái)找到系統(tǒng)的ActivityThread 并且要找到單例對(duì)象,才可以修改該對(duì)象值
}
class ProxyIActivityManager implements InvocationHandler{
private Object iActivityManager;
public ProxyIActivityManager(Object iActivityManager){
this.iActivityManager = iActivityManager;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.i(TAG, "ProxyIActivityManager invoke:" + method.getName());
if (method.getName().contains("startActivity")){
int index = 0;
Intent realIntent = null;
for (int i = 0; i<args.length; i++){
if (args[i] instanceof Intent){
realIntent = (Intent) args[i];//真正的Intent,無(wú)法通過(guò)PackageManagerService檢查
index = I;
break;
}
}
//代理Intent,可以通過(guò)PackageManagerService檢查
Intent proxyIntent = new Intent(mContext, ProxyActivity.class);
proxyIntent.putExtra(REAL_INTENT, realIntent);
args[index] = proxyIntent;
}
return method.invoke(iActivityManager, args);
}
}
第二步hook ActivityThread中的H (即Handler對(duì)象)
public void hookActivityThreadHandler() throws Exception {
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Field currentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
currentActivityThreadField.setAccessible(true);
Object currentActivityThreadValue = currentActivityThreadField.get(null);
Field mHandlerField = activityThreadClass.getDeclaredField("mH");
mHandlerField.setAccessible(true);
Handler handlerValue = (Handler) mHandlerField.get(currentActivityThreadValue);
Field mCallbackField = Handler.class.getDeclaredField("mCallback");
mCallbackField.setAccessible(true);
mCallbackField.set(handlerValue, new HandlerCallback(handlerValue));
}
class HandlerCallback implements Handler.Callback{
private Handler mHandler;
public HandlerCallback(Handler handlerValue){
mHandler = handlerValue;
}
@Override
public boolean handleMessage(Message msg) {
//LAUNCH_ACTIVITY 的what值是100
if (msg.what == 100){
//先處理自己的Handler消息,再處理ActivityThread中自身的handler消息
try {
Log.i(TAG,"LAUNCH_ACTIVITY");
Object activityClientRecord = msg.obj;//ActivityClientRecord
Field intentField = activityClientRecord.getClass().getDeclaredField("intent");
intentField.setAccessible(true);
Intent proxyIntent = (Intent) intentField.get(activityClientRecord);
Intent realIntent = (Intent) proxyIntent.getParcelableExtra(REAL_INTENT);
if (realIntent != null){
//方法一,直接替換intent
//intentField.set(activityClientRecord, realIntent);
//方法二 替換component
proxyIntent.setComponent(realIntent.getComponent());
}
}catch (Exception e){
}
}
//處理ActivityThread中自身的handler消息
mHandler.handleMessage(msg);
return true;
}
}
給大家兩個(gè)思考的問(wèn)題
- ActivityThread究竟是線程嗎?
- 一個(gè)應(yīng)用進(jìn)程有多少個(gè)ActivityThread?