学习日记-2022-02-22

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

枚举类型


activitystate.jpg

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,线程私有,也会栈溢出

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容