framework
ActivityStarter
1,计算启动模式
2,计算启动参数
3,生成ActivityRecord
Flag
A -> B ->C ,A要拿C的返回结果,只需要在A启动B的使用startActivityForResult,B启动C的时候用startActivity,并加上flag= Intent.FLAG_ACTIVITY_FORWARD_RESULT 即可
taskAffinity
设置android:taskAffinity可以吧act启动到别的栈里,但是必须配合new_task 标志位
有几个任务栈,home以后再按menu就会有几个窗口
NEW_TASK
假设有app ,a 和 b, a默认界面a1,b默认界面b1,有界面b2在后面
1,a1 -> b2 ,可以直接启动b2,俩个会在一个栈里
2, a1 -> b2 NEW_TASK,b2会在自己包名的栈里
3,情况1 home返回桌面,点击b,会启动b1;
情况2 home返货桌面,点击b,他判断栈里有东西了,直接展示栈顶,也就是b2
4,singleInstance 单独占一个任务栈
ActivityRecord
记录,task信息taskAffinity,applicationInfo,userId,processName,packageName,launchModel,ActivityState,launchmodel
ActivityState
枚举类型

Activity HOOK流程
这快我们先从思路上分析,我们有一个proxyAct,注册过的,有个bAct,没注册过的
当我们启动b 时,经过activityManagerService检测就会报错,所以分两步,
1,我们要在系统检测前把我们的bAct替换为proxyAct 给系统检测,
2,在系统检测完以后再替换回来,让系统走bAct的生命周期
1.1找到提交检测的代码,在他之前修改intent 地方在
Instrumentation -> execStartActivity
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
1.2 替换intent
ActivityTaskManager.getService()
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
IActivityTaskManagerSingleton.get() 就是获取 IActivityTaskManager的单例模式
1.2 动态代理
动态替换IActivityTaskManager ,具体就是拿出Singleton的变量instance并替换
如果是startActivity,我们就拿出参数里的intent A,生成新的指向proxyAct的intent B,然后把A作为一个参数放入B里
如果不是startActivity,我们就还是走原来instance的方法
2.1 找到还原intent的事件点
系统检测完以后会走回activityThread
会优先走到handler的EXECUTE_TRANSACTION 事件
我们复写handler callback方法,返回false,保证执行原handlerMessage流程
并判断如果是EXECUTE_TRANSACTION 事件,则拿出intent进行替换
2.2 找到intent
其中obj就是ClientTransaction 里面包含了List<ClientTransactionItem> mActivityCallbacks
ClientTransactionItem的是实现是LaunchActivityItem
LaunchActivityItem
public class LaunchActivityItem extends ClientTransactionItem {
@UnsupportedAppUsage
private Intent mIntent;
....
}
2.3 替换intent
根据tag拿出intent b ,反射替换即可
线程
解决ABA问题
AtomicStampedReference reference
reference.set(newValue,reference.getStamp()+1)
Stamp 就是类似版本号
suspend
suspend 与resume相对, 会挂起,不会释放锁,因此被弃用,不如wait -> notify
线程状态
new ,run,block(阻塞sync),wait(等待), timeout(waittimeout) ,over
个人看法,block和wait的区别,就是会不会释放锁,如sync, sleep,yield,不会释放锁就属于阻塞,io也属于阻塞,wait属于等待
join
join 调用的wait(0),会释放锁,但是释放的是lock这个对象,对外部sync没关系
public final void join(long millis) throws InterruptedException {
synchronized(lock) {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
lock.wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
lock.wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
}
FutureTask
ft继承自runable ,可以接受callable,runnable,callable返回值回调,futureTask.get()可以获取运行结果
线程池
shutdown 当前任务和队列任务执行完以后关闭当前线程池,shutdown以后再添加任务会执行拒绝策略
shutdownNow 会执行interrupt() 方法,但是如果没有sleep,wait是打断不了的,还是会执行完当前任务再结束,同时队列的任务不会再执行,并以列表的形式返回
awaitTermination 就是持有mainLock一段时间,也就是你调用线程池的一部分方法都会因为获取不到mainLock 而阻塞
http
断点续传
客户端头里上传 Range:bytes=512000-
RandomAccessFile 通过 seek(int i) 方法,文件头就会由0变成i
JVM
本地方法栈
和虚拟机栈差不多,没有gc,线程私有,也会栈溢出