Activity启动源码 并通过源码分析实现 Activity绕过AndroidManifest检测

Activity启动源码
源码解析
(注意这里使用的Android源码是Android10.0)
查看Android源码的网址
http://androidxref.com/ 这个是比较常用的,能看到10.0之前的源码
https://cs.android.com/ 这个是能看到10.0源码的(这个可能需要梯子)
从Activity的StartActivity开始
class Activity
@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);
}
}
可以看到无论option是否为null都是走startActivityForResult()方法
class Activity
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
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 {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
先看一下这里的代码
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
进去看这个execStartActivity()方法是干什么的
class Instrumentation
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
//这个是同步锁
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityTaskManager.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;
}
重点是关注这里
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
第一次跨进程通信
点进去getService()方法
class ActivityTaskManager
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
这里的IActivityTaskManagerSingleton.get()方法我就直说是调用Singleton的create()方法,直接返回一个Stub,从这个Stub就可以看出这里是跨进程通信,这里通过ServiceManager来进行跨进程通信获取到另一个进程的Binder这里是ACTIVITY_TASK_SERVICE的进程,这里其实是一个CS结构,S就是ServiceManager,通过获取到想要的Binder。
好这里是返回IActivityTaskManager.Stub.asInterface(b),并执行他的startActivity()方法,那么这个"它"是个什么?
这里我直接给出答案就是ActivityTaskManagerService类
class ActivityTaskManagerService extends IActivityTaskManager.Stub
看他的startActivity()方法(注意这里是调用Stub的startActivity()方法,那么也意味着进程切换到系统进程,其实每次看到ActivityTaskManagerService就已经是涉及跨进程操作)
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
好家伙直接几个跳转,最后跳到
class ActivityTaskManagerService
int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
我们先看这个userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
这里userId是 UserHandle.getCallingUserId()
class UserHandle
public static @UserIdInt int getCallingUserId() {
return getUserId(Binder.getCallingUid());
}
从名称可以猜测他是与Binder相关系,应该是记录/查找Binder的uid,
然后继续看一下getActivityStartController().checkTargetUser()方法
class ActivityStartController
/**
* If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling
* user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into
* account "current user", etc.
*
* If {@code validateIncomingUser} is false, it skips the above check, but instead
* ensures {@code targetUserId} is a real user ID and not a special user ID such as
* {@link android.os.UserHandle#USER_ALL}, etc.
*/
int checkTargetUser(int targetUserId, boolean validateIncomingUser,
int realCallingPid, int realCallingUid, String reason) {
if (validateIncomingUser) {
return mService.handleIncomingUser(
realCallingPid, realCallingUid, targetUserId, reason);
} else {
mService.mAmInternal.ensureNotSpecialUser(targetUserId);
return targetUserId;
}
}
从注解中看到就是如过validateIncomingUser为true 那么就会通过realCallingUid来检查targetUserId连接当前的User。
这里的User其实就是对应的Binder,也就是上么提及到从Context.ACTIVITY_TASK_SERVICE中获取的Binder。
从上面的代码走到这里那么这个validateIncomingUser是为true,那么就是会走
return mService.handleIncomingUser(
realCallingPid, realCallingUid, targetUserId, reason);
这里先暂时分析到这里回到ActivityTaskManagerService.getActivityStartController().obtainStarter()方法
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
从代码就能猜到是通过线程池来启动这个Activity,点进去看一下obtainStarter()
class ActivityStartController
/**
* @return A starter to configure and execute starting an activity. It is valid until after
* {@link ActivityStarter#execute} is invoked. At that point, the starter should be
* considered invalid and no longer modified or used.
*/
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
从注解就证实我们的想法,就是通过线程池来启动这个(注意一下这里启动线程池的其实是系统进程,而不是一开的的进程)
那我们看一下这个线程池的具体执行方法
class ActivityStartController
ActivityStartController(ActivityTaskManagerService service) {
this(service, service.mStackSupervisor,
new DefaultFactory(service, service.mStackSupervisor,
new ActivityStartInterceptor(service, service.mStackSupervisor)));
}
@VisibleForTesting
ActivityStartController(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
Factory factory) {
mService = service;
mSupervisor = supervisor;
mHandler = new StartHandler(mService.mH.getLooper());
mFactory = factory;
mFactory.setController(this);
mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service,
service.mH);
}
这里的new DefaultFactory(service, service.mStackSupervisor, new ActivityStartInterceptor(service, service.mStackSupervisor))
就是这个线程池但是在源码中看是红色的,我们无法找到DefaultFactory这类,其实这个类是在ActivityStarter这个类中
类的位置为android-29\com\android\server\wm\ActivityStarter.java
可以在你的sdk中这个位置找到
因为这里是线程此,直找execute()方法
class ActivityStarter
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
}
} finally {
onExecutionComplete();
}
}
这里走的是startActivityMayWait()方法
class ActivityStarter
private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup) {
...
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup);
}
这个方法非常之多操作,这里我解析出来,一部分一部分分析,
class ActivityStarter
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
这个是解析Activity的信息看一下这里面的参数获取rInfo
class ActivityStarter
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
点进去看一下
class ActivityStackSupervisor
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
int modifiedFlags = flags
| PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
if (intent.isWebIntent()
|| (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
modifiedFlags |= PackageManager.MATCH_INSTANT;
}
// In order to allow cross-profile lookup, we clear the calling identity here.
// Note the binder identity won't affect the result, but filterCallingUid will.
// Cross-user/profile call check are done at the entry points
// (e.g. AMS.startActivityAsUser).
final long token = Binder.clearCallingIdentity();
try {
return mService.getPackageManagerInternalLocked().resolveIntent(
intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
} finally {
Binder.restoreCallingIdentity(token);
}
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
return mService.getPackageManagerInternalLocked().resolveIntent( intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
重点在这一行,这里resolveIntent()方法是红色的,那么我们先看getPackageManagerInternalLocked()
class ActivityTaskManagerService
PackageManagerInternal getPackageManagerInternalLocked() {
if (mPmInternal == null) {
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
}
return mPmInternal;
}
然而PackageManagerInternal是红色的不可见,并且找到后发现他是个抽象类,要找到他的继承者,很麻烦。然后我先猜一下他的实现是不是PackageManagerInternalImpl,一查找果真发现了,并且是一个内部类,在PackageManagerService类中。
class PackageManagerInternalImpl
private class PackageManagerInternalImpl extends PackageManagerInternal {
....
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
return resolveIntentInternal(intent, resolvedType, flags, userId, false,
Binder.getCallingUid());
}
/**
* Normally instant apps can only be resolved when they're visible to the caller.
* However, if {@code resolveForStart} is {@code true}, all instant apps are visible
* since we need to allow the system to start any installed application.
*/
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
int flags, int userId, boolean resolveForStart, int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
chooseBestActivity(intent, resolvedType, flags, query, userId);
return bestChoice;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
}
List
这里就是取出所有的Actvity,他是根据intent来判断你能启动的Activity,通过隐式intent调用我们是能选择不同的Activity来启动的,如选择打开一个网页(使用隐式Intent来打开),会提示有很多个浏览器(前提下你的手机装了多个浏览器)。同理打开Activity有可能有多个合适的。
然后继续往下看一下 chooseBestActivity() 其实从方法名称来看就知道就是选择最合适的Activity出来。
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
return query.get(0);
} else if (N > 1) {
final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
// If there is more than one activity with the same priority,
// then let the user decide between them.
ResolveInfo r0 = query.get(0);
ResolveInfo r1 = query.get(1);
if (DEBUG_INTENT_MATCHING || debug) {
Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
+ r1.activityInfo.name + "=" + r1.priority);
}
// If the first activity has a higher priority, or a different
// default, then it is always desirable to pick it.
if (r0.priority != r1.priority
|| r0.preferredOrder != r1.preferredOrder
|| r0.isDefault != r1.isDefault) {
return query.get(0);
}
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
flags, query, r0.priority, true, false, debug, userId);
if (ri != null) {
return ri;
}
// If we have an ephemeral app, use it
for (int i = 0; i < N; i++) {
ri = query.get(i);
if (ri.activityInfo.applicationInfo.isInstantApp()) {
final String packageName = ri.activityInfo.packageName;
final PackageSetting ps = mSettings.mPackages.get(packageName);
final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
final int status = (int)(packedStatus >> 32);
if (status != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
return ri;
}
}
}
.....
return ri;
}
}
return null;
}
这里我就不细看了,有兴趣的可以自己看这个类,从注释中可以发现和我的猜想一致。
我们重新回到ActivityStarter
class ActivityStarter
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
这个时候我们知道了这个rInfo其实就是一个我们想要打开的Activity信息。
继续往下看
class ActivityStarter
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
这个就是进一步加工成ActivityInfo,通过注释说明就是收集目标intent的信息即是Activity的信息。
继续往下看,这里可以说是比较关键的一步。
class ActivityStarter
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
allowBackgroundActivityStart);
点进去看一下。
class ActivityStarter
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
allowBackgroundActivityStart);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return getExternalResult(mLastStartActivityResult);
}
这里的reason是开启一个Activity,然后又是一个startActivity()继续往下看
又是一大段东西,再次分析
class ActivityStarter
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart){
mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
WindowProcessController callerApp = null;
if (caller != null) {
callerApp = mService.getProcessController(caller);
if (callerApp != null) {
callingPid = callerApp.getPid();
callingUid = callerApp.mInfo.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
final int userId = aInfo != null && aInfo.applicationInfo != null
? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
.....
//获取Activity栈
final ActivityStack resultStack = resultRecord == null
? null : resultRecord.getActivityStack();
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
inTask != null, callerApp, resultRecord, resultStack);
....
}
先看这里 int err = ActivityManager.START_SUCCESS; 不同的情况会返回一个一个状况给err,默认为START_SUCCESS
就像下面这样
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart){
.....
if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
// We couldn't find a class that can handle the given Intent.
// That's the end of that!
err = ActivityManager.START_INTENT_NOT_RESOLVED;
}
if (err == ActivityManager.START_SUCCESS && aInfo == null) {
// We couldn't find the specific class specified in the Intent.
// Also the end of the line.
err = ActivityManager.START_CLASS_NOT_FOUND;
}
.....
}
继续往下面看,当err都通过各种情况判断,那么就走下面这里的代码
final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
return res;
继续看这个新的startActivity()
class ActivityStarter
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
int result = START_CANCELED;
final ActivityStack startedActivityStack;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
} finally {
final ActivityStack currentStack = r.getActivityStack();
startedActivityStack = currentStack != null ? currentStack : mTargetStack;
if (ActivityManager.isStartResultSuccessful(result)) {
if (startedActivityStack != null) {
// If there is no state change (e.g. a resumed activity is reparented to
// top of another display) to trigger a visibility/configuration checking,
// we have to update the configuration for changing to different display.
final ActivityRecord currentTop =
startedActivityStack.topRunningActivityLocked();
if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
mRootActivityContainer.ensureVisibilityAndConfig(
currentTop, currentTop.getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
}
} else {
// If we are not able to proceed, disassociate the activity from the task.
// Leaving an activity in an incomplete state can lead to issues, such as
// performing operations without a window container.
final ActivityStack stack = mStartActivity.getActivityStack();
if (stack != null) {
stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
null /* intentResultData */, "startActivity", true /* oomAdj */);
}
// Stack should also be detached from display and be removed if it's empty.
if (startedActivityStack != null && startedActivityStack.isAttached()
&& startedActivityStack.numActivities() == 0
&& !startedActivityStack.isActivityTypeHome()) {
startedActivityStack.remove();
}
}
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityProcessing(r, result, startedActivityStack);
return result;
}
看一下这行代码
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
点进去看一下,holy s** 又是一大段,继续看
class ActivityStarter
// Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
final int preferredWindowingMode = mLaunchParams.mWindowingMode;
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
ActivityRecord reusedActivity = getReusableIntentActivity();
....
}
先看setInitialState()这个方法
class ActivityStarterclass ActivityStarter
private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
boolean doResume, int startFlags, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean restrictedBgActivity){
//这个方法是初始化ActivityStarter自身的属性,将部分属性设置为null
reset(false /* clearRequest */);
mLaunchMode = r.launchMode;
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
mLaunchTaskBehind = r.mLaunchTaskBehind
&& !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
}
// If we are actually going to launch in to a new task, there are some cases where
// we further want to do multiple task.
if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
if (mLaunchTaskBehind
|| r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
}
}
...
}
mLaunchMode = r.launchMode;
mLaunchFlags = adjustLaunchFlagsToDocumentMode( r, LAUNCH_SINGLE_INSTANCE == mLaunchMode, LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags()); mLaunchTaskBehind = r.mLaunchTaskBehind && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE) && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT)
这两行代码就是获取Activiy的启动model,如single_Task,single_top这些模式。
isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)看到这行代码了吗,其实这个setInitialState方法就是先看Activity是不是SINGLE_TASK或SINGLE_INSTANCE,因为这两个比较特殊,关系到需要开一个新的Activity栈,所以需要判断是否需要开一栈,更多细节就不看了,想了解的可以自己找这个方法看。
重新回到startActivityUnchecked()方法,到了computeLaunchingTaskFlags()这个方法,其实这个就是如果启动模式是INGLE_TASK或SINGLE_INSTANCE,那么就开一个新的栈来存放这个新的Activity。
继续往下看
当启动模式为LAUNCH_SINGLE_TOP或LAUNCH_SINGLE_TASK就会走下面这个方法
deliverNewIntent(top)
class ActivityStarter
private void deliverNewIntent(ActivityRecord activity) {
if (mIntentDelivered) {
return;
}
ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTaskRecord());
activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
mIntentDelivered = true;
}
再走deliverNewIntentLocked()方法
class ActivityRecord
final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
// The activity now gets access to the data associated with this Intent.
mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
intent, getUriPermissionsLocked(), mUserId);
final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
boolean unsent = true;
final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
// We want to immediately deliver the intent to the activity if:
// - It is currently resumed or paused. i.e. it is currently visible to the user and we want
// the user to see the visual effects caused by the intent delivery now.
// - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
&& attachedToProcess()) {
try {
ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
ar.add(rintent);
// Making sure the client state is RESUMED after transaction completed and doing
// so only if activity is currently RESUMED. Otherwise, client may have extra
// life-cycle calls to RESUMED (and PAUSED later).
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
NewIntentItem.obtain(ar, mState == RESUMED));
unsent = false;
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
} catch (NullPointerException e) {
Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
}
}
if (unsent) {
addNewIntentLocked(rintent);
}
}
看到这个 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,NewIntentItem.obtain(ar, mState == RESUMED))
在网上我们能常常看到SINGLE_TOP的特点:
当目标Activity处于当前栈顶时,会调用Activity的onNewIntent()方法,但不创建新实例;其他情况都和standard一致。
这个就是走的这一行代码。
好继续startActivityUnchecked()方法往下走
class ActivityStarterclass ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
.....
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
if (reusedActivity != null) {
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
// The reusedActivity could be finishing, for example of starting an
// activity with FLAG_ACTIVITY_CLEAR_TOP flag. In that case, return the
// top running activity in the task instead.
outActivity[0] = reusedActivity.finishing
? reusedActivity.getTaskRecord().getTopActivity() : reusedActivity;
}
return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
}
}
}
先看这行**reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity)**代码,这里的reusedActivity就是我们需要创建的Activity。这里比较关键,
点进去看里面的代码比较多,我挑一些重点的来看并在代码处注明点注释
class ActivityStarter
/**
* Figure out which task and activity to bring to front when we have found an existing matching
* activity record in history. May also clear the task if needed.
* @param intentActivity Existing matching activity.
* @return {@link ActivityRecord} brought to front.
*/
private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
//先获取到Activity所在的栈顶
mTargetStack = intentActivity.getActivityStack();
mTargetStack.mLastPausedActivity = null;
.....
//将这个栈移动到最前面,也就是说将其变成当前使用的栈(无论创建Activity是否放入到产生的新栈)把Activity所在栈放到
//最前面
mTargetStack.moveTaskToFrontLocked(intentTask,
mNoAnimation, mOptions, mStartActivity.appTimeTracker,
"bringToFrontInsteadOfAdjacentLaunch");
...
// We are moving a task to the front, use starting window to hide initial drawn
// delay.
//通过上面的注释说明就是显示这个栈在window中,方法里面我就不点看了,其实无非就是获取到window,并且显示栈中的Acttivity
intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
true /* taskSwitch */);
}
大概这个setTargetStackAndMoveToFrontIfNeeded()方法就是这样,将当前栈(可能为新的栈)推到最前面,并且通过window来显示。回到上面的setInitialState()方法,继续往下走
走到这里**setTaskFromIntentActivity(reusedActivity)**其实这里也是走上面deliverNewIntentLocked()方法,主要是也是启动SINGLE_TOP的Activity。
然后看到后面的注释,就是说明后面的操作就是将Activity放到栈顶。
暂停(pause)上一个Activity
然后继续往下面看
class ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity, boolean restrictedBgActivity) {
....
mTargetStack.mLastPausedActivity = null;
mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
false /* forceSend */, mStartActivity);
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
....
}
先看这里mLastPausedActivity这个属性其实就是上一Activity,在开启一个新的Activity的时候先将上一个Activity Pause掉,然后再执行将新的Activity
那么下面这几步就是走的将上一个Activity pause掉
先看startActivityLocked()方法
class ActivityStarter
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options){
....
if (r.mLaunchTaskBehind) {
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
r.setVisibility(true);
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
...
}
直接看 ensureActivitiesVisibleLocked()方法
class ActivityStack
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
true /* notifyClients */);
}
/**
* Ensure visibility with an option to also update the configuration of visible activities.
* @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
* @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
*/
// TODO: Should be re-worked based on the fact that each task as a stack in most cases.
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows, boolean notifyClients){
....
else if (r.visible) {
// If this activity is already visible, then there is nothing to do here.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Skipping: already visible at " + r);
if (r.mClientVisibilityDeferred && notifyClients) {
r.makeClientVisible();
}
if (r.handleAlreadyVisible()) {
resumeNextActivity = false;
}
//这个必定为true,会走这里
if (notifyClients) {
r.makeActiveIfNeeded(starting);
}
}
}
class ActivityRecord{
/**
* Make activity resumed or paused if needed.
* @param activeActivity an activity that is resumed or just completed pause action.
* We won't change the state of this activity.
*/
//看注释就知道,这个方法是用来resumed或paused Activity的
boolean makeActiveIfNeeded(ActivityRecord activeActivity){
//这个是ResumeActivity,下面那个是PauseActivity,那么现在走哪个呢?其实现在我们是正在生成一个新的Activity
//所以走得是shouldResumeActivity这一个,所以我们看的是resumeTopActivityUncheckedLocked()这个方法
if (shouldResumeActivity(activeActivity)) {
if (DEBUG_VISIBILITY) {
Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
}
return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
null /* options */);
} else if (shouldPauseActivity(activeActivity)) {
if (DEBUG_VISIBILITY) {
Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
}
// An activity must be in the {@link PAUSING} state for the system to validate
// the move to {@link PAUSED}.
setState(PAUSING, "makeVisibleIfNeeded");
try {
//看到下面熟悉吗?这不就是LifeCycle吗,当Activity的的pause就会通过下面来发送
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
PauseActivityItem.obtain(finishing, false /* userLeaving */,
configChangeFlags, false /* dontReport */));
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
}
}
return false;
}
}
class ActivityStack
/**
* Ensure that the top activity in the stack is resumed.
*
* @param prev The previously resumed activity, for when in the process
* of pausing; can be null to call from elsewhere.
* @param options Activity options.
*
* @return Returns true if something is being resumed, or false if
* nothing happened.
*
* NOTE: It is not safe to call this method directly as it can cause an activity in a
* non-focused stack to be resumed.
* Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the
* right activity for the current system state.
*/
@GuardedBy("mService")
//先看一眼注解 确保栈的顶层是Activity是resumed,
//关注一下这一个prev参数
//注释是:上一个resumed Activity 用于pasusing,也就是说会停掉上一个Activity,使其进入pause阶段
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
//先看这个方法,因为用到了prev
result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
}
先看一下这个方法resumeTopActivityInnerLocked(prev, options);
class ActivityStack
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){
....
boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
.....
}
重点在这个方法startPausingLocked()
class ActivityStack
/**
* Start pausing the currently resumed activity. It is an error to call this if there
* is already an activity being paused or there is no resumed activity.
*
* @param userLeaving True if this should result in an onUserLeaving to the current activity.
* @param uiSleeping True if this is happening with the user interface going to sleep (the
* screen turning off).
* @param resuming The activity we are currently trying to resume or null if this is not being
* called as part of resuming the top activity, so we shouldn't try to instigate
* a resume here if not null.
* @param pauseImmediately True if the caller does not want to wait for the activity callback to
* complete pausing.
* @return Returns true if an activity now is in the PAUSING state, and we are waiting for
* it to tell us when it is done.
*/
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately){
...
ActivityRecord prev = mResumedActivity;
....
//将mLastPausedActivity 设置为 prev 为什么提这点,不知道你是否还记得上面的startActivityUnchecked()方法中的
//mTargetStack.mLastPausedActivity = null; 就是在这里赋值的
mPausingActivity = prev;
mLastPausedActivity = prev;
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.setState(PAUSING, "startPausingLocked");
prev.getTaskRecord().touchActiveTime();
clearLaunchTime(prev);
mService.updateCpuStats();
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
//看到这里了吗?是不是很熟悉,和上面一样,也是停止这一个prev Activity,让其进入Pause阶段
mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
}
....
}
第二次跨进程通信
那么再让我们看一下具体的执行是怎么样,先看这个PauseActivityItem.obtain()
public class PauseActivityItem extends ActivityLifecycleItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
"PAUSE_ACTIVITY_ITEM");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
if (mDontReport) {
return;
}
try {
// TODO(lifecycler): Use interface callback instead of AMS.
ActivityManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/** Obtain an instance initialized with default params. */
public static PauseActivityItem obtain() {
PauseActivityItem instance = ObjectPool.obtain(PauseActivityItem.class);
if (instance == null) {
instance = new PauseActivityItem();
}
instance.mFinished = false;
instance.mUserLeaving = false;
instance.mConfigChanges = 0;
instance.mDontReport = true;
return instance;
}
}
最先调用一个obtain返回的是一个instance,而这个instance就是PauseActivityItem,并且是通过ObjectPool.obtain(PauseActivityItem.class);这个方法来获取的,就是获取到了一个线程池,那么最后无非就是调用他的
execute()或postExecute()方法,在无论是execute()或是postExecute()方法中涉及到了跨进程操作,这里的postExecute()涉及AMS,而execute()中的token是一个IBinder。不知道你是否还记得,在一开始的请求Activity创建的操作中就涉及到了跨进程操作,从当
前进程->AMS进程,现在由AMS回到了当期进程,其中过程我就不赘述了。
最后走的是ActivityThread的handlePauseActivity()方法
最终暂停Activity处
class ActivityThread
@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
//点进这个方法
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
}
final Bundle performPauseActivity(IBinder token, boolean finished, String reason,
PendingTransactionActions pendingActions) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, reason, pendingActions) : null;
}
/**
* Pause the activity.
* @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
*/
//从注释中知道了是用于暂停activity
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
PendingTransactionActions pendingActions) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
RuntimeException e = new RuntimeException(
"Performing pause of activity that is not resumed: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
}
if (finished) {
r.activity.mFinished = true;
}
// Pre-Honeycomb apps always save their state before pausing
final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
if (shouldSaveState) {
callActivityOnSaveInstanceState(r);
}
//暂停Activity在这个方法 点进去看
performPauseActivityIfNeeded(r, reason);
// Notify any outstanding on paused listeners
ArrayList<OnActivityPausedListener> listeners;
synchronized (mOnPauseListeners) {
listeners = mOnPauseListeners.remove(r.activity);
}
int size = (listeners != null ? listeners.size() : 0);
for (int i = 0; i < size; i++) {
listeners.get(i).onPaused(r.activity);
}
//保存Activity的状态
final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
if (oldState != null) {
// We need to keep around the original state, in case we need to be created again.
// But we only do this for pre-Honeycomb apps, which always save their state when
// pausing, so we can not have them save their state when restarting from a paused
// state. For HC and later, we want to (and can) let the state be saved as the
// normal part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
return shouldSaveState ? r.state : null;
}
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
if (r.paused) {
// You are already paused silly...
return;
}
try {
r.activity.mCalled = false;
//再看这个mInstrumentation.callActivityOnPause()方法
mInstrumentation.callActivityOnPause(r.activity);
if (!r.activity.mCalled) {
throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
+ " did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to pause activity "
+ safeToComponentShortString(r.intent) + ": " + e.toString(), e);
}
}
//设置Activity的状态为ON_PAUSE
r.setState(ON_PAUSE);
}
看一下这个方法mInstrumentation.callActivityOnPause(r.activity)
class Instrumentation
/**
* Perform calling of an activity's {@link Activity#onPause} method. The
* default implementation simply calls through to that method.
*
* @param activity The activity being paused.
*/
public void callActivityOnPause(Activity activity) {
activity.performPause();
}
这个就是调用Activity的preformPause()方法,其实这里不仅是只有pause()方法还有很多关于Activity的生命周期相关的方法,如callActivityOnStart(),callActivityOnRestart()等等
好继续往下面看
class Activity
final void performPause() {
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
onPause();
writeEventLog(LOG_AM_ON_PAUSE_CALLED, "performPause");
mResumed = false;
if (!mCalled && getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.GINGERBREAD) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
}
看到这个onPause()方法了吗,这个就是最终调用Activity的onPause方法
芜湖~~ 终于走完这个方法,我们知道了如何让上一个Activity进入Pause阶段了
大致流程就是下面这样
startActivityUnchecked -> startActivityLocked() -> ensureActivitiesVisibleLocked() -> makeActiveIfNeeded-> resumeTopActivityUnCheckedLocked -> resumeTopActivityInnerLocked -> startPausingLocked -> ActivityThread.handlePauseActivity -> Instrumentation.callActivityOnPause()-> Activity.performPause -> onPause()
初始化(创建)Activity
停止Activity完成后回到ActivityStack.startPausingLocked()方法,继续往下走
class ActivityStack
else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
看这个方法startSpecificActivityLocked()
class ActivityStackSupervisor
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
....
}
走到这个方法中realStartActivityLocked(r, wpc, andResume, checkConfig)
这一步绝对难以想象,跨度之地大吓死人,一步一步来(在这里我打个预防针,过程我会贴出来的,也可以不看,直接看结果,有兴趣的可以看一下是怎么找出来的)
class ActivityStackSupervisor
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException{
...
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
}
多余的不看,直接看这里,直取黄龙。一行一行来看, 首先是这里
final ClientTransaction clientTransaction = ClientTransaction.obtain( proc.getThread(), r.appToken);
第一步:先搞懂这个 proc.getThread(),这个其实是ActivityThread
第二步:clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),...)
这里为clientTransaction添加了一个callback
第三步:clientTransaction.setLifecycleStateRequest(lifecycleItem)
这里的lifecycleItem是ResumeActivityItem.obtain()
第四步: mService.getLifecycleManager().scheduleTransaction(clientTransaction),这个是最麻烦的,直接看
class ClientLifecycleManager
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
到了这里直接人晕掉,全部都是红色的只能一点一点来
先来transaction.schedule()
class ClientTransaction
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
if (instance == null) {
instance = new ClientTransaction();
}
instance.mClient = client;
instance.mActivityToken = activityToken;
return instance;
}
mClient是什么鬼?看到里面这个obtain方法了吗,mClient就是IApplicationThread,也就是ActivityThread
看ActivityThread.scheduleTransaction(this)方法
class ActivityThread extends ClientTransactionHandler
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
第一次看是懵逼的这个是什么鬼?自己调自己?无限循环?后面发现调用的是ActivityThread的父类里面的scheduleTransaction()的方法
也就是ClientTransactionHandler.scheduleTransaction()方法
class ClientTransactionHandler
// Schedule phase related logic and handlers.
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
走的就是这个sendMessage()方法,直接看吧其实就是一个Handle处理,看他怎么处理
回到了ActivityThread类
class ActivityThread
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
mTransactionExecutor这个又是什么鬼啊?只能找了他是一个TransactionExecutor类直接看他的execute()方法
class TransactionExecutor
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
log("End resolving transaction");
}
/** Cycle through all states requested by callbacks and execute them at proper times. */
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null) {
// No callbacks to execute, return early.
return;
}
log("Resolving callbacks");
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
// In case when post-execution state of the last callback matches the final state requested
// for the activity in this transaction, we won't do the last transition here and do it when
// moving to final state instead (because it may contain additional parameters from server).
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
: UNDEFINED;
// Index of the last callback that requests some post-execution state.
final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
log("Resolving callback: " + item);
final int postExecutionState = item.getPostExecutionState();
final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
item.getPostExecutionState());
if (closestPreExecutionState != UNDEFINED) {
cycleToPath(r, closestPreExecutionState);
}
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
if (r == null) {
// Launch activity request will create an activity record.
r = mTransactionHandler.getActivityClient(token);
}
if (postExecutionState != UNDEFINED && r != null) {
// Skip the very last transition and perform it by explicit state request instead.
final boolean shouldExcludeLastTransition =
i == lastCallbackRequestingState && finalState == postExecutionState;
cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
}
}
}
两个重点方法
final ClientTransactionItem item = callbacks.get(i);
item.execute(mTransactionHandler, token, mPendingActions);
不知道你是否还记得上面ActivityStackSupervisor.realStartActivityLocked()方法中的四步的第二步,我再把代码贴出来
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
这里的item就是这个LaunchActivityItem.obtain(),调用他的execute()方法
class LaunchActivityItem
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
这里的**client.handleLaunchActivity(r, pendingActions, null /* customIntent /)*
这里有个细节就是token就是一个IBinder,这里又出现了跨进程通信(其实在这里我们知道了Activity就交由AMS来管理的,凡是需要用到Activity的信息,都需要到AMS中获取)
Activity的创建
调用的就是ActivityThread.handleLaunchActivity方法
class ActivityThread
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
if (!ThreadedRenderer.sRendererDisabled) {
GraphicsEnvironment.earlyInitEGL();
}
WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
看到这行了吗? final Activity a = performLaunchActivity(r, customIntent),这个就是最终的Activity的创建。
进去看
class ActivityThread
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
....
//context的实现在这里
ContextImpl appContext = createBaseContextForActivity(r);
....
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
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, window, r.configCallback,
r.assistToken);
...
}
class Instrumentation
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
class AppComponentFactory
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
通过**(Activity) cl.loadClass(className).newInstance()**来创建Activity
不知道你是否还注意到这行代码ContextImpl appContext = createBaseContextForActivity(r);
这个appContext就是Context,Context的创建就在这里,并通过**activity.attach()**将Activity的属性绑定进去,
最终我们知道是通过反射来生成Activity的,
继续看performLaunchActivity()方法
class ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
....
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
....
}
class Instrumentation
/**
* Perform calling of an activity's {@link Activity#onCreate}
* method. The default implementation simply calls through to that method.
* @param activity The activity being created.
* @param icicle The previously frozen state (or null) to pass through to
* @param persistentState The previously persisted state (or null)
*/
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
//直接看这个方法
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
class Activity
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
restoreHasCurrentPermissionRequest(icicle);
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
mActivityTransitionState.readState(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
dispatchActivityPostCreated(icicle);
}
最终这里调用了Activity的onCreate()方法
阶段总结
创建Activity到目前阶段的总结:首先是先通过本进程的startActivity的过程,然后通过跨进程通信需要用到AMS来进行具体操作,然后先判断这个Activity是否需要用到开新的栈,如果需要就放到最顶部的栈,并用window来显示,如果是这里是不需要用到新的栈的情况下,那么就是放到现有栈的顶部(注意:这里讨论的不是创建第一个Activity,而是在原有Activity的情况下创建新的Activity,并放入到同一个Activit栈中。如果是第一个Activity就到这里,没有暂停上一个Activity的操作),先将栈中现有最顶部的Activity取出来(新的Activity还没有添加上去),然后也是通过跨进程通信,通知现在本地进程将顶部Activity进入onPause阶段。所以现在是经历了两次跨进程通信,一次是本进程 -> AMS创建新的Activity栈(也可以不创建),本质是取出最新的Activity栈 -> 本进程将顶层的Activity进入onPause状态。然后通过反射来创建一个Activity,然后创建context等属性,通过attach()方法传入给Activity,并且最终调用Activity的onCreate方法
好了就总结到这里。
使用Hook绕开AndroidManifest检查
既然上面研究了那么久的源码,总要发挥点作用,这里我将借助Hook来实现绕开AndroidManifest的检查。
这里使用的源码是Android 10.0。
情景说明
我们常常跳转Activity的时候,都需要到AndroidManifest中注册Activity才能够跳转过去。那么能不能不注册Activity就打开Activity呢?
其实是可以的,这里我将实现这个方法。
解决思路
首先我们需要知道AndroidManifest中注册的信息是与Intent相关的,那么我们先注册一个存在的Activity先。
当我们需要跳转到一个没有注册的Activity的时候,通过hook获取到这个OIntent(Original),然后创建一个SafeIntent(这个Intent是跳转到存在的Activity的),那么这样就能通过AndroidManifest的检查,然后根据上面的源码知道了Activity的创建过程是需要用到一个Handler的,那么我们就hook这个Handler,拿到这个Handler,然后将里面的新Intent取出来,将OIntent放回去这样就可以了。
代码
首先说明一个已经注册了的Activity --- RegisterHookActivity
将要跳转的一个未注册的Activity --- TestHookActivity
(注意这个Activity是继承Activity的,而不是AppCompatActivity,某些版本会出问题,原因是AppCompatActivity
在Navutils.getParentActivityName()中,在这里它会再一次检查ActivityInfo info = pm.getActivityInfo(componentName, flags),然后抛出NameNotFoundException异常。
这里的pm就是PackageManager pm = context.getPackageManager();
而在ActivityThread.getPackageManager()中,,
第一次走这个方法时sPackageManager不存在,他需要创建一个新的出来,所以导致问题的产生。每一次都是一个新的PackageManager
但是我在10.0测试时不存在这个问题,会不会出现问题到Navutils.getParentActivityName()中查看一下源码就知道了。
当然现在有很多这种绕过AndroidManifest检查的开源库,帮你弄好了各个版本的问题,你也可以选择这些,这里我只是用作测试我的源码观看成果。
替换Intent
这里我们需要替换的Intent的代码
class HookStartActivityUtils
public void hookStartActivity() throws Exception {
//获取ActivityTaskManager中的IActivityTaskManagerSingleton
//因为ActivityTaskManager是hider的所有需要使用反射来获取
// ActivityTaskManager
Class<?> activityTaskManagerClass = Class.forName("android.app.ActivityTaskManager");
//获取属性 IActivityTaskManagerSingleton
Field iActivityTaskManagerSingleton = activityTaskManagerClass.getDeclaredField("IActivityTaskManagerSingleton");
//设置权限
iActivityTaskManagerSingleton.setAccessible(true);
//这里get(null)的原因是这个属性是静态的,可以直接获取,不需要要指明是那个对象
Object singleton = iActivityTaskManagerSingleton.get(null);
//获取singleton里面的mInstance属性
Class<?> singletonClass = Class.forName("android.util.Singleton");
Field mInstance = singletonClass.getDeclaredField("mInstance");
mInstance.setAccessible(true);
//这里的mInstance属性就不是静态的,所以就要指明是那个对象的属性,
//这个对象就是singleton
Object iamInstance = mInstance.get(singleton);
//int result = ActivityTaskManager.getService()
// .startActivity(whoThread, who.getBasePackageName(), intent,
// intent.resolveTypeIfNeeded(who.getContentResolver()),
// token, target != null ? target.mEmbeddedID : null,
// requestCode, 0, null, options);
//经过上面的步骤我们终于获取到了ActivityTaskManager.getService()的具体对象了,现在这个对象就是iamInstance
//下面是动态代理iamInstance的startActivity()方法
//拿到需要我们代理的类
Class<?> iamClass = Class.forName("android.app.IActivityTaskManager");
Method[] declaredMethods = iamClass.getDeclaredMethods();
//for (Method declaredMethod : declaredMethods) {
// Log.d(TAG, declaredMethod.getName());
//}
iamInstance = Proxy.newProxyInstance(HookStartActivityUtils.class.getClassLoader(),
new Class[]{iamClass},
//InvocationHandle必须执行者
new StartActivityInvocationHandler(iamInstance));
// 重新指定mInstance里面的对象,重新指明singleton属性的值为新的iamInstance
mInstance.set(singleton, iamInstance);
//这样我们就能通过动态代理拿到startActivity()方法了
}
private class StartActivityInvocationHandler implements InvocationHandler {
//方法执行者
private Object mObject;
public StartActivityInvocationHandler(Object object) {
this.mObject = object;
}
//现在关于ActivityTaskManagerService的方法都能hook到,执行对象为iamInstance
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d(TAG, method.getName());
if (method.getName().equals("startActivity")) {
//原来的Intent先取出来
Intent originalIntent = (Intent) args[2];
//AndroidManifest中注册的信息时放入到Intent中,这里换成一个注册过的Activity放入到,
//这样就能通过检查,后面在创建Activity的时候,在hook 放入一个这个Activit
//创建一个注册了的Activity的Intent
Intent safeIntent = new Intent(mContext, mProxyClass);
//将这个Intent传进去
args[2] = safeIntent;
//将原本的Intent放进去
safeIntent.putExtra(EXTRA_ORIGIN_INTENT, originalIntent);
}
return method.invoke(mObject, args);
}
}
根据上面源码分析,我们知道了Activity的启动过程,这里我先通过动态代理的方法来代理android.app.IActivityTaskManager这个类,每次执行这个类里面的方法都会走我们这个代理方法,然后我们找到startActivity这个方法,在上面的源码分析我们知道了Intent的操作在这个方法里面,那么我们就在这个方法里面进行替换Intent,并将原来的Intent与新的Intent进行绑定。
可能有部分的人不清楚反射,这里我介绍一点用下面这个举例子
//这个是我们需要获取Singleton类,通过反射获取
Class<?> singletonClass = Class.forName("android.util.Singleton");
//获取Singleton类里面的mInstance属性
Field mInstanceField = singletonClass.getDeclaredField("mInstance");
//当我们想获取或改变属性的值的时候需要我们通过setAccessible(true),才能访问这个属性
mInstanceField.setAccessible(true);
//然后这里我们需要获取mInstanceField属性里面的值,这里我们需要指定获取是哪一个对象里面mInstance的值
//所以在get()方法中需要填入一个singleton,这个singleton就是一个对象。
Object iamInstance = mInstanceField.get(singleton);
换回原来的Intent
根据上面的源码分析,我们知道了Activity的 启动过程,其中是涉及到了一个Handler,那么这里我们就从这个Handler来入手
我们创建一个Handler,来替换原来的Handler,并且在处理的途中更换回原来的Intent
class HookStartActivityUtils
public void hookLaunchActivity() throws Exception {
// 获取ActivityThread实例
Class<?> atClass = Class.forName("android.app.ActivityThread");
Field scatField = atClass.getDeclaredField("sCurrentActivityThread");
scatField.setAccessible(true);
Object sCurrentActivityThread = scatField.get(null);
// 获取ActivityThread中的mH
Field mHField = atClass.getDeclaredField("mH");
mHField.setAccessible(true);
Object mHandler = mHField.get(sCurrentActivityThread);
// hook LaunchActivity
//给Handler设置callBack回调,也只能通过反射
Class<?> handlerClass = Class.forName("android.os.Handler");
Field mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField.setAccessible(true);
//将里面的Handler更换成我们的那个,这样就能在创建Activity的时候发送message就由
//我们这个Handler来处理
mCallbackField.set(mHandler, new HandlerCallback());
}
private class HandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(@NonNull Message msg) {
//没发一个消息就会走一次这个CallBack,在源码中我们知道了
//EXECUTE_TRANSACTION = 159
if (msg.what == 159) {
//现在我们需要替换Intent
handlerLaunchActivity(msg);
}
return false;
}
/**
* 开启启动Activity拦截
*
* @param msg
*/
private void handlerLaunchActivity(Message msg) {
Log.d(TAG,"收到handle");
//根据Activity的启动源码,我们先去找到Intent的所在位置
//获取List<ClientTransactionItem> mActivityCallbacks对象
Class<?> clientTransactionItemClass = msg.obj.getClass();
Field activityCallbacksField = null;
try {
activityCallbacksField = clientTransactionItemClass.getDeclaredField("mActivityCallbacks");
activityCallbacksField.setAccessible(true);
List mActivityCallbacks = (List) activityCallbacksField.get(msg.obj);
for (int i = 0; i < mActivityCallbacks.size(); i++) {
if (mActivityCallbacks.get(i).getClass().getName()
.equals("android.app.servertransaction.LaunchActivityItem")) {
//获取LaunchActivityItem
Object launchActivityItem = mActivityCallbacks.get(i);
Class<?> launchActivityItemClass = launchActivityItem.getClass();
Field mIntentField = launchActivityItemClass.getDeclaredField("mIntent");
mIntentField.setAccessible(true);
//先取出来原本的Intent
Intent safeIntent = (Intent) mIntentField.get(launchActivityItem);
Intent originalIntent = safeIntent.getParcelableExtra(EXTRA_ORIGIN_INTENT);
//更换intent
if (originalIntent != null) {
mIntentField.set(launchActivityItem,originalIntent);
//safeIntent.setComponent(originalIntent.getComponent());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个就是大致过程。
完整代码
public class HookStartActivityUtils {
private static final String TAG = "HookStartActivityUtils";
private Context mContext;
private Class<?> mProxyClass;
private final String EXTRA_ORIGIN_INTENT = "EXTRA_ORIGIN_INTENT";
public HookStartActivityUtils(Context context, Class<?> proxyClass) {
this.mContext = context.getApplicationContext();
this.mProxyClass = proxyClass;
}
public void hookLaunchActivity() throws Exception {
// 获取ActivityThread实例
Class<?> atClass = Class.forName("android.app.ActivityThread");
Field scatField = atClass.getDeclaredField("sCurrentActivityThread");
scatField.setAccessible(true);
Object sCurrentActivityThread = scatField.get(null);
// 获取ActivityThread中的mH
Field mHField = atClass.getDeclaredField("mH");
mHField.setAccessible(true);
Object mHandler = mHField.get(sCurrentActivityThread);
// hook LaunchActivity
//给Handler设置callBack回调,也只能通过反射
Class<?> handlerClass = Class.forName("android.os.Handler");
Field mCallbackField = handlerClass.getDeclaredField("mCallback");
mCallbackField.setAccessible(true);
//将里面的Handler更换成我们的那个,这样就能在创建Activity的时候发送message就由
//我们这个Handler来处理
mCallbackField.set(mHandler, new HandlerCallback());
}
private class HandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(@NonNull Message msg) {
//没发一个消息就会走一次这个CallBack,在源码中我们知道了
//EXECUTE_TRANSACTION = 159
if (msg.what == 159) {
//现在我们需要替换Intent
handlerLaunchActivity(msg);
}
return false;
}
/**
* 开启启动Activity拦截
*
* @param msg
*/
private void handlerLaunchActivity(Message msg) {
Log.d(TAG,"收到handle");
//根据Activity的启动源码,我们先去找到Intent的所在位置
//获取List<ClientTransactionItem> mActivityCallbacks对象
Class<?> clientTransactionItemClass = msg.obj.getClass();
Field activityCallbacksField = null;
try {
activityCallbacksField = clientTransactionItemClass.getDeclaredField("mActivityCallbacks");
activityCallbacksField.setAccessible(true);
List mActivityCallbacks = (List) activityCallbacksField.get(msg.obj);
for (int i = 0; i < mActivityCallbacks.size(); i++) {
if (mActivityCallbacks.get(i).getClass().getName()
.equals("android.app.servertransaction.LaunchActivityItem")) {
//获取LaunchActivityItem
Object launchActivityItem = mActivityCallbacks.get(i);
Class<?> launchActivityItemClass = launchActivityItem.getClass();
Field mIntentField = launchActivityItemClass.getDeclaredField("mIntent");
mIntentField.setAccessible(true);
//先取出来原本的Intent
Intent safeIntent = (Intent) mIntentField.get(launchActivityItem);
Intent originalIntent = safeIntent.getParcelableExtra(EXTRA_ORIGIN_INTENT);
//更换intent
if (originalIntent != null) {
mIntentField.set(launchActivityItem,originalIntent);
//safeIntent.setComponent(originalIntent.getComponent());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void hookStartActivity() throws Exception {
//获取ActivityTaskManager中的IActivityTaskManagerSingleton
//因为ActivityTaskManager是hider的所有需要使用反射来获取
// ActivityTaskManager
Class<?> activityTaskManagerClass = Class.forName("android.app.ActivityTaskManager");
//获取属性 IActivityTaskManagerSingleton
Field iActivityTaskManagerSingleton = activityTaskManagerClass.getDeclaredField("IActivityTaskManagerSingleton");
//设置权限
iActivityTaskManagerSingleton.setAccessible(true);
//这里get(null)的原因是这个属性是静态的,可以直接获取,不需要要指明是那个对象
Object singleton = iActivityTaskManagerSingleton.get(null);
//获取singleton里面的mInstance属性
Class<?> singletonClass = Class.forName("android.util.Singleton");
Field mInstance = singletonClass.getDeclaredField("mInstance");
mInstance.setAccessible(true);
//这里的mInstance属性就不是静态的,所以就要指明是那个对象的属性,
//这个对象就是singleton
Object iamInstance = mInstance.get(singleton);
//int result = ActivityTaskManager.getService()
// .startActivity(whoThread, who.getBasePackageName(), intent,
// intent.resolveTypeIfNeeded(who.getContentResolver()),
// token, target != null ? target.mEmbeddedID : null,
// requestCode, 0, null, options);
//经过上面的步骤我们终于获取到了ActivityTaskManager.getService()的具体对象了,现在这个对象就是iamInstance
//下面是动态代理iamInstance的startActivity()方法
//拿到需要我们代理的类
Class<?> iamClass = Class.forName("android.app.IActivityTaskManager");
Method[] declaredMethods = iamClass.getDeclaredMethods();
iamInstance = Proxy.newProxyInstance(HookStartActivityUtils.class.getClassLoader(),
new Class[]{iamClass},
//InvocationHandle必须执行者
new StartActivityInvocationHandler(iamInstance));
// 重新指定mInstance里面的对象,重新指明singleton属性的值为新的iamInstance
mInstance.set(singleton, iamInstance);
//这样我们就能通过动态代理拿到startActivity()方法了
}
private class StartActivityInvocationHandler implements InvocationHandler {
//方法执行者
private Object mObject;
public StartActivityInvocationHandler(Object object) {
this.mObject = object;
}
//现在关于ActivityTaskManagerService的方法都能hook到,执行对象为iamInstance
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d(TAG, method.getName());
if (method.getName().equals("startActivity")) {
//原来的Intent先取出来
Intent originalIntent = (Intent) args[2];
//AndroidManifest中注册的信息时放入到Intent中,这里换成一个注册过的Activity放入到,
//这样就能通过检查,后面在创建Activity的时候,在hook 放入一个这个Activit
//创建一个注册了的Activity的Intent
Intent safeIntent = new Intent(mContext, mProxyClass);
//将这个Intent传进去
args[2] = safeIntent;
//将原本的Intent放进去
safeIntent.putExtra(EXTRA_ORIGIN_INTENT, originalIntent);
}
return method.invoke(mObject, args);
}
}
}
使用
public class TestActivity extends BaseActivity {
private Button mButton;
@Override
protected void initData() {
}
@Override
protected void initView() {
//hook Activity的工具
HookStartActivityUtils utils = new HookStartActivityUtils(this, RegisterHookActivity.class);
try {
utils.hookStartActivity();
utils.hookLaunchActivity();
} catch (Exception e) {
e.printStackTrace();
}
mButton = findViewById(R.id.onclick);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(TestActivity.this, TestHookActivity.class);
startActivity(intent);
}
});
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_test);
}
}
总结
查看源码后我们就能通过Hook来实现Activity绕过AndroidManifest检查,而这只是其中的冰山一角,还有很多细节我是没有点进去看的,但就这一块都弄的我头昏眼花,如果熟悉源码的话你就能做出很多操作,通过Hook来实现很多骚操作。
这次的文章真的是鸿篇巨制,求个点赞没问题吧!!!!