Git Product home page Git Product logo

tom-notes's People

Contributors

tomgarden avatar

Watchers

 avatar

tom-notes's Issues

list.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

对应的流程图在 方法小计/调用栈/

从 DexClassLoader 加载 DEX 来看 DEX 文件的处理过程。

DexClassLoader

从 application 的启动过程来看 DEX 的使用过程。

app_run

  1. 我们要了解 DexHunter 的源码细节
  2. 通过阅读其文档我们知道该项目做的事情是修改 Android 系统源码The modification is mainly in "art/runtime/class_linker.cc" (ART) and "dalvik/vm/native/dalvik_system_DexFile.cpp" (DVM).
  3. 并将系统重新编译,让被加固的应用运行在修改后的系统,就会把加固了的内容取出来。
  4. 当然还有很多细节,暂不表。
  5. 所以我们需要从 application 的启动过程来了解 DexHunter 所做的事情是什么。

《Android 源代码情景分析》第十二章:

Activity 管理服务器 ActivityManagerService 再启动一个应用程序组件时(假设启动的就是我们想要启动的应用的 MAIN Activity),如果发现所需要的的应用程序进程还没有启动起来,他就会请求 Zygote 进程将这个应用程序进程启动起来。

Zyegote 进程通过复制自身的方式来创建一个新的应用程序进程。

应用程序启动过程中,除了可以获得一个虚拟机实例外,还可以获得一个 Binder 线程池和一个消息循环,这样,运行在它里面的应用程序组件就可以方便的使用 Android 系统的消息处理机制,以及 Binder 进程间通信机制来实现自己的业务逻辑。

在上述过程中我们关心的内容是: 创建新进程的过程中,DEX 是如何被操作的,系统正常操作 DEX 的过程和 DexHunter 操作 DEX 过程的异同。

《Android 源代码情景分析》第七章:

根 Activity 以快捷图标的形式显示在应用程序启动器中,它的启动过程就代表了一个 Android 应用程序的启动过程。子 Activity 由根 Activity 或其他子 Activiyt 启动。它们有可能与启动它们的 Activiyt 运行在同一个进程中,也有可能运行在不的进程中,这取决于它们的启动参数的配置。

我们从 Launcher.startActivitySafely 开始这一流程:当我们在 应用程序启动器 Launcher 的界面上点击一个应用程序的快捷图标时,Launcher 组件的成员函数 startActivitySafely 就会被调用来启动这个应用程序的根 Activity,其中要启动的根 Activity 信息包含在 intent 中。


我是页脚

修改默认路径配置.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

无差别抄录:http://blog.csdn.net/yiyiyf/article/details/52693800

1 .AndroidStudio是android studio的配置文件夹

进入Android Studio的安装目录,进入bin文件夹,用文本编辑软件打开idea.properties,去掉以下两项的注释符号#,修改对应的路径为新路径即可。

#---------------------------------------------------------------------
# Uncomment this option if you want to customize path to IDE config folder. Make sure you're using forward slashes.
#---------------------------------------------------------------------
# idea.config.path=${user.home}/.AndroidStudio/config
idea.config.path=D:/.AndroidStudio/config


#---------------------------------------------------------------------
# Uncomment this option if you want to customize path to IDE system folder. Make sure you're using forward slashes.
#---------------------------------------------------------------------
# idea.system.path=${user.home}/.AndroidStudio/system
idea.system.path=D:/.AndroidStudio/system

2 .gradle是构建工具

Gradle的配置文件夹

在Android Studio的配置选项中修改

Setting>>Build,Execution,Deployment>>Gradle>>Service directory path

3 .android文件夹的修改

这个文件夹是由Android SDK配置模拟器生成的,也是最占空间的一个。
首先,需要添加一个系统的环境变量ANDROID_SDK_HOME ,

变量名其实有些误导人,这个如果Google官方定义成AVD_HOME可能还好一些,其实应该是模拟器的默认路径。添加好环境变量后到新的路径下修改下相应的.ini文件内的路径信息,然后重启系统生效。

参考

  1. Android Studio配置文件路径修改
  2. https://developer.android.com/studio/command-line/variables

我是页脚

ASO预研.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x00. ASO

ASO是“应用商店优化”的简称。ASO(App store Optimization)就是提升你APP在各类APP应用商店/市场排行榜和搜索结果排名的过程。类似普通网站针对搜索引擎的优化,即SEO(Search Engine Optimization)优化。ASO优化就是利用App Store的搜索规则和排名规则让APP更容易被用户搜索或看到。

0x01. 经验

  1. https://www.niaogebiji.com/article-22868-1.html?from=groupmessage&isappinstalled=0
  2. https://www.jianshu.com/p/e3019ae01552
  3. 青瓜传媒-2019 安卓ASO所有推广玩法!

0x03. 排名权重维度

  1. 名称
  2. 关键词
  3. 评论
  4. CPD,竞价排名
  5. 免费活动(首发\加官)
  6. 积分墙

0x04. 初步实施认识

  1. 历年各个应用市场的市场占有率(网络采集)

    • (2018安卓应用商店排行榜Top10)[https://finance.ifeng.com/c/7dLrwKxcTrO]
    • (2019安卓应用市场排行榜Top10)[http://mini.eastday.com/mobile/190422111221870.html]
  2. 根据排名权重逐步完成优化

0x05. 移动增长整体解决方案服务商

  1. 七麦数据_ASO100
    • 注册账号可以观察应用 ASO 相关参数统计
    • 关键词拓展和优化工具可用
  2. 姑婆那些事儿
  3. 酷传
  4. 禅大师
    • 注册账号可以观察应用 ASO 相关参数统计
  5. ASO114_系统正在维护中_

0x06. ASO 实施

操作之前的统计数据_七麦/禅大师_可查

  1. 应用市场覆盖
    • 阿里
    • 历趣
    • 安智

各个Android应用市场的实施维度大体相同,各种维度的权重不同效果各有差异,总体路线

  1. 名称

  2. 关键词

    • 可以通过关键词竞争指数确定关键词
    • 在名称\应用描述\版本更新描述\等位置逐步投放关键词
    • 关键词可以通过七麦数据提供的工具进行扩展和检查关联度
    • 关键词可以通过酷传分析竞争指数
    • 组织最终筛选得到的关键词到句子中
  3. 下载量

  4. 评论

  5. 免费活动(首发\加官)

  6. CPD,竞价排名

  7. 积分墙

0x07. 华为应用市场

7.1. 经验

  1. 如何提高华为小米应用商店的关键词覆盖?

7.2. 关键词解析位置

  1. 应用名称
  2. 应用描述
  3. 一句话介绍
  4. 更新说明
  5. 评论

7.3. 应用市场活动

  1. 首发
  2. 绿色应用(已实施)

我是页脚

2018-08-07-log-1.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html

  • 按照上述链接 修正 .gradle 中的字段即可。
Unable to create Debug Bridge: Unable to start adb server: adb server version (39) doesn't match this client (40); killing...
ADB server didn't ACK
Full server startup log: /tmp/adb.1000.log
Server had pid: 4763
--- adb starting (pid 4763) ---
adb I 08-21 15:47:02  4763  4763 main.cpp:56] Android Debug Bridge version 1.0.40
adb I 08-21 15:47:02  4763  4763 main.cpp:56] Version 4797878
adb I 08-21 15:47:02  4763  4763 main.cpp:56] Installed as /beyourself/DevTool/DevKit/Sdk/platform-tools/adb
'/beyourself/DevTool/DevKit/Sdk/platform-tools/adb start-server' failed -- run manually if necessary

Error: Please select Android SDK

solution : File > Sync Project with Gradle Files


我是页脚

AndroidProfiler.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

剖析应用性能

对 Profiler/trace 有了一定了解 , 它们的标注范围主要集中在视图结构方面的耗时内容

如果想针对线程进行耗时动作划分暂时还不够全面 , 比如主线程中加载布局 和 执行 I/O 操作同时存在的情况下无法分析 I/O 相关操作的细节信息

启动 Android Profile 能力进行追踪

  1. 直接点击 AndroidStudio 图标 Profile 'AppName'
  2. 通过应用插桩生成跟踪日志
    Debug.startMethodTracing("tomyangming.trace")
    //需要仔细分析的代码内容
    Debug.stopMethodTracing()

我是页脚

11章-Zygote和System进程的启动过程.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x00、 Zygote 和 System 进程的启动过程

init 进程 > Zygote > System

  • init 进程为 Linux 系统所启动的第一个进程

0x01、 Zygote进程的启动脚本

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

在 init 进程中

init 进程通过阅读 .rc 脚本文件的方式完成动作

  • Zygote 进程就是它按照 .rc 脚本文件的意图启动的。
  1. 找到 system/core/init.rc 这个脚本文件。
    • 并参阅 AOSP/system/core/init/readme.txt 文件中的 android init language 说明能大致了解脚本文件的意义。
  2. init 进程在启动时会调用 service_start 函数来启动 zygote 进程。

在 init 进程中 fork 了一个新进程,即为 zygote 进程。

在 zygote 进程中 执行 /system/bin/app_process

在 zygote 程中创建了 /dev/socket/zygote 文件,将这个文件路劲和 ANDROID_SOCKET_zyogte 作为 key:value (路径为 value) 加入环境变量中。

在 System 进程的启动过程中

2018-10-16_Android_源代码阅读_流程图_Zygote进程启动流程及细节_Viso_.png

Reference

  • Android系统源代码情景分析(罗升阳)

我是页脚

2018-3-23.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)
* public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent)
* public DexPathList(ClassLoader definingContext, String dexPath, String libraryPath, File optimizedDirectory)
* private static ArrayList splitDexPath(String path)
- private static ArrayList splitPaths(String path1, String path2, boolean wantDirectories)
- private static void splitAndAdd(String searchPath, boolean directoriesOnly, ArrayList resultList)

我们尝试了文本

  • 但是太乱了

又尝试了 UML 时序图

  • 能看到所涉及的类宽度和广度
  • 方法细节关键流程有点顾及不到

我是页脚

Reference.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

官方

  1. Dalvik 可执行文件格式

民间

  1. Android Dex文件格式解析
  2. Android中的Apk的加固(加壳)原理解析和实现
  3. 【精】图解Dex文件结构及解析要点
  4. 通过dexdump来学习DEX文件格式

工具

1-dexdump

  • E:\dev_kit\android_sdk\build-tools\xxx\dexdump.exe
tom@DESKTOP-P2EBEQB MINGW64 /e/dev_kit/android_sdk/build-tools/27.0.3
$ ./dexdump.exe
dexdump: no file specified
Copyright (C) 2007 The Android Open Source Project

dexdump: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...

 -c : verify checksum and exit
 -d : disassemble code sections ---- 
 -f : display summary information from file header
 -h : display file header details
 -i : ignore checksum failures
 -l : output layout, either 'plain' or 'xml'
 -m : dump register maps (and nothing else)
 -t : temp file name (defaults to /sdcard/dex-temp-*)

AOSP路径: I:\AOSP\android-4.4.4_r1\dalvik\vm\DvmDex.h


我是页脚

OS_Debug.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

  1. AOSP Download
  2. AOSP Build
  3. AOSP Read
  4. AOSP Debug

关于 AOSP Debug Java

在探索某一部分的细节逻辑的时候总是会需要查看源码的细节实现 , 查看当然好 , 但是能断点调试就更加棒了.

调试 Aosp 的方式有多种 , 这里我们只记录整个 AOSP 下载并调试的一点细节

  1. File -> Project Structure -> Project : 将 Android SDK 设置为和源码版本一致

    • apply , OK
  2. Run -> Attach Debugger to Android Process -> show all process : system_process

    • 直接快捷图标按钮也一样哈
  3. 启动一个和 AOSP 版本相同的 模拟器 (我想编译出来的那个 img 应该是最恰当的吧 ,
    但是我自己用的 AndroidStudio 之前下载的大版本相同的 , 图个方便 , 后续不满足需求再重编)

*. 测试: 在 ActivityStarter.java 类文件中 startActivityMayWait 函数多打几个断点 ,
随便一个启动 新 Activity 的动作都会击中断点

参考

  1. :Android AOSP基础(五)Android Studio调试系统源码的三种方式

我是页脚

OS_Read_sources.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x00. 阅读 Android 源代码(2020-07-16 09:56:38)

0.1. 常规操作 无争议

以前用 SourceInsight 做这件事 , 需要安装虚拟机 , 现在用 AndroidStudio

查看 自己 检出的 Android 源代码版本 > 方式一 :

  • 目录/build/core/version_defaults.mk 打开version_defaults.mk 文件,然后找� PLATFORM_SDK_VERSION 这个关键字的值,就可以在下表中找出相应的版本。

如何生成AndroidStudio可以打开的项目文件

  • 这个文件可以作为参考 , 下文细节和文件内容相关 , 又不完全相同
  • AOSP的 development/tools/idegen/readme 中有讲如何操作,我们按照其步骤来即可。
  • 这个文件已经比较老啦 , 在今天查看这个文件虽然有帮助但是并不能解决所有问题 , 还是需要花时间做些探索

未提前编译 AOSP 源码同步完成后支架操作 idegen 生成 android.ipr 尝试导入源码 , 点击无法跳转

  1. 先make development/tools/idegen/子目录:

    • mmm development/tools/idegen/
      • 实际上我是分两步的 :
      • cd development/tools/idegen/
      • mmm
    • 这个会得到idegen.jar,这个jar在第二步中要用到,如果没有这一步,第二步会提示找不到这个jar。
  2. 生成项目文件:

    • development/tools/idegen/idegen.sh
    • 这一步会利用前面的jar,生成android.ipr等项目文件。
    • 本人只得到了两个文件 : idegen.ipridegen.iml
    • 这两个文件位于 aosp 根目录
  3. 将项目导入到 idea 或者 AndroidStudio

    • 导入的时候选择 idegen.ipr 父目录(AOSP 目录)即可
    • 或者导入的时候选择 idegen.ipr 文件即可

IDEA 配置修改

如果 时间太久(2020-07-16 09:56:50) 还是应该参照官方指导做出合适的配置 aosp/development/tools/idegen/README

个人配置如下 :

//Help -> Edit custom properties

# 支持文件数
idea.max.intellisense.filesize=100000
# 支持大小写
idea.case.sensitive.fs=true
//Help > Edit Custom VM

-Xms1g
-Xmx5g

0x01. 用最新的 idea 导入 aosp 项目无法跳转

1.1. 思路一 通过旧版本 idea 加载 idegen.sh 生成的 ipr 文件

省心, 要忍受相对较陈旧的 IDE 工具

查看 idegen.sh 文件的 git 提交时间 , 找到历史 idea(2016.3.82017.3.7) 版本进行导入 ,

观察到 :

  1. 虽然有些许红色错误提示 , 但是可以顺利完成 Java 跳转

  2. 不支持 Kotlin (思路二 可以知道为啥不支持 kotlin)

  3. 要完成 java 跳转需要做的额外事情是:

    • 打开 File -> Project Structure 窗口
    • 选择 Project Settings 中的 Modules 子项
    • 切换到 Dependencies 标签
    • <Module source><No SDK> 移动到列表顶部
    • apply
    • ok

1.2. 思路二 (键者更喜欢) , 仅仅针对 2020.1.2 版本完成了实际测试

仍然要先安装软件执行导入/打开动作

导入后先完成如下动作 , 在 2017 版本如下操作尝到了甜头在 2020 版本仍然保持这个做法

  • 打开 File -> Project Structure 窗口
  • 选择 Project Settings 中的 Modules 子项
  • 切换到 Dependencies 标签
  • <Module source><No SDK> 移动到列表顶部
  • apply
  • ok
  • 等到扫描和索引完成后会发现依然不能跳转

新思路 : 要使用 idea 2018 、 2019 或者 2020 版本我们或需是需要研究下 idea 的 .iml 文件

通过测试我们知道

  • 测试手段可忽略 测试手段就是通过使用 idea 创建 java 项目然后查看精简版的 iml 文件 , 再通过修改查看索引结果
  • 测试手段可忽略 如此反复就得到了规律结论

.iml 文件中的 <sourceFolder 节点中的属性 type 及其对应的值删掉并且重新扫描和建立索引的话就可以完成 java 代码跳转了

  • 这里涉及到的 type 共有两种 type="kotlin-test"type="kotlin-source"
  • 这么做 java 是可以跳转了 , kotlin 是否仍被支持呢 ? 经过测试 , 果然就不支持啦 , kotlin 代码跳转受限
    • 再次经过测试可以知道不支持 kotlin 内容跳转并不是我们删除 type 造成的 ,
      而是因为 iml 文件中 content 节点本身就没有 kotlin 代码所在的路径的配置
    • 最终经过我们手动配置后就可以在 kotlin 中跳转了
    • 经过我们这一系列操作之后的 iml 文件格式如下
      <!--非本次重点的头部信息略-->
      
      <component name="NewModuleRootManager" inherit-compiler-output="true">
          <exclude-output />
          <content url="file://$MODULE_DIR$">
      
              <!--自定义节点用于控制 kotlin 跳转 , 可以手动添加 , 觉得手动添加烦人 , 就写个脚本吧 , 找出所有需要添加的路径一次完成-->
              <!--[猜测 , 未测试]也可以通过 `File -> Project Structure` 添加节点-->
              <sourceFolder url="file://$MODULE_DIR$/tools/metalava/src/test/java"  />
      
              <!--原来的content 内容 删除了 sourceFolder 节点中的 type 属性-->
              <sourceFolder url="file://$MODULE_DIR$/art/test/004-JniTest/src"  />
      
              <!--content 中的其他节点省略-->
          </content>
      
          <!--orderEntry 节点们 也省略-->
      
      </component>
      </module>

至此我们已经可以通过 idea 正常读取 AOSP 了

事实上 : 通过 Android Studio 也可行

仍然会有部分错误提示 , 暂时放一放这个细节

参考

  1. https://juejin.im/post/5bd5c42ce51d457a9b6c8387
  2. https://www.geek-share.com/detail/2681729474.html

//=================== 一个失败的分割线 ===================

  1. https://www.jianshu.com/p/a19dcb06cd53

我是页脚

一点思考.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

在源代码阅读的过程中,我们多数时候不是从整个系统的开始处阅读的。

这会导致一些参数的初始化过程我们不太清楚。

这一问题在有的时候我们可以根据猜测和网络上已经有的信息来规避。

但是也有些代码在查阅的时候强依赖这些参数(对象)的细节信息,这就需要我们返回去了解该参数(对象)的初始化过程。

要知道除非我们会退到整个源代码项目的入口点,否则我们始终回不可预期的遇到需要代码回溯的问题。

现在我们还是走的碰到问题然后回溯的路子。

我们期望在有一天回溯到某一个节点的时候,该节点可以很大程度上避免今后的回溯过程。也就是将其作为源码入口点。


我是页脚

AndroidAPP质量评价标准.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x00、 Android APP 质量评价

大纲:核心应用质量

  • 视觉设计和用户交互
  • 功能
  • 兼容性、性能和稳定性
  • 安全性

0x01、 关于性能

概述:使用更少的硬件资源达到更优的功能实现,这个取舍做的越好意味着性能越高。

  • “取舍”是一件见仁见智的事情,需要通过实际数据作为辅助才更有说服力。

以下三点来自于 Android Profiler 工具当前的功能实现。

1.1、 CPU

1.2、 内存

1.3、 网络


我是页脚

异常处理.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

Connect to 127.0.0.1:8888 [/127.0.0.1] failed: Connection refused (Connection refused)
Connect to 127.0.0.1:1083 [/127.0.0.1] failed: Connection refused (Connection refused)
  • 当前 出现这种 异常的情况是 : 通过代理工具(v2ary)设置了全局代理 然后关闭该代理工具 , 重新 build Android project 出现的 , 重启 AndroidStudio 后就好啦
  • 如果单纯重启无效试试 invalidate and restart
  • 如果还是不行 查看 gradle.properties 文件中是否有多余的代理代码
    • 文件位置 ~/.gradle/gradle.properties
    • 文件位置 project_path/gradle.properties

AndroidStudio 查看 Plugin Marketplace 不展示内容

  • 出现这种情况的时候我的设备上运行着 Charles 停止他的拦截开关就好啦
application install failed 
the device might have stale dexed jars that don't match the current version

https://stackoverflow.com/questions/29577329/installation-failed-since-the-device-possibly-has-stale-dexed-jars-that-dont-ma

原因 : 设备内存不足了
解决 : 清理下或者加内存


我是页脚

systrace.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

Android 性能优化 ☞ 卡顿

本文内容可以通过通篇阅读官方文档完全获取 , 本文是按照个人思路做的流程化的笔记📒 .
所涉及的连接如下:

  1. 渲染速度缓慢 : https://developer.android.google.cn/topic/performance/vitals/render?hl=zh-cn
  2. 在命令行上捕获系统跟踪记录 : https://developer.android.google.cn/topic/performance/tracing/command-line?hl=zh-cn
  3. 捕获设备上的系统跟踪记录 : https://developer.android.com/topic/performance/tracing/on-device?hl=zh-cn
  4. 浏览 Systrace 报告: https://developer.android.com/topic/performance/tracing/navigate-report?hl=zh-cn

0x01. 什么是卡顿以及卡顿的检测方法枚举

界面呈现是指从应用生成帧并将其显示在屏幕上的动作。要确保用户能够流畅地与您的应用互动,您的应用呈现每帧的时间不应超过 16ms,以达到每秒 60 帧的呈现速度。如果您的应用存在界面呈现缓慢的问题,系统会不得不跳过一些帧,这会导致用户感觉您的应用不流畅。我们将这种情况称为卡顿

  • 目视检查方法
  • Systrace 方法
  • 自定义性能监控方法

0x02. Systrace(System Trace) : 系统跟踪方法

小节摘要 : Systrace 工具通过跟踪系统的各项资源指标输出一个跟踪文件(我们称为trace文件) , 然后通过相应的图形界面解析工具(Perfetto/trace_viewer)将跟踪文件转换为可视可分析的报表(推荐 -3-)

  1. Perfetto : 是一个将 trace文件 转换为可视化报表的工具 : https://ui.perfetto.dev/
    • Perfetto 界面
  2. trace_viewer : 这个工具展示出来的 UI 当前已经是旧用户界面 了 , 可以通过 Perfetto 工具的 Legacy UI 来生成旧用户界面
  3. 可以通过 AndroidStudio Profile 打开trace文件 , 选择进程的时候我选择了 默认的那个 re-initialized> 可用 : 这个跟 Perfetto 相比 :
    • 这个跟 Perfetto 相比选中目标线程后才可以使用检索能力 ; 检索内容可以是 Trace.beginSection 函数打的标签也可以是其他内容
    • 但是通过肉眼找到目标Slices(色块/切片)的时候 , 是可以列举出子Slices(色块/切片)所对应的层级关系的(可折叠)
    • 可以查看 Frames(帧) 耗时
    • 二者都可以查看某一个函数的耗时 , 但是 AndroidStudio 列表的形式更直观些

生成trace文件的方式有二

  1. 命令行方式
  2. 此次采用的方式 : API>=28/Android9及之上的版本可以通过系统内建的工具生成 trace文件

0x03. 进一步定位已知问题

当我们知道某个函数或者某个类有卡顿状况的时候通过以下操作可以缩小限定范围

trace文件生成后就要将其以可视化的方式展示出来

  • 推荐 : AndroidStudio -> Profile -> Start new profiling session -> load from file
    • 需要将 trace文件 设置扩展名未 .trace
  • 不推荐 : Perfetto -> open trace file

时间轴上的条状色块是各个 label 对应的执行时间 , 但是如果没有打自定义 label 的话 , 那些 label 都是系统默认打的;

如果是假设某一部分有卡顿想要通过这个工具验证这个假设是否成立 , 我们可以打自定义标签:

Trace.beginSection("HelloWorld")
//other code
Trace.endSection()

确保生成 trace文件 的过程中打标签的代码被执行 , 当 Perfetto 将 trace文件 可视化后就可以通过搜索标签 HelloWorld 来定位自己标签对应的Slices(色块/切片) , 通过观察这个Slices(色块/切片)的长度是否大于 16ms 即可判断是否卡顿

  • 对于Android Studio Profile : 需要先锁定目标线程 , 一般就是 Main 线程再发起搜索
  • 对于Perfetto : 注意这里提到的检索不是浏览器的检索功能 , 是这个网页内部的检索功能

再继续沿着Slices(色块/切片)深入其子Slices(色块/切片)即可确定到是那些类的加载或者执行导致的时间大幅消耗 , 从而做出优化

0x04. 可否直接通过这种方式确定卡顿瓶颈呢?

4.1. AndroidStudio Profile 比较直观的列出了卡顿帧

通过 卡顿帧 结合时间线继续向下缩小卡顿排查范围 如果有必要 可以结合代码进一步定位:

Trace.beginSection("HelloWorld")
//other code
Trace.endSection()
  • AndroidStudio-Profile-UI.png

4.2. Perfetto 不是很直观

不知道某个页面某个功能是否存在卡顿的问题(肉眼感知不明显) , 通过 systrace 跟踪得到日志 , 再通过 Perfetto 分析跟踪记录 , 如何判断哪里有卡顿呢 ?

很多情况下Slices(色块/切片)从上到下的排列是这样的

Choreographer#doFrame Choreographer.doFrame.png
traversal 作为下层 , 表示的是上层所做的事 , 的一个细节
measure / layout /draw 作为下层 , 表示的是上层所做的事 , 的一个细节
RV XxxxxView 作为下层 , 表示的是上层所做的事 , 的一个细节
inflate 作为下层 , 表示的是上层所做的事 , 的一个细节
someClass 作为下层 , 表示的是上层所做的事 , 的一个细节

0x05. 当开始从 View 筛查的时候

5.1. Android 无法应对这种情况

5.2. Profile 可以通过打标记完成

当开始从 View 筛查的时候常常由于频繁的放大缩小到动作导致之前分析过并得到结论的内容被忘记

  1. 增加一个行 , 并设置对应的数据字符 : 操作步骤没学会 , 但是在 https://ui.perfetto.dev/ 页面中会展示 Debug 字样的按钮 , 后来我找不到了
  2. 可以在顶部的时间横轴插旗

如此就可以找到相对加载时间较长的 View , 进而可以做出相应的优化

0x06. 上述定位的是 View 相关的耗时问题

0x07. 非 UI 类问题导致的耗时如何辨别

0x08. View 加载造成的卡顿优化

  1. 尝试降低布局的层级嵌套数量
  2. 嵌套数降低到无法继续降低的时候有可能仍然卡顿(布局复杂的情况) , 可以尝试异步加载 : Asynclayoutinflater

0x09. 如何评估卡顿原因确定收益最大的优化方向

待研究的方法

参考

  1. Android:通过systrace进行性能分析
  2. https://juejin.cn/post/6844903949560971277#heading-18
  3. http://gityuan.com/2016/01/17/systrace/
  4. 代码生成 trace 文件
  5. Android 布局优化是真的难,从入门到放弃……

草稿暂存

Debug.startMethodTracing("tomyangming.trace")
Trace.beginSection("[email protected]")
Trace.endSection()
Debug.stopMethodTracing()

我是页脚

映射文件

{
  "last_success_opt_commit_log_line_key": "17e01ee4bb4c75d888022cd0032626b3bee8890c···@/@···2023-08-17 18:06:41 +0800···@/@···ubuntu18 aosp done",
  "issues_dictionary_map_key": {
    "README.md": 2,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Build.md": 3,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Read_sources.md": 4,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Source_download-1.md": 5,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Source_download.md": 6,
    "Collection/Android/Android系统源代码情景分析/AOSP/快捷链接.md": 7,
    "Collection/Android/Gradle/GitHub_Packages_了解.md": 8,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Debug.md": 9,
    "Collection/Android/Android系统源代码情景分析/AOSP/OS_Run_emulator.md": 10,
    "Collection/Android/Gradle/gradle探索方向.md": 11,
    "Collection/Android/性能优化/AndroidAPP质量评价标准.md": 12,
    "Collection/Android/性能优化/AndroidProfiler.md": 13,
    "Collection/Android/性能优化/ReadMe.md": 14,
    "Collection/Android/性能优化/systrace.md": 15,
    "Collection/kotlin/clone.md": 16,
    "Collection/QAS/C++/spawn-fcgi包装app异常文件疑问.md": 17,
    "Collection/QAS/C++/群组.md": 18,
    "_posts/Collections/Android/ASO/ASO预研.md": 19,
    "_posts/Collections/Android/AndroidStudio/AndroidStudio方便使用.md": 20,
    "_posts/Collections/Android/AndroidStudio/kotlin自动注释.md": 21,
    "_posts/Collections/Android/AndroidStudio/log/2018-08-07-log-1.md": 22,
    "_posts/Collections/Android/AndroidStudio/下载 ndk .md": 23,
    "_posts/Collections/Android/AndroidStudio/修改默认路径配置.md": 24,
    "_posts/Collections/Android/AndroidStudio/异常处理.md": 25,
    "_posts/Collections/Android/Android_API_DOC/2018-08-09-\tandroid.util.Log.md": 26,
    "_posts/Collections/Android/Android_API_DOC/android.net/ConnectivityManager.md": 27,
    "_posts/Collections/Android/Android_API_DOC/android.os.Build.md": 28,
    "_posts/Collections/Android/Android_API_DOC/android.provider/android.provider.CallLog.md": 29,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/Handler-Looper-Message.md": 30,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/OS_Logger_module.md": 31,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/OS_Read_1.md": 32,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/OS_Read_pakcage_understand.md": 33,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP阅读工具.md/AndroidStudio或IntelliJ.md": 34,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP阅读工具.md/SourceInside.md": 35,
    "_posts/Collections/Android/Android系统源代码情景分析/Dex文件结构/Dex文件结构-1.md": 36,
    "_posts/Collections/Android/Android系统源代码情景分析/Dex文件结构/Reference.md": 37,
    "_posts/Collections/Android/Android系统源代码情景分析/README.md": 38,
    "_posts/Collections/Android/Android系统源代码情景分析/list/list.md": 39,
    "_posts/Collections/Android/Android系统源代码情景分析/todo.md": 40,
    "_posts/Collections/Android/Android系统源代码情景分析/一些学习资源.md": 41,
    "_posts/Collections/Android/Android系统源代码情景分析/助力硬件.md": 42,
    "_posts/Collections/Android/Android系统源代码情景分析/必须做的事情.md": 43,
    "_posts/Collections/Android/Android系统源代码情景分析/方法小计/1.md": 44,
    "_posts/Collections/Android/Android系统源代码情景分析/方法小计/c-c++语法.md": 45,
    "_posts/Collections/Android/Android系统源代码情景分析/方法小计/words.md": 46,
    "_posts/Collections/Android/Android系统源代码情景分析/方法小计/调用栈/2018-3-23.md": 47,
    "_posts/Collections/Android/Android系统源代码情景分析/点/一点思考.md": 48,
    "_posts/Collections/Android/Android系统源代码情景分析/点/关键服务的源码位置.md": 49,
    "_posts/Collections/Android/Android系统源代码情景分析/目录/11章-Zygote和System进程的启动过程.md": 50,
    "_posts/Collections/Android/Android系统源代码情景分析/阻碍/1-AndroidStudio入手.md": 51,
    "_posts/Collections/Android/Android系统源代码情景分析/阻碍/2-SourceInsight入手.md": 52,
    "_posts/Collections/Android/Android系统源代码情景分析/阻碍/3-.aidl转.java.md": 53,
    "_posts/Collections/Android/Android系统源代码情景分析/阻碍/4-编译源代码.md": 54,
    "_posts/Collections/Android/Drozer/drozer 使用方法.md": 55,
    "_posts/Collections/Android/Drozer/drozer-下载-安装-资源.md": 56,
    "_posts/Collections/Android/Drozer/drozer按需把控.md": 57,
    "_posts/Collections/Android/Gesture/1临渊羡鱼.md": 58,
    "_posts/Collections/Android/Gradle/Gradle.Error.md": 59,
    "_posts/Collections/Android/Gradle/README.md": 60,
    "_posts/Collections/Android/Gradle/一个窗口打开多个Project.md": 61,
    "_posts/Collections/Android/Gradle/代理设置.md": 62,
    "_posts/Collections/Android/Gradle/内存占用.md": 63,
    "_posts/Collections/Android/Gradle/编译速度.md": 64,
    "_posts/Collections/Android/Intent/Intent_1.md": 65,
    "_posts/Collections/Android/Intent/Intent_2.md": 66,
    "_posts/Collections/Android/JetPack.md": 67,
    "_posts/Collections/Android/Library/PermissionUtil/2018-10-20_readme.md": 68,
    "_posts/Collections/Android/Library/PermissionUtil/Java.lang.ClassNotFoundException.md": 69,
    "_posts/Collections/Android/Library/PermissionUtil/Permission.md": 70,
    "_posts/Collections/Android/Security/信息源.md": 71,
    "_posts/Collections/Android/Uri/使用 String 生成 Uri 的常见操作.md": 72,
    "_posts/Collections/Android/Utils/Overview.md": 73,
    "_posts/Collections/Android/Utils/app_permission.md": 74,
    "_posts/Collections/Android/aapt/1_aapt.md": 75,
    "_posts/Collections/Android/adb/README.md": 76,
    "_posts/Collections/Android/adb/adb_shell_dumpsys.md": 77,
    "_posts/Collections/Android/adb/adb按需探索.md": 78,
    "_posts/Collections/Android/adb/adb整体把控.md": 79,
    "_posts/Collections/Android/adb/logcat.md": 80,
    "_posts/Collections/Android/android_os/android-环境变量.md": 81,
    "_posts/Collections/Android/apktool/1_apktool.md": 82,
    "_posts/Collections/Android/clone_app/clone app.md": 83,
    "_posts/Collections/Android/custom weight/View 加载流程 & 自定义控件.md": 84,
    "_posts/Collections/Android/custom weight/custom Preference.md": 85,
    "_posts/Collections/Android/find_view_by_id.md": 86,
    "_posts/Collections/Android/ndk/ndk-build_error_collection.md": 87,
    "_posts/Collections/Android/point4dev/AndroidBarStatus.md": 88,
    "_posts/Collections/Android/point4dev/AndroidTest/Android测试探究.md": 89,
    "_posts/Collections/Android/point4dev/Android性能分析.md/Android性能分析-1.md": 90,
    "_posts/Collections/Android/point4dev/Android性能分析.md/内存泄露.md": 91,
    "_posts/Collections/Android/point4dev/Android性能分析.md/卡顿和丢帧问题分析.md": 92,
    "_posts/Collections/Android/point4dev/Application_Performance_Management(APM)/Application_Performance_Management(APM).md": 93,
    "_posts/Collections/Android/point4dev/DataBinding.md": 94,
    "_posts/Collections/Android/point4dev/Google Play 发布 app.md": 95,
    "_posts/Collections/Android/point4dev/HTTPDNS.md": 96,
    "_posts/Collections/Android/point4dev/Handler-Message-MessageQueue-Looper.md": 97,
    "_posts/Collections/C_C++/知识点/NULL & nullptr & 0.md": 98,
    "_posts/Collections/C_C++/知识点/POSIX.md": 99,
    "_posts/Collections/C_C++/知识点/define & typedef .md": 100,
    "_posts/Collections/C_C++/知识点/delete-free-malloc.md": 101,
    "_posts/Collections/C_C++/知识点/gdb/gdb_感性.md": 102,
    "_posts/Collections/C_C++/知识点/gdb/gdb_理性.md": 103,
    "_posts/Collections/C_C++/知识点/include.md": 104,
    "_posts/Collections/C_C++/知识点/question/question_1.md": 105,
    "_posts/Collections/C_C++/知识点/作用域.md": 106,
    "_posts/Collections/C_C++/知识点/关于指针.md": 107,
    "_posts/Collections/C_C++/知识点/关键字/extern.md": 108,
    "_posts/Collections/C_C++/知识点/内存对齐&页对齐.md": 109,
    "_posts/Collections/C_C++/知识点/内存管理.md": 110,
    "_posts/Collections/C_C++/知识点/动态库 & 静态库.md": 111,
    "_posts/Collections/C_C++/知识点/变量初始化.md": 112,
    "_posts/Collections/C_C++/知识点/名词解释_1.md": 113,
    "_posts/Collections/C_C++/知识点/名词解释_2.md": 114,
    "_posts/Collections/C_C++/知识点/命名空间.md": 115,
    "_posts/Collections/C_C++/知识点/头文件 & 命名空间.md": 116,
    "_posts/Collections/C_C++/知识点/头文件 & 类 & 成员变量.md": 117,
    "_posts/Collections/C_C++/知识点/字节序.md": 118,
    "_posts/Collections/C_C++/知识点/小技巧.md": 119,
    "_posts/Collections/C_C++/知识点/析构函数(Destructor).md": 120,
    "_posts/Collections/C_C++/知识点/标准库/标准库小结_1.md": 121,
    "_posts/Collections/C_C++/知识点/现象.md": 122,
    "_posts/Collections/C_C++/知识点/空字符.md": 123,
    "_posts/Collections/C_C++/知识点/编译器-标准库.md": 124,
    "_posts/Collections/C_C++/知识点/编译错误/warning.md": 125,
    "_posts/Collections/C_C++/知识点/跨平台/跨平台-2.md": 126,
    "_posts/Collections/C_C++/知识点/跨平台/跨平台.md": 127,
    "_posts/Collections/C_C++/知识点/预处理/#ifndef,#define,#endif.md": 128,
    "_posts/Collections/C_C++/知识点/预处理/预处理.md": 129,
    "_posts/Collections/C_C++/知识点/预处理/预处理`##`.md": 130,
    "_posts/Collections/Cryptorarphy/AES.md": 131,
    "_posts/Collections/Cryptorarphy/RSA算法.md": 132,
    "_posts/Collections/DesignPattern/DesignPrinciple.md": 133,
    "_posts/Collections/DesignPattern/FactoryPattern.md": 134,
    "_posts/Collections/Doxygen.md": 135,
    "_posts/Collections/Flutter/README.MD": 136,
    "_posts/Collections/GIT/.gitignore.md": 137,
    "_posts/Collections/GIT/GitHub/2018-08-14-GraphQL API v4.md": 138,
    "_posts/Collections/GIT/GitHub/2018-08-14-REST API v3 [Overview].md": 139,
    "_posts/Collections/GIT/GitHub/2018-08-15-Apps.md": 140,
    "_posts/Collections/GIT/GitHub/2018-08-15-REST API v3 [Issue].md": 141,
    "_posts/Collections/GIT/GitHub/2018-08-18-REST API v3 [OAuth Authorizations API].md": 142,
    "_posts/Collections/GIT/GitHub/2018-08-20-REST API v3 [search].md": 143,
    "_posts/Collections/GIT/GitHub开发者计划.md": 144,
    "_posts/Collections/GIT/README.MD": 145,
    "_posts/Collections/GIT/git diff.md": 146,
    "_posts/Collections/GIT/git remote.md": 147,
    "_posts/Collections/GIT/git-差异化配置.md": 148,
    "_posts/Collections/GIT/git_operate.md": 149,
    "_posts/Collections/GIT/man/git branch --help.md": 150,
    "_posts/Collections/GIT/访问 github 连接被拒绝.md": 151,
    "_posts/Collections/I know , I don't know/Android/Android Linux 命令.md": 152,
    "_posts/Collections/I know , I don't know/Android/Android源码阅读.md": 153,
    "_posts/Collections/I know , I don't know/Android/编程.md": 154,
    "_posts/Collections/I know , I don't know/C++/c++类定义时,关键字class和类名之间还有一个宏.md": 155,
    "_posts/Collections/I know , I don't know/Linux可执行文件.md": 156,
    "_posts/Collections/I know , I don't know/int取值范围.md": 157,
    "_posts/Collections/I know , I don't know/makefile.md": 158,
    "_posts/Collections/IOS/IOS逆向.md": 159,
    "_posts/Collections/IOS/_问题贴.md": 160,
    "_posts/Collections/IOS/关于测试.md": 161,
    "_posts/Collections/IOS/关于越狱.md": 162,
    "_posts/Collections/IOS/杂记.md": 163,
    "_posts/Collections/IOS/越狱之后文件传输.md": 164,
    "_posts/Collections/Internet/(Ramnode)购买了一个VPS.md": 165,
    "_posts/Collections/Internet/IPv6.md": 166,
    "_posts/Collections/Internet/InitVerticalPrivateRoom.md": 167,
    "_posts/Collections/Internet/InstallShadowsocks.md": 168,
    "_posts/Collections/Internet/Linux方向键乱码.md": 169,
    "_posts/Collections/Internet/Ramnode体验.md": 170,
    "_posts/Collections/Internet/TCP-IP--Http--Socket.md": 171,
    "_posts/Collections/Internet/VPS_选购_存档.md": 172,
    "_posts/Collections/Internet/VPS测试工具.md": 173,
    "_posts/Collections/Internet/perl_warning_Setting_locale_failed.引发的问题.md": 174,
    "_posts/Collections/Internet/计算机网络.md": 175,
    "_posts/Collections/Java/JNI/JNI 学习资料.md": 176,
    "_posts/Collections/Java/JNI/JNI.1.md": 177,
    "_posts/Collections/Android/未分类/架构&模式.md": 178,
    "_posts/Collections/Android/未分类/Handler.md": 179,
    "_posts/Collections/Android/未分类/JetPack.md": 180,
    "_posts/Collections/Android/面经&八股/Android Basic Activity.md": 181,
    "_posts/Collections/Android/面经&八股/Android Basic Intent.md": 182,
    "_posts/Collections/Android/面经&八股/Android Basic View.md": 183,
    "_posts/Collections/Android/面经&八股/Android Basic.md": 184,
    "_posts/Collections/Android/面经&八股/ReadMe.MD": 185,
    "_posts/Collections/关于学习方法/关于-陈皓.md": 186,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/1.下载源代码.md": 187,
    "_posts/Collections/Software/jdk提取免安装文件.md": 189,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/2.下载源代码.ubuntu18.md": 190,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/3.Ubuntu多版本OpenJDK.md": 191,
    "_posts/Collections/Android/Android系统源代码情景分析/AOSP/OS_Read_sources.md": 192
  }
}

一些学习资源.md

OS_Source_download.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

一、 使用环境

Ubuntu 16.04

二、 操作流程

https://source.android.com/

2.1、 下载流程理解

  1. 下载 repo
  2. 下载初始化数据(大小不固定,>30G,本次使用过程中发现文件大小为 45G )
    • 这个过程可以通过使用 repo 下载
      • 我的首次操作使用这种方式(下载到60G还没完成,我方了,转而停止下载使用清华镜像站的解决方案)
    • 清华镜像站推荐下载他们的压缩包然后解压使用
  3. repo init (在这一步指定要下载的系统代码版本)
  4. repo sync
    • 在这里完成对目标代码的下载
    • 本步骤强烈建议使用脚本完成,因为会出错需要重复执行目标命令,但是长达几个小时的下载过程一直监视很麻烦。

2.2、 可复用的内容

  1. repo 文件已经下载 /media/tom/os/bin/repo
  2. repo 已经安装 /media/tom/os/AOSP/android-****/.repo
    • 当下载新版本的android源码时,新建一个对应版本的文件夹,将 .repo 文件夹整个剪切过去
    • 在新建的文件夹中执行通过 init 设置即将下载的源码版本
    • 执行 sync 命令即可

三、 问题解决

3.0、 使用国内镜像

  1. 同步、更新、下载Android Source & SDK from 国内镜像站
  2. 清华 Android 镜像使用帮助

3.1、 网络不可达

$ repo init
fatal: Cannot get https://gerrit.googlesource.com/git-repo/clone.bundle
fatal: error [Errno 101] Network is unreachable

直接翻墙解决 > 恰好我有 VPS 和 Shadowsocks = 失败

  • 失败原因应该是配置好系统代理之后没有重启命令行导致的。

解决方案:

  1. 先单独克隆repo
    git clone https://gerrit-googlesource.lug.ustc.edu.cn/git-repo
    
  2. 然后将git-repo里面的repo文件复制到bin目录,然后chmod a+x ~/bin/repo.
    • 再在同步源码的工作目录新建.repo文件夹,把git-repo重命名为repo复制到.repo目录下:
    • 重新初始化:
    repo init
    

为了应对重复失败:error: Exited sync due to fetch errors
我们找到一个脚本:

#!/bin/sh
repo sync -j4
while [ $? -ne 0 ]
do
repo sync -j4
done

3.2、 疑似错误

听说 Android 源码一共就 4~8G 但是我们都下载了 60+G 还没有完这然我怀疑下错了,所以我想再来一次。

  • 并且使用了清华镜像教程

转移到 cygwin

  1. cd /cygdrive/i/AOSP/android-4.4.4_r1/
  2. /cygdrive/i/AOSP/bin/repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.4.4_r1
  3. ./sync_tomsh
  4. /cygdrive/i/AOSP/bin/repo sync

cygwin 查看当前编码

repo sync -c 出现错误 (UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 9: ordinal not in range(128)) 我们认为是python 默认编码的原因于是修改 python 默认编码为 utf8 (从默认的 ascii 修改成 utf8)

http://shirley-ren.iteye.com/blog/1018750

cygwin permission denion

以管理员身份运行

转到虚拟机

有些类文件我们 google 很轻松就找到了源码,但是这和我们下载下来的源码的分类和路径不大相同:这时什么原因我们应该如何根据 google 到的代码在本地找到对应?

例如我们当前在 google 找到了目标代码

  • android / platform / libcore / android-4.3_r3 / . / luni / src / main / java / libcore / io / Libcore.java
  • 针对这个结果我们在本地找到了这样的路径:
  •               `I:\AOSP\android-4.4.4_r1\libcore\ luni \ src \ main \ java \ libcore \ io`
    
  • 如果所有的源码具有如上规律那事情就很清楚了。我们暂且这么认为

3.3、 The following untracked working tree files would be overwritten by checkout

Syncing work tree:  97% (437/450)error: The following untracked working tree files would be overwritten by checkout:
	10/android.jar
	10/framework.aidl
	……//代表一堆文件
	Android.mk
	CleanSpec.mk
	api/1.xml
	……//代表一堆文件
	current/Android.mk
	……//代表一堆文件
Please move or remove them before you can switch branches.
Aborting
Syncing work tree: 100% (450/450), done.  

error: prebuilts/sdk/: platform/prebuilts/sdk checkout 48df57e9d07887b7621d51cc93ae7600815a842d 

解决方案:将上述文件删除重新执行 sync 命令即可

3.4、 info: A new version of repo is available

info: A new version of repo is available

warning: project 'repo' branch 'master' is not signed
warning: Skipped upgrade to unverified version

尚未解决

0x04. Google 对自家手机硬件的软件支持计划

https://support.google.com/pixelphone/answer/4457705?hl=zh-Hans

0x05. repo 使用细节

在清华镜像站, 下载压缩包 ,解压之后直接执行 repo sync 即可检出所有 AOSP 代码 .

这里需要搞清楚的是,

  1. 我们并未指定源码版本 , 那么我们如果进行编译的话是在编译那个版本 ?
  2. 再有就是, 如果这时候我们想要编译指定版本我们应该怎么做 ?
  3. 暂时猜测 repo 既然是 git 的简化工具, 那么 AOSP 是否采用分支的方式管理不同版本的代码的呢?
    • 有待实践确认这一猜想

5.1. 启发命令

分支管理

查看所有分支

cd .repo/manifests
git branch -a
# 或
git branch -a | cut -d / -f 3

切换分支

$ repo init -b android-4.2.2_r1 

repo切换分支后,cat .repo/manifests.git/config 可见以下内容,在branch "default"的merge那里,没切换前是merge = refs/heads/master,切换后如下:

[core]
    repositoryformatversion = 0
    filemode = false
[filter "lfs"]
    smudge = git-lfs smudge --skip -- %f
[remote "origin"]
    url = git://mirrors.ustc.edu.cn/aosp/platform/manifest
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "default"]
    remote = origin
    merge = refs/heads/android-4.2.2_r1

# 创建自己的新分支
$ repo start gingerbread-release --all 

# 查看当前的分支
$ repo branches

我是页脚

GitHub_Packages_了解.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

使用 GitHub Packages 发布 Android lib

0x00. 远程仓库了解

之前我们使用 JCenter 作为远程仓库主要存在两个问题

  1. 下载较慢, 有一定概率下载失败
  2. 后来我上传也不行了 , 懒得排查上传异常原因了

所以我尝试探索其他的远程仓库

  1. maven
  2. github packages

再次研究这部分内容可以考虑下 : https://jitpack.io/

0x02. GitHub Packages 了解

GitHub Packages , 经过测试 , 上传比较快 , 同等环境下(翻墙代理) ,
从 JCenter 下载依赖 , 失败多次 ,
从 GitHub Packages 下载没有失败过

配置过程不复杂

  1. 使用 Gradle 发布 Java 包
  2. 配置 Gradle 用于 GitHub 包
  3. Publishing Android libraries to GitHub Packages
  4. 无效 为 aar 关联源代码
  5. 有效 为 aar 关联源代码

存在的问题就是 , 使用上传到 GitHub Packages 的 Lib 还需要 提供自己的 GitHub 身份认证 ,
虽然这也不是什么复杂的操作 , 但是比起直接一行代码完成依赖 , 还是会多那么几行烦人的代码 .

碰到的问题 : aar 上传后无法查看源码 , 已经解决了 , 这个小细节等下一阶段输出文档的时候再详细描述

恩 上传到 MavenCenter 更烦人 , 所以我回来啦

0x03. GitHub Packages 使用详情

配置文件 , 可以直接拷贝也可以参照上文官方指导 , 阅读后再使用

3.1. Android gradle 配置代码

ext {
    moduleVersionCode = 2
    moduleVersionName = '0.1.6'
    moduleName = 'LibLog'

    mavenGroupId = 'io.github.tomgarden'
}

//这个节点和官方文档不同
task androidSourcesJar(type: Jar) {
    /*生成 sources.jar 应对生成的 aar 跳转代码无法阅读的问题*/
    archiveClassifier.set('sources')
    from android.sourceSets.main.java.srcDirs
}

publishing {

    //这个节点和官方文档不同
    publications {
        gpr(MavenPublication) {
            groupId mavenGroupId
            artifactId moduleName
            version moduleVersionName
            artifact("$buildDir/outputs/aar/$moduleName-release.aar")
            // 将 generateSourcesJar Task 生成的 sources.jar 也一并上传
            artifact(androidSourcesJar)
        }
    }

    repositories {
        maven {
            name = moduleName
            //仓库地址
            url = uri("https://maven.pkg.github.com/TomGarden/lib_log")
            credentials {
                username = project.findProperty("gpr.user") ?: System.getenv("TOMGARADEN_USERNAME")
                password = project.findProperty("gpr.key") ?: System.getenv("PUBLISH_LIB_TO_GITHUB_PACKAGES_TOKEN")
            }
        }
    }
}

3.2. 环境变量设置实践

#
# /Volumes/tom_disk/Users/tom/.tom_shell_profile
#
################################################################
# 以前我们用 bash 作为命令语言解释器 , 这时候如果我们需要配置环境变量
# 修改啊 ~/.bash_profile 即可
#
# 后来我们使用 zsh 作为命令语言解释器 , 这时候如果我们要配置环境变量就需要
# 设置文件 ~/.zshrc
#
# 干脆我们自己写一个文件 , 然后到上述两个文件中各添加一条指令:
# source ~/.tom_shell_profile
################################################################

# 发布 Android lib 到 github 需要的 github 做身份认证的 token
# 在 Android project 中通过 `System.getenv("ANDROID_SDK_HOME")` 获取此值

# 专一用于管理 GitHub Packages [write:packages/read:packages] 
export TOMGARADEN_USERNAME=TomGarden
export TOMGARADEN_WRITE_PACKAGES_TOKEN=略
export TOMGARADEN_READ_PACKAGES_TOKEN=略
#
# /Volumes/tom_disk/Users/tom/.zshrc
# /Volumes/tom_disk/Users/tom/.bash_profile
#
# 自定义环境变量设置(也可以将原文内容复制过来, 这么做是为了不同的命令解释器可复用)
source ~/.tom_shell_profile

3.3. 编译上传动作

$gradlew clean 
$gradlew build
# 替换 ModuleName
$gradlew :<ModuleName>:publish

至此依赖包已经上传到 GitHub Packages 了

3.4. 下载已上传的依赖包到自己的项目中使用:

在要使用远程库的 Module 中添加代码

//此节点位于 ModuleName/build.gradle
dependencies {
    //implementation project(path: ':LibLog')
    implementation 'io.github.tomgarden:LibLog:0.1.6'
}

//此节点位于 ModuleName/build.gradle , 或者 ProjectName/build.gradle
repositories {
    maven {
        url = uri("https://maven.pkg.github.com/TomGarden/lib_log")
        url = uri("https://maven.pkg.github.com/TomGarden/lib_pickcolor")
        credentials {
            //不限的 github 账户名
            username = System.getenv("TOMGARADEN_USERNAME")
            //与 github 账户名成对的 具有 read:packages 权限的 token
            password = System.getenv("TOMGARADEN_READ_PACKAGES_TOKEN")
        }
    }
}

编译运行即可使用了

0x04. 如果一个人开发了一系列的工具组件 , 如何较简单的完成分发

  1. 创建一个公共组件 repository : TomAndroidLibs
  2. 所有分发组件上传到这个公共组价库
  3. 使用组件的开发者需要配置自己的 GitHub 账户信息
  4. 失败了 , 所以细节略
  5. 可能是因为与仓库地址相关 , 所以上传的过程中报 402

4.1 记录一个异常

> Task :LibPickColor:publishGprPublicationToLibPickColorRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':LibPickColor:publishGprPublicationToLibPickColorRepository'.
> Failed to publish publication 'gpr' to repository 'LibPickColor'
   > Could not PUT 'https://maven.pkg.github.com/TomGarden/lib_pickcolor/io/github/tomgarden/LibPickColor/0.1.3/LibPickColor-0.1.3.aar'. Received status code 422 from server: Unprocessable Entity

解决方法是将 artifactId 使用小写字母

如果修改名称后找不到文件 Could not read 'path/lib_pick_color-release.aar' as it does not exist.
可以参照链接 : 🔗 archivesBaseName = moduleName

4.2. github package 重复上传冲突异常

# 出现这种情况是因为上传包完成后 , 项目首页没有及时刷新包信息 UI 认为上传失败重新发起上传报的异常
# 上传完成后可以稍等 2 分钟再刷新页面

> Task :lib_system_bar:publishGprPublicationToLib_system_barRepository FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':lib_system_bar:publishGprPublicationToLib_system_barRepository'.
> Failed to publish publication 'gpr' to repository 'lib_system_bar'
   > Could not PUT 'https://maven.pkg.github.com/TomGarden/lib_system_bar/io/github/tomgarden/lib_system_bar/0.0.1/lib_system_bar-0.0.1.aar'. Received status code 409 from server: Conflict

0x05. (这个步骤无结果 , 可以不读)上传到 Maven Central

我们按照 https://juejin.im/post/5c3bddeff265da616501c56b 的操作指导(没有上传公钥) ,
完成了操作 , 并且上传成功了 , 但是在 maven center 搜索不到自己上传的 lib 文件
还需要跟进

看看等等怎么样 :

不想等了 , 本次就采用 GitHub Packages

5.1. 参考内容

  1. https://www.jianshu.com/p/67d81977b027

我是页脚

助力硬件.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

测试机选购初步想法

0x01. 测试机购买组合一 :

过于钟情这个选项

  1. Pixel 3A Google 系统支持到 2022 年 5 月

  2. OPPO 2000 - A92s 6G+128G 九十度黑

0x02. 测试机单项购买 Pixel

3000 - Google Pixel 4a

0x03. 测试机单项购买 OPPO

OPPO 3000 - Reno4 5G 晶钻红 8G+128G
OPPO 2500 - Reno4 SE 超闪黑/8G+128G

0x04 说明:

  1. 个人对 3000 元的花费定义优先级为 0x01 > 0x02 > 0x03
  2. 如果 pixel 可以作为一个可选项 , 需要我先跟店铺做一个简单沟通再下单较为合适
  3. 没选 vivo 是因为 vivo 商城体验没有 oppo 好
  4. 钟情 pixel 是因为对于开发者来说有更多钻研系统的空间

我是页脚

OS_Build.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x01. 资源情况

  • MAC OS 10.15
  • i7
  • 16G 闪存
  • 500G 硬盘(凑活够用) > 1T 更合适

0x02. 命令使用情况

2.1. 查看可以 lunch 的版本

# 执行 lunch 不加参数即可
lunch

2.2. 编译失败会需要清除历史编译文件的动作才好开始重新开始编译

m clean

2.3. 整体编译

  1. 设置最大打开的文件描述符的数量(.tom_shell_profile) : ulimit -S -n 2048
  2. 使用 envsetup.sh 脚本初始化环境:source build/envsetup.sh
  3. 选择构建目标: lunch aosp_x86-eng
  4. 开始构建 : m

注意事项:

  1. 日志输出到指定文件 , 避免命令行应用异常的时候日志无法有效观察
  2. 剩余存储空间在 60G 上下的时候是无法完成编译的 , 会因为内存不足而失败 ;
    整体编译除了源码本身外还需要磁盘空间数为 : 83.73 G 的时候编译成功, 成功后剩余 20 G 空间;
    用时在 4h 以内
  3. 如果先做了整体编译 , 然后做了部分代码的细节修改 , 再做整体编译
    我是对 framework 层代码做了小修小改 , 用时基本在 40min 内

2.4. 修改 Framework 层的部分代码, 部分编译

2.5. 修改 framework 层的文件夹代码

2.5.1. 没有导致异常的修改和部分重新编译 : 对已有 api 的简单调用

下文 adb 命令的执行状态和 emulator 的执行状态一样 , 都是先执行过了如下命令:

source build/envsetup.sh
lunch

修改过的文件的路径 frameworks/base/services/core/java/com/android/server/wm

  • 主要是在某些文件中添加了 android.util.Log 的调用
  1. 执行编译 成功
    # 1. 这个路径没有太明确的判断是试出来的逐层试, 并观察
    # 2. 太深的路径会导致修改没有被应用,这个原因暂不深究 . 
    #    失败的测试路径 : cd frameworks/base/services/core/java/com/android/server/wm
    # 3. 随着修改的文件的越来越多 , 这个路径要随之变化
    # 4. 如果有必要使用 `mm java` 会大大提高编译速度
    #     但是携带 java 命令常常导致编译失败 , 失败了删除它再试一次或需能成功
    cd frameworks/base/services
    mm java
    

编译完成将新的编译产物应用到模拟器上

  1. 将模拟器置于启动状态

    # -writable-system 如果没有这个命令 adb remount 可能会失败
    $ emulator -writable-system
    
  2. 执行同步操作动作前, 需要先获取模拟器文件系统的操作权限

    adb root
    adb disable-verity # https://source.android.com/security/verifiedboot/dm-verity
                       # 启动时验证会尽力确保所有已执行代码均来自可信来源 , 此命令为关闭此验证动作
    adb reboot
    adb root
    adb remount
    
  3. 执行文件同步动作

    $ adb sync // Sync the updated module to the device
    $ adb shell stop // Stopping the shell
    $ adb shell start // Starting the shell again
    
  4. 然后可以验证自己想修改是否生效了 , 我生效了

2.5.2. 出现异常的代码修改 : 添加类文件

我们希望查看某一个函数相关的调用栈 , android.util.Log 需要大量的编码, 而且不是很直观

  • 把应用层开发中常用的日志工具 Logger 做一个剪裁 , 放到 frameworks/base/core/java/android/util/tom_logger
  • Logger 剪裁版本
异常一:

对文件的修改情况

  1. framework/base/service 中的某些文件调用了 Log / TomLogger
  2. framework/base/core/java 中添加了 tom_logger/TomLogger 相关日志工具类文件

编译情况

  1. 只编译了 framework/base/service 没有编译 framework/base/core/java

异常情况

  1. 模拟器已经无法正常启动了(由于异常进入了死循环) .
异常二:

异常一的基础上增加对 framework/base/core/java 涉及文件的编译动作

$ cd frameworks/base/core
$ mm java # 由于我们只修改了 java 代码, 此命令应该可以降低编译成本
  1. 这个编译动作始终失败, 并且没有给出异常后的操作建议
  2. 还有一个存疑的问题暂不深究: 当模拟器已经处于异常的死循环状态时候 ,
    我们通过某些操作将新的修正成功编译了应该如何将新编译的结果应用到模拟器上?
    下面就是我们围绕这个问题保留的参考内容
异常解决 : 异常原因和涉及原理暂不深究

重新全量编译 , 得到有意义的异常帮助信息 , 并解决了问题(新添加的代码运行正常, 调用栈清晰)

$ cd aosp
$ m clean
$ m


FAILED: out/soong/.intermediates/frameworks/base/api-stubs-docs/android_common/check_current_api.timestamp

error: Added package android.util.tom_logger [AddedPackage]
Aborting: Found compatibility problems checking the public API against the API in /Volumes/beyourself/AOSP/aosp/frameworks/base/api/current.txt
-e
******************************
You have tried to change the API from what has been previously approved.

To make these errors go away, you have two choices:
   1. You can add '@hide' javadoc comments to the methods, etc. listed in the
      errors above.

   2. You can update current.txt by executing the following command:
         make api-stubs-docs-update-current-api

      To submit the revised current.txt to the main Android repository,
      you will need approval.
******************************

$ make api-stubs-docs-update-current-api
#### build completed successfully (01:55 (mm:ss)) ####

$ m
#### build completed successfully (14:09 (mm:ss)) ####

2.5.3. 部分参考和相关疑问

进度小计

当前进度 : 在 /Volumes/beyourself/AOSP/aosp/frameworks/base/core/java
执行 mm java 会在 30 min 后编译失败, 跟进这个异常 :

  • 我们要解决这个问题是因为 Log 无法满足我们的需要 , 我们希望在 framework 增加自己的日志工具
  • 我们希望通过日志工具了解 Activity 的启动流程中多次调用关键函数的细节
  • 我们在了解 Activity 启动过程中碰到一点疑问, 希望做进一步探究
  • 我们在了解 Activity 的启动过程
  • 我们希望了解 Activity 横竖屏切换过程中发生了什么
  • Dialog 位于 Fragment , Fragment 位于 Activity .
    我们希望在 Activity 切换横竖屏的过程中能按照我们的意图保存状态

2.*. m help

# mm help 和下面的内容也一样
➜  aosp m help
The basic Android build process is:

cd /Volumes/beyourself/AOSP/aosp
source build/envsetup.sh    # Add "lunch" (and other utilities and variables)
                            # to the shell environment.
lunch [<product>-<variant>] # Choose the device to target.
m -j [<goals>]              # Execute the configured build.

Usage of "m" imitates usage of the program "make".
See /Volumes/beyourself/AOSP/aosp/build/make/Usage.txt for more info about build usage and concepts.

Common goals are:

    clean                   (aka clobber) equivalent to rm -rf out/
                            清除编译动作所产生的所有文件
    checkbuild              Build every module defined in the source tree
    droid                   Default target
    nothing                 Do not build anything, just parse and validate the build structure

    java                    Build all the java code in the source tree
    native                  Build all the native code in the source tree

    host                    Build all the host code (not to be run on a device) in the source tree
    target                  Build all the target code (to be run on the device) in the source tree

    (java|native)-(host|target)
    (host|target)-(java|native)
                            Build the intersection of the two given arguments

    # 下面几个字段的含义暂不能明晰呢

    snod                    Quickly rebuild the system image from built packages
                            Stands for "System, NO Dependencies"
    vnod                    Quickly rebuild the vendor image from built packages
                            Stands for "Vendor, NO Dependencies"
    pnod                    Quickly rebuild the product image from built packages
                            Stands for "Product, NO Dependencies"
    psnod                   Quickly rebuild the product_services image from built packages
                            Stands for "ProductServices, NO Dependencies"
    onod                    Quickly rebuild the odm image from built packages
                            Stands for "ODM, NO Dependencies"


So, for example, you could run:

cd /Volumes/beyourself/AOSP/aosp
source build/envsetup.sh
lunch aosp_arm-userdebug
m -j java

to build all of the java code for the userdebug variant of the aosp_arm device.


#### build completed successfully (1 seconds) ####

0x03. 异常状况

3.1. 不同格式的硬盘分区读取

Linxu 读取 mac 分区

#关闭Journal
$ diskutil disableJournal disk0s2
Journaling has been disabled on disk0s2
 
#打开Journal  
$ diskutil enableJournal disk0s2
Journaling has been enabled on disk0s2

mac 读取 linux 分区

3.2. 如果有有需要调整最大打开文件数

  • 异常信息 : too many open files soong bootstrap failed with: exit status 1

在 macOS 中,可同时打开的文件描述符的默认数量上限太低,在高度并行的构建流程中,可能会超出此上限。如需提高此上限,请将下列行添加到 ~/.bash_profile 中:

//如果按照官方的建议设置了 1024 还是提示这个错误 , 可以尝试 2048
set the number of open files to be 1024
ulimit -S -n 1024 

3.3. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

调整 Java 的对大小设置 export _JAVA_OPTIONS="-Xmx6g"

参考:https://stackoverflow.com/questions/60468693/java-outofmemoryerror-when-building-aosp-10

3.4. Linux [编译成功虚拟机失败]

3.5. Catalina 编译android 10报错


➜  aosp m
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=10
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
HOST_ARCH=x86_64
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-19.5.0-x86_64-10.15.5
HOST_BUILD_TYPE=release
BUILD_ID=QQ3A.200605.002.A1
OUT_DIR=out
============================================
FAILED: out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0
/bin/bash -c "(out/host/darwin-x86/bin/treble_sepolicy_tests -l 		out/host/darwin-x86/lib64/libsepolwrap.dylib  -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts 		-b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/28.0_mapping.combined.cil 		-o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/built_28.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy 		-u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil 		--fake-treble ) && (touch out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0 )"
/bin/bash: line 1: 21672 Segmentation fault: 11  ( out/host/darwin-x86/bin/treble_sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/28.0_mapping.combined.cil -o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_28.0_intermediates/built_28.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy -u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil --fake-treble )
[ 78% 63452/80802] build out/target/product/generic_x86/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
FAILED: out/target/product/generic_x86/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
/bin/bash -c "(out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib 		 -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts  -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy ) && (touch out/target/product/generic_x86/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests )"
/bin/bash: line 1: 21667 Segmentation fault: 11  ( out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy )
[ 78% 63453/80802] build out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/treble_sepolicy_tests_26.0
FAILED: out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/treble_sepolicy_tests_26.0
/bin/bash -c "(out/host/darwin-x86/bin/treble_sepolicy_tests -l 		out/host/darwin-x86/lib64/libsepolwrap.dylib  -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts 		-b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/26.0_mapping.combined.cil 		-o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/built_26.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy 		-u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil 		--fake-treble ) && (touch out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/treble_sepolicy_tests_26.0 )"
/bin/bash: line 1: 21668 Segmentation fault: 11  ( out/host/darwin-x86/bin/treble_sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/26.0_mapping.combined.cil -o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_26.0_intermediates/built_26.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy -u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil --fake-treble )
[ 78% 63454/80802] build out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/treble_sepolicy_tests_27.0
FAILED: out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/treble_sepolicy_tests_27.0
/bin/bash -c "(out/host/darwin-x86/bin/treble_sepolicy_tests -l 		out/host/darwin-x86/lib64/libsepolwrap.dylib  -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts 		-b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/27.0_mapping.combined.cil 		-o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/built_27.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy 		-u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil 		--fake-treble ) && (touch out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/treble_sepolicy_tests_27.0 )"
/bin/bash: line 1: 21670 Segmentation fault: 11  ( out/host/darwin-x86/bin/treble_sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -b out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy -m out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/27.0_mapping.combined.cil -o out/target/product/generic_x86/obj/ETC/treble_sepolicy_tests_27.0_intermediates/built_27.0_plat_sepolicy -p out/target/product/generic_x86/obj/ETC/sepolicy_intermediates/sepolicy -u out/target/product/generic_x86/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil --fake-treble )
21:05:28 ninja failed with: exit status 1

#### failed to build some targets (02:10:52 (hh:mm:ss)) ####

问题的答案

  1. Catalina编译android 10报错
    • 只有问题解决方法 , 没有问题解决思路
    1. tom 手动补丁 网络引导 : https://android-review.googlesource.com/q/I31744acd018ea4c980c46a9979bbad17ae1c4f68
    2. tom 手动补丁 , 网络引导: https://android-review.googlesource.com/q/I1e2f4095795daead6eb96280d60a122c51ba66ba
  2. Macos catalina上android源码编译不过问题解决措施
    • 从这里了解到 AOSP 问题讨论网站
    • 从这里搜索关键字Fix sepolicy_tests on Mac 10.15即可找到这个答案
    • 现在能想到的困难就是 , 如果遇到新问题这个关键字选定和大量结果的阅读和识别也有点困难的
  3. [BigSur 11.1 编译 Android10 报错] : 在上述问题的基础上添加 11.1 字段即可 , 但是还有其他未能逾越的异常

3.6. adb sync 执行失败

# 执行失败
➜  aosp adb sync 
/Volumes/beyourself/AOSP/aosp/out/target/product/generic_x86/data/: 5 files pushed. 37.9 MB/s (1141778 bytes in 0.029s)
adb: error: failed to copy '/Volumes/beyourself/AOSP/aosp/out/target/product/generic_x86/system/framework/ipmemorystore-aidl-interfaces-V1-java.jar' to '/system/framework/ipmemorystore-aidl-interfaces-V1-java.jar': remote couldn't create file: Read-only file system

# 观察状况
➜  aosp adb root
adbd is already running as root

➜  aosp adb shell

generic_x86:/ # cd system/ 

eneric_x86:/system # ls -l

drwxr-xr-x  2 root root   4096 2020-09-14 02:09 framework

generic_x86:/system # whoami
root

# 说明即使是 root 用户也没有 framework 文件夹的写权限 , 虽然看起来是有的

# 关闭安全验证
adb disable-verity
# 重新启动
adb reboot
adb root

# 重新挂载文件系统失败
adb remount
  1. 一个解决方案(暂未验证)
  2. 重新挂载文件系统失败

我是页脚

clone.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

kotlin 克隆对象的方法

  1. 继承 kotlin.Cloneable

    • 这种方式的问题在于某些对象属性不是真正的克隆 , 而是引用复制
    class TetrisSquareDelegate : SquareDelegate(), Cloneable {
        var calculateWidth: Int = 0        /*控件水平尺寸(宽度) , 在 OnMeasuer 计算得出*/
        var calculateHeight: Int = 0       /*控件垂直尺寸(高度) , 在 OnMeasuer 计算得出*/
    
        public override fun clone(): TetrisSquareDelegate {
            return super.clone() as TetrisSquareDelegate
        }
    }
  2. Gson 序列化/反序列化

    • 这种方式当需要 clone 的类是子类的时候需要额外代码 , 不推荐这一思路
      1.
    • 异常信息:Unable to invoke no-args constructor for interface kotlin.Lazy. Registering an InstanceCreator with Gson for this type may fix this problem.
      • 反序列化对象中存在 by lazy 参数也会导致此异常
    /** 快速复制对象 , 不只是复制索引
    * 也可以通过对象继承 kotlin.Cloneable 实现这一能力
    * */
    inline fun <reified T> Any.cloneObj(): T {
        return this.toJsonString().toObjFromJsonString<T>()
    }
    
    inline fun Any.toJsonString(): String = Gson().toJson(this)
    
    inline fun <reified T> String.toObjFromJsonString(): T = Gson().fromJson(this, T::class.java)
  3. 反序列化子类问题可以参考

    1. 关键类 : 文档
    2. Google已经发布了自己的RuntimeTypeAdapterFactory来处理多态性,但不幸的是,它不是gson核心的一部分(您必须将类复制并粘贴到项目中)。

我是页脚

Dex文件结构-1.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

一、 背景

从代码阅读中我们间歇性记录的一点小细节。

二、 细节们

关键文件:android-4.4.4_r1\dalvik\libdex\DexFile.h

Dex 文件结构
DexHeader

三、 代码

3.1、 基础数据

/*
 * These match the definitions in the VM specification.

    unit*_t : * 代表 bit(位) uint8_t 代表无符号整数所占内存为 1字节(8bit)
    u* 或者 s*  : * 代表字节 u1 说明,u1 所表示的数据所占内存为 1字节。
 */
typedef uint8_t             u1;
typedef uint16_t            u2;
typedef uint32_t            u4;
typedef uint64_t            u8;
typedef int8_t              s1;
typedef int16_t             s2;
typedef int32_t             s4;
typedef int64_t             s8;

3.2、 DexHeader

/*
 * Direct-mapped "header_item" struct.
 */
struct DexHeader {
    u1  magic[8];           /* includes version number */
    u4  checksum;           /* adler32 checksum */
    u1  signature[kSHA1DigestLen]; /* SHA-1 hash */
    u4  fileSize;           /* length of entire file */
    u4  headerSize;         /* offset to start of next section */
    u4  endianTag;
    u4  linkSize;
    u4  linkOff;
    u4  mapOff;
    u4  stringIdsSize;
    u4  stringIdsOff;
    u4  typeIdsSize;
    u4  typeIdsOff;
    u4  protoIdsSize;
    u4  protoIdsOff;
    u4  fieldIdsSize;
    u4  fieldIdsOff;
    u4  methodIdsSize;
    u4  methodIdsOff;
    u4  classDefsSize;
    u4  classDefsOff;
    u4  dataSize;
    u4  dataOff;
};

对于符合规范的 DEX 文件来说:

  1. magic 所占内存为 8 字节 64 位。
    • 前四字节代表#define DEX_MAGIC "dex\n"

    • 后四字节有两种可能

      • 新版本 API(13,+∞) :#define DEX_MAGIC_VERS "036\0"
      • 旧版本 API(-∞,13] :#define DEX_MAGIC_VERS_API_13 "035\0"
    • 用表格表示:

      API\Byte Index 0 1 2 3 4 5 6 7
      API(13,+∞) d e x \n 0 3 6 \0
      API(-∞,13] d e x \n 0 3 5 \0

我是页脚

android.provider.CallLog.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

android.provide.CallLog.java

API 25

一、属性

两个比较重要的属性是

  1. public static final String AUTHORITY = "call_log";
  2. public static final String SHADOW_AUTHORITY = "call_log_shadow";
    • @hide 因此我们不再详究

有关 call_log 的拼装包括如下:

  1. CallLog.CONTENT_URI = Uri.parse("content://" + AUTHORITY);
  2. CallLog.Call.CONTENT_URI = Uri.parse("content://call_log/calls");
    • CallLog.Call.CONTENT_URI_WITH_VOICEMAIL = ``

我是页脚

下载 ndk .md

我是页眉


[正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文](https://github.com/TomGarden/tom-notes/blob/master/_posts/Collections/Android/AndroidStudio/下载 ndk .md)

2018-03-05 17:29:48

今天下载 ndk 出现连接超时的现象,通过代理服务器下载有感觉太慢。

于是直接手动下载下来了,下载之后有不太确定如何使用,在网络上查找也没有找到确切的操作指南。

在中期 AndroidSutido 之后连接超时的现象不修自复了

  • 这个时候我已经手动下载了 ndk-build(android-ndk-r16b-linux-x86_64.zip)但是不确定如何使用
  • 当 AndroidStudio 自动化操作完成后通过观察发现:
    • 自动下载并自动解压之后的文件目录比手动下载并解压后的文件目录多出一个文件:package.xml,当然了该文件不一定会起到什么作用。因为打开查看里面是一些版权信息。

总结,下次出现连接超时的状况完全可以手动下载并且解压到默认目录: ~/sdk/ndk-build


我是页脚

ConnectivityManager.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

ConnectivityManager

public class ConnectivityManager
extends Object
java.lang.Object
   ↳ 	android.net.ConnectivityManager 

Class that answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.

The primary responsibilities of this class are to:

  1. Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)
  2. Send broadcast intents when network connectivity changes
  3. Attempt to "fail over" to another network when connectivity to a network is lost
  4. Provide an API that allows applications to query the coarse-grained or fine-grained state of the available networks
  5. Provide an API that allows applications to request and select networks for their data traffic

Instances of this class must be obtained using Context.getSystemService(Class) with the argument ConnectivityManager.class or Context.getSystemService(String) with the argument Context.CONNECTIVITY_SERVICE.


我是页脚

OS_Read_1.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

但凡想要进行一些细节操作的时候都会因为对 Android 系统的一些操作不了解而感到困惑 .

目的 : 这次是在完善 lib_pickcolor 的时候 , DialogFragment 的状态保存不知道怎么保存函数参数(kotlin) ,
但是 SDK 提供的 AlertDialog 却是可以保存部分自己的按钮实现代码的 , 所以想模仿它 , 又无从下手 ,
所以就再次来到 AOSP 了 .

路线 : 从 App 启动入手 , 这样的话能预见到的重点为:

  1. Activity 启动流程 , 生命周期过程
  2. 切换横竖屏过程中 Activity 生命周期变化细节
  3. 依赖 Activity 生存的 Fragment 的生命周期变化细节
  4. 由 Fragment 持有的 Dialog 的随着 宿主 生命周期变化所产生的响应状态存储于重建

嗯 , 日拱一卒

0x00. 最自然的我们就从桌面点击启动一个应用开始分析

我们的代码版本(编译虚拟机的版本和源代码的版本是相同的)

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=10
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
HOST_ARCH=x86_64
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-19.5.0-x86_64-10.15.5
HOST_BUILD_TYPE=release
BUILD_ID=QQ3A.200605.002.A1
OUT_DIR=out
============================================
  1. 我们知道桌面也是一个 应用层的 APP , 但是忘记了这个应用叫什么名字 , 查看进程名 猜测是 nexuslauncher
  2. 现在需要查看这个应用程序的源代码做出部分修改来验证这一猜测
  3. 失败描述: (没有使用源代码编译模拟器)尝试在 launcher MAIN Activity 打断点 , 完全无法完成断点 : 断点失败原因未知
    • 系统应用找了一圈只直到 setting app 断点成功才做此记录
  4. 成功描述: (使用当前源码编译虚拟机)重新编译一次, 查看 Luncher 完全在掌控之中, 看来早晚是需要一个 pixel 的

0x01. 感受

当看到 Launcher.java 一个文件 2000+ 行代码 , 我就告诉自己我一定不能傻傻的一行一行读 ,

  • 一定要按需跳读 , 保证脉络清晰就好 , 不要在细节上花费过多时间

0x02. 门槛

这一小节可以先跳过, 后面碰到困难的时候可以回来寻找对应的细节

2.1. 关于 Android 通信机制的细节

0x02. APP 启动流程 从 Launcher 点击作为起点

2.1. Launcher 进程的事件跟进

大致脉络如下 , 看代码的时候参考这个脉络自然是清晰的

  1. 点击事件监听
  2. Activity.startActivity
  3. Activity.startActivityForResult
  4. IActivityTaskManager.startActivity
    //aosp/frameworks/base/core/java/android/app/Instrumentation.java
    int result = ActivityTaskManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);
    至此 IActivityTaskManager.aidl 文件在 IPC C/S 架构中的 server 端实现代码就是我们要寻找的目标
    • IPC 服务端会实现 IActivityTaskManager.Stub
    • 所以可以通过全局检索 extends IActivityTaskManager.Stub ,
      来找到 server 端接口实现 , 从而了解 startActivity 的调用细节 .
      事实是恰好只有一个实现类: aosp/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    • 需要注意的是, 如果要断点 ActivityTaskManagerService 需要针对进程 system_process , 而不是应用进程

2.2. SystemProcess 进程的事件跟进

2.2.1. startActivity

2.2.2. startActivity 如何触发 activityPaused

从图中吸收吧

在这一部分存疑的问题 , 在真正触发新进程创建之前的判断逻辑跟进暂未完成 ,
因为如果无需新建进程的情况下 , 是不会触发后续流程的 .

2.2.3. 触发新进程启动动作

  • ActivityTaskManagerService.activityPaused , 触发后续动作 .
  • ActivityStackSupervisor.startSpecificActivityLocked 通过进程间通信 , 做进一步触发
  • LocalService.startProcess 是一个较为明确的入口 , 进入后续动作

startSpecificActivityLocked:1008, ActivityStackSupervisor (com.android.server.wm)
resumeTopActivityInnerLocked:3040, ActivityStack (com.android.server.wm)
resumeTopActivityUncheckedLocked:2578, ActivityStack (com.android.server.wm)
resumeFocusedStacksTopActivities:1159, RootActivityContainer (com.android.server.wm)
completePauseLocked:1843, ActivityStack (com.android.server.wm)
activityPausedLocked:1770, ActivityStack (com.android.server.wm)
handleMessage:455, ActivityStack$ActivityStackHandler (com.android.server.wm)
dispatchMessage:107, Handler (android.os)
loop:214, Looper (android.os)
run:67, HandlerThread (android.os)
run:44, ServiceThread (com.android.server)

2.2.*. 进程日志梳理

  1. ActivityTaskManagerService.startActivity

  2. ActivityTaskManagerService.activityPaused

    • 核心代码由这个流程入口触发, 所以我们有理由相信 当前 Activity 的 startActivity 动作
      会触发 当前 activity 的 activityPaused 动作 , 进而有更多额外操作
  3. 现在需要跟进的是 startActivity 如何触发 activityPaused 动作

    • 了解 startActivity 更多细节查看是否有触发 activityPaused 的动作

    • 如果在这里是在找不到还有一个思路 , 更深入的理解 Binder 看看通信更深入的细节或需有帮助

    • 创建新 Task 的时候也做了应用和系统进程间的 binder 通信

      • 已经厘清 , 首次进入这个调用栈 , 没有执行有效的逻辑就返回了
      • 但是发送了 Handler 通信 , 可以监听这个通信点 , 但是不用监听信息发送的整个流程了
    • 找到了 哇哈哈哈哈哈 , 通过 Binder 通信告知 Launcher 暂停自身

      • 猜测后续会触发 ActivityTaskManagerService.activityPaused
    • 进程间通信流程固然重要, 厘清各个进程内部的线程间通信也十分必要 ,
      尤其是 System-process 进程中的线程间通信

    • 感觉上有一个 Handler 在做循环等待 Client 做部分修正

  4. ActivityTaskManagerService.startActivity 在断点的调试的时候会有多次调用 , 需要理解

    • 应该尝试在了解之前内容的情况下将断点延后
  5. 至此我们可以继续下一步跟进动作了

  • 第一次完整跟进 , 我们并没有抓住重点 , 直到新的 Activity 启动完成 都没有找到合理的重点代码
    但是这其中到是存在一个 handler 对象 , 或需是突破 , 再看看吧 .
  • 既然如此我们不要急于找到与启动 Activity 启动相关的关键点 , 虽然这是最终目的
    我们暂时把精力转移到理解这一个调用流程上, 看看都做了什么事情, 然后逐个了解这几个事情, 最终定位到 Activity 的启动细节
  • 第二次完整跟进 , 还是没有抓到在重点 , 但是有一点可以关注一下 , 那就是目标应用进程的启动
    • 在 Launcher 应用启动新应用的过程中我们一共有三个进程参与这个动作
      • Launcher 进程 , 负责 UI 交互 , 获取目标 Activity 的初始信息
      • System 进程 , 负责启动目标 Activity 进程
        • 前两次跟丢了就是在这里跟丢的 , System 进程启动目标应用进程的动作我们没有准确锁定 , 启动目标应用进程后的后续动作我们没有跟踪到
        • 掐卡在进程启动入口了, 我们先定位进程启动位置 , 后定位 activity 启动位置
  • 第三次完整跟进还是无功而返
    • 其中有的地方也进行了函数传递 , 可以再留意一下
  • 后来查阅了 Android 系统源代码分析中的相关章节 , 由于不同版本代码已经有了较大变化 .
    • 我们在关键的代码位置 Process.start(...) 断点发现调用栈是来自
    • ServiceThread -> HandlrThread -> Looper -> 略
    • 这说明我们对 Handler 通信机制细节还有可以深入理解的地方
    • https://developer.android.com/guide/components/bound-services#Messenger
      • Handler.sendMsg 并非都能引起 handleMessage 回调 , 携带 Runnable 的 sendMsg 就是一个例子
      • Handler.post 也不能引起 handleMessage 回调
      • 这一部分可以先解析一下再继续回到 Application 启动的流程中去
      • 带着问题去看 , 先明确启动新 APP 过程中使用的是什么方法再继续
        • 包含 sendMessage(message.setCallback(...)) 的调用

  • 注意力来到 ActivityStack 了

  • 能监控的启动调用流程中没有找到 ActivityStack 相关的可以联想的内容 , 暂时还是考虑 Handler 通信吧

  • ActivityStack$ActivityStackHandler 这个类重点观察下相关内容

    • Handler 可能是突破口 , 只是我们丢失了另一个接口 , 暂时无法完成两个接口的对接
    • 可以暂时将启动动作放到流程图避免再次丢失
  • 有了实质性的进展现在需要搞清楚的点如下

    1. 尽可能理解进入创建进程代码之前的逻辑
    • 这有助于理解相同个的函数会有多次调用这个问题 , 正是这个多次调用的问题导致我们一直无法跟踪到重点代码
    • 关于 RootActivityContainer.resumeFocusedStacksTopActivities 被调用两次这件事需要继续跟进 ,
      这个是发现被调用两次的首个函数 , 尝试去探寻它的上层调用逻辑 , 明确调用两次的原因
    • 经过探查确认了进入 ActivityTaskManagerService 现在应该关注两个路径
      • ActivityTaskManagerService$startActivty > 此调度入口可以探寻
      • ActivityTaskManagerService$activityPaused > 此调度入口暂时未知
      • 所以我们大概需要回到 Launcher 进程重新观察一下了 > 做过了没有特殊的收获
    • 虽然我们还不知道 ActivityTaskManagerService$activityPaused 的调度入口, 但仍然可以跟进下这个流程
      • 如果只在这个入口打断点 , 会发现在断点阻断之前 , 新应用进程已经启动完成了 , 所以这里不是启动流程的关键点
      • 把这个调用流视作干扰信息 , 是不行的, 应该以这里为起点做断点或者日志调试, 做更多的观察和收集 ,
        从而判断这个调用到底是否重要的调用
      • 也可以对比下两个启动流的参数差异
      • 现在应该考虑一下两个 ActivityStack 的调度流程了

    DONE - 下一步是需要辨析 ClientLifecycleManager 对象中的函数调用差异以及在客户端进程中的细节差异
    下一步重新编译 framework
    - 循环节点已经完成插桩
    - 记得先解决可能发生的异常再编译 , 预计使用部分编译动作

    1. 搞清楚创建新进程的动作细节是怎样一步一步进行操作的
    • 搞清楚这一点再考虑如何在新进程创建新的 Activity
    • 单凭断点优点容易误判 , 我们需要日志系统重新编译
      • 日志调用
      • 编译文件输出到指定位置
      • 部分编译
  1. AOSP 中如何获取当前进程信息 , 进程名
  • 定制一个精简的日志工具 , 帮助更快更精准的代码定位
  • 进程和 沙盒 / 虚拟机 相关 > 尝试理解这一部分内容

2.2.2. onPause 多次调用验证

┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Thread: Binder:1819_11
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ Binder.execTransact  (Binder.java:994)
│    Binder.execTransactInternal  (Binder.java:1021)
│       IActivityTaskManager$Stub.onTransact  (IActivityTaskManager.java:1981)
│          ActivityTaskManagerService.activityPaused  (ActivityTaskManagerService.java:1714)
│             ActivityStack.activityPausedLocked  (ActivityStack.java:1769)
│                ActivityStack.completePauseLocked  (ActivityStack.java:1842)
│                   RootActivityContainer.resumeFocusedStacksTopActivities  (RootActivityContainer.java:1161)
│                      ActivityStack.resumeTopActivityUncheckedLocked  (ActivityStack.java:2577)
│                         ActivityStack.resumeTopActivityInnerLocked  (ActivityStack.java:3039)
│                            ActivityStackSupervisor.startSpecificActivityLocked  (ActivityStackSupervisor.java:1007)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ ActivityStackSupervisor.startSpecificActivityLocked
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────

┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ Thread: Binder:1819_11
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ Binder.execTransact  (Binder.java:994)
│    Binder.execTransactInternal  (Binder.java:1021)
│       IActivityTaskManager$Stub.onTransact  (IActivityTaskManager.java:1981)
│          ActivityTaskManagerService.activityPaused  (ActivityTaskManagerService.java:1714)
│             ActivityStack.activityPausedLocked  (ActivityStack.java:1769)
│                ActivityStack.completePauseLocked  (ActivityStack.java:1882)
│                   RootActivityContainer.ensureActivitiesVisible  (RootActivityContainer.java:810)
│                      RootActivityContainer.ensureActivitiesVisible  (RootActivityContainer.java:823)
│                         ActivityDisplay.ensureActivitiesVisible  (ActivityDisplay.java:1315)
│                            ActivityStack.ensureActivitiesVisibleLocked  (ActivityStack.java:2184)
│                               ActivityStack.makeVisibleAndRestartIfNeeded  (ActivityStack.java:2389)
│                                  ActivityStackSupervisor.startSpecificActivityLocked  (ActivityStackSupervisor.java:1007)
├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
│ ActivityStackSupervisor.startSpecificActivityLocked
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────

2.3. 相关类小计

ActivityMetricsLogger

  • 侦听活动启动,过渡,可见性更改和窗口绘制的回调,以确定应用程序启动时间和绘制延迟。 活动指标的真实来源,并提供有关Tron,logcat,事件日志和WaitResult的数据。

RootActivityContainer

0x03. 疑点问题

提醒

  • 设计模式应该跟上了 , 不然会有不必要的阻碍
  • 如果有必要记得重新编译 一个 模拟器

进度存档

  1. AOSP 调试已经可用 , 下一步应该进行 Activity 启动流程的探究
  • 卡壳在 aidl 通信的位置了 , 我们搞清楚这个调用流程
  1. aidl 通信例程 , 已经完成 , 已经理解 aidl 通信使用流程
  • 存疑, service 在宿主进程未启动的情况下, 无法被其他进程启动
  1. Luncher 应用作为客户端通过 IPC 机制将新应用的启动信息传送到 IActivityTaskManager 服务端
  • 现在卡壳在 IActivityTaskManager 服务端代码的出处了
  • 下一步要搞清楚这个 IActivityTaskManager 是如何发挥作用的

参考

➜  generic_x86 emulator -help  
Android Emulator usage: emulator [options] [-qemu args]
  options:
    -list-avds                     list available AVDs
    -sysdir <dir>                  search for system disk images in <dir>
    -system <file>                 read initial system image from <file>
    -writable-system               make system image writable after 'adb remount'
    -datadir <dir>                 write user data into <dir>
    -kernel <file>                 use specific emulated kernel
    -ramdisk <file>                ramdisk image (default <system>/ramdisk.img
    -image <file>                  obsolete, use -system <file> instead
    -initdata <file>               same as '-init-data <file>'
    -data <file>                   data image (default <datadir>/userdata-qemu.img
    -partition-size <size>         system/data partition size in MBs
    -cache <file>                  cache partition image (default is temporary file)
    -cache-size <size>             cache partition size in MBs
    -no-cache                      disable the cache partition
    -nocache                       same as -no-cache
    -sdcard <file>                 SD card image (default <datadir>/sdcard.img
    -snapstorage <file>            file that contains all state snapshots (default <datadir>/snapshots.img)
    -no-snapstorage                do not mount a snapshot storage file (this disables all snapshot functionality)
    -snapshot <name>               name of snapshot within storage file for auto-start and auto-save (default 'default-boot')
    -no-snapshot                   perform a full boot and do not do not auto-save, but qemu vmload and vmsave operate on snapstorage
    -no-snapshot-save              do not auto-save to snapshot on exit: abandon changed state
    -no-snapshot-load              do not auto-start from snapshot: perform a full boot
    -snapshot-list                 show a list of available snapshots
    -no-snapshot-update-time       do not do try to correct snapshot time on restore
    -wipe-data                     reset the user data image (copy it from initdata)
    -avd <name>                    use a specific android virtual device
    -skindir <dir>                 search skins in <dir> (default <system>/skins)
    -skin <name>                   select a given skin
    -no-skin                       deprecated: create an AVD with no skin instead
    -noskin                        same as -no-skin
    -memory <size>                 physical RAM size in MBs
    -cores <number>                Set number of CPU cores to emulator
    -accel <mode>                  Configure emulation acceleration
    -no-accel                      Same as '-accel off'
    -ranchu                        Use new emulator backend instead of the classic one
    -engine <engine>               Select engine. auto|classic|qemu2
    -netspeed <speed>              maximum network download/upload speeds
    -netdelay <delay>              network latency emulation
    -netfast                       disable network shaping
    -code-profile <name>           enable code profiling
    -show-kernel                   display kernel messages
    -shell                         enable root shell on current terminal
    -no-jni                        disable JNI checks in the Dalvik runtime
    -nojni                         same as -no-jni
    -logcat <tags>                 enable logcat output with given tags
    -no-audio                      disable audio support
    -noaudio                       same as -no-audio
    -audio <backend>               use specific audio backend
    -radio <device>                redirect radio modem interface to character device
    -port <port>                   TCP port that will be used for the console
    -ports <consoleport>,<adbport> TCP ports used for the console and adb bridge
    -onion <image>                 use overlay PNG image over screen
    -onion-alpha <%age>            specify onion-skin translucency
    -onion-rotation 0|1|2|3        specify onion-skin rotation
    -dpi-device <dpi>              specify device's resolution in dpi (default 165)
    -scale <scale>                 scale emulator window (deprecated)
    -http-proxy <proxy>            make TCP connections through a HTTP/HTTPS proxy
    -timezone <timezone>           use this timezone instead of the host's default
    -dns-server <servers>          use this DNS server(s) in the emulated system
    -cpu-delay <cpudelay>          throttle CPU emulation
    -no-boot-anim                  disable animation for faster boot
    -no-window                     disable graphical window display
    -version                       display emulator version number
    -report-console <socket>       report console port to remote socket
    -gps <device>                  redirect NMEA GPS to character device
    -shell-serial <device>         specific character device for root shell
    -tcpdump <file>                capture network packets to file
    -bootchart <timeout>           enable bootcharting
    -charmap <file>                use specific key character map
    -prop <name>=<value>           set system property on boot
    -shared-net-id <number>        join the shared network, using IP address 10.1.2.<number>
    -nand-limits <nlimits>         enforce NAND/Flash read/write thresholds
    -gpu <mode>                    set hardware OpenGLES emulation mode
    -camera-back <mode>            set emulation mode for a camera facing back
    -camera-front <mode>           set emulation mode for a camera facing front
    -webcam-list                   lists web cameras available for emulation
    -screen <mode>                 set emulated screen mode
    -force-32bit                   always use 32-bit emulator
    -selinux <disabled|permissive> Set SELinux to either disabled or permissive mode
    -unix-pipe <path>              Add <path> to the list of allowed Unix pipes
    -fixed-scale                   Use fixed 1:1 scale for the initial emulator window.
    -wait-for-debugger             Pause on launch and wait for a debugger process to attach before resuming
    -skip-adb-auth                 Skip adb authentication dialogue

     -qemu args...                 pass arguments to qemu
     -qemu -h                      display qemu help

     -verbose                      same as '-debug-init'
     -debug <tags>                 enable/disable debug messages
     -debug-<tag>                  enable specific debug messages
     -debug-no-<tag>               disable specific debug messages

     -help                         print this help
     -help-<option>                print option-specific help

     -help-disk-images             about disk images
     -help-debug-tags              debug tags for -debug <tags>
     -help-char-devices            character <device> specification
     -help-environment             environment variables
     -help-virtual-device          virtual device management
     -help-sdk-images              about disk images when using the SDK
     -help-build-images            about disk images when building Android
     -help-all                     prints all help content

我是页脚

OS_Source_download-1.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

娱乐线路

  1. 安装并维护 Ubuntu 。
    • JDK 安装
    • 依赖安装:
      • sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl valgrind
        • 提示无法找到 libwxgtk2.6-dev 所以我们先拿出它来。
        • libwxgtk2.6-dev
          • 下载安装提示缺少更多的依赖,于是查看了下在 Ubuntu 16.04 中的 libwxgtk2.6-dev 已经升级到 libwxgtk3.0-dev
            • 查询命令:apt-cache search libwxgtk
          • 所以我们暂时安装 3.0 版本吧(有问题再折回)。
      • 所以上述命令可以更改为
        • sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk3.0-dev build-essential zip curl valgrind
  2. 下载 Android 源代码
    • 下载指定版本的 Android 源码
    • 我们下载的版本为 android-2.3.1-r1
  3. 编译异常&修复
    • JDK 版本不对,应该使用 JDK 6
    • Checking build tools versions...
      ============================================
      PLATFORM_VERSION_CODENAME=REL
      PLATFORM_VERSION=2.3.1
      TARGET_PRODUCT=generic
      TARGET_BUILD_VARIANT=eng
      TARGET_SIMULATOR=
      TARGET_BUILD_TYPE=release
      TARGET_BUILD_APPS=
      TARGET_ARCH=arm
      HOST_ARCH=x86
      HOST_OS=linux
      HOST_BUILD_TYPE=release
      BUILD_ID=GRH78
      ============================================
      Checking build tools versions...
      build/core/prebuilt.mk:91: *** recipe commences before first target.  Stop.
      

参考 & 摘录

  1. https://source.android.com/

已经下载过 AOSP 之后希望切换编译版本应该怎么做

repo 命令

切换某个版本的命令:

  • repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-10.0.0_r39

其中 android-4.0.1_r1 即为我们即将切换的编译版本 , 这实际上是一个 AOSP 分支 , 那么如何查看我们可选分支有哪些呢?

  1. 通过 Google AOSP 查看

我是页脚

spawn-fcgi包装app异常文件疑问.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

https://stackoverflow.com/q/72180366/7707781

1. 问题 :

直接命令行通过 spawn-fcgi 启动的程序 , 如果发生 crash 如何收集 core 文件 ?

2. 背景 & 环境

探索 C++ Web 编程

  1. web-server : nginx
  2. 网关(FastCGI) : fastcgipp 3.0
  3. CGI Wrapper : spawn-fcgi .
    不是 Nginx 提供的 FCGI Wrap .
    当然 FCGI Wrap 使用的也是 spawn-fcgi , 这是题外话 .
  4. 自己编写的 C++ 程序 (crash_demo)

3. 问题复现步骤

  1. crash_demo 故意 throw "测试异常, 观察 core 文件" , 编译生成 crash_demo.run
  2. sudo nginx -c my_nginx_custom.config
  3. ulimit -c unlimited
  4. spawn-fcgi -a 127.0.0.1 -p 9000 -f /path/crash_demo.run
  5. 测试正常访问路径 , 可以正常完成 HTTP 访问 .
  6. 触发 carsh_demo , 得到 5xx 异常页面 , 但是 crash_demo.run 所在目录没有看到 core 文件

猜测(2是我倾向的答案)

  1. core 文件没有生成
  2. core 文件生成了 , 但是我不知道文件位置 ;

有人知道问题所在吗 ?

======================================================

1. Question

I run "crash_demo.run" by spawn-fcgi .
How to collect core file .

2. Background & Environment

I'm exolore C++ Web Programming .

  1. web-server : nginx
  2. CGI(FastCGI) : fastcgipp 3.0
  3. CGI Wrapper : spawn-fcgi
    • I didn't use FCGI Wrap which ngifix supplied .
    • I understand FCGI Wrap be drive by spawn-fcgi , Of course this is off topic .
  4. My c++ application . (be called crash_demo) .

3. Step to reproduce exception

  1. crash_demo insert code throw "test exception str, check _core_ file" , build got crash_demo.run
  2. run nginx : sudo nginx -c my_nginx_custom.config
  3. ulimit -c unlimited
  4. run crash_demo.run by spawn-fcgi : spawn-fcgi -a 127.0.0.1 -p 9000 -f /path/crash_demo.run
  5. test the normal http request , and http request can be completed normally .
  6. test the crash_demo http request , got 5xx response .
    • The directory where crash_demo.run is located does not see the core file

My guess

  1. core file not generate .
  2. core file is generated , but i don't the file path .

Does anyone know what happened?



Solution update

My question is flawed .

Thanks @sehe , my step :

  1. I read two webpage
    1. https://man7.org/linux/man-pages/man5/core.5.html
    2. https://zhuanlan.zhihu.com/p/240633280
  2. update my /proc/sys/kernel/core_pattern
    • core -> core_%e_%p_%t
  3. ulimit -c unlimited
  4. spawn-fcgi -a 127.0.0.1 -p 9000 -f /path/crash_demo.run
  5. sudo find / core_ | grep core_crash_demo
    • result /path/core_crash_demo._5080_1652169152

So , my guess on my question is failed .

The fact is , I don't generate core file , when my question.

When my generated core file successed , the core file path is crash_demo.run parent directory .



Solution update 2

再次遇到此问题 , 我们想做两件事

  1. 搞清楚 core dump 文件生成的细节
  2. core dump 文件如何使用

core dump 文件生成的细节

主要参考内容 : core manual

core manual 中设计的点很多 , 不同的情况可能遇到不同的问题, 不过基本可以确认,阅读此文件可以解决大多数问题。
这里我只写出自己关注的点。

要生成 core dump 有几个前提条件 :

  • 对于 core dump 文件的大小 ,有系统层面的限制 , 可以通过 命令 ulimit 查看和修改
    • ulimit -a 查看 ; ulimit -c unlimited 修改
  • 关于 修改 /proc/sys/kernel/core_pattern ,
    • 默认的内容一般为 core , 除非被修改过
    • 如果文件的首个字符是 | 意味通过管道后进一步执行后续命令 , 细节需要再细读文档,不再展开。
    • 我们修改为 core_%e_%p_%t -> core_可执行文件名_pid_时间戳
    • 修改命令为 : sudo bash -c 'echo core_%e_%p_%t > /proc/sys/kernel/core_pattern'
      • 如果修改为 /tmp/core_%e_%p_%t , core dump 会放到 /tmp 目录下

再次执行异常程序后可以使用 find 命令查找 core 文件位置了

  • sudo find / core_ | grep core_
  • 我的 core 文件就生成在异常 调用程序语句所执行的文件夹
    • 程序在 ~/a/b/c/d/exe.run
    • 调用为 ~$ /a/b/c/d/exe.run
    • core 文件位置为 ~/core

core dump 文件如何使用

  1. 使用 vscode 调试 有 ui 更直观些 , launch.json 增加 属性 coreDumpPath : https://code.visualstudio.com/docs/cpp/cpp-debug#_memory-dump-debugging
  2. 也可以直接使用 gdb , 略。

Solution update 2 (English)

we whant to know two point :

  1. how generate core dump file
  2. how to fine exception code by core dump file

how generate core dump file?

Reference the file : core manual

core manual write many point , I just list the point i care :

  1. system limit core dump file size , we need unlimit it:
  • ulimit -a check limit / ulimit -c unlimited cancel limit
  1. fix /proc/sys/kernel/core_pattern
  • default value is core
  • fix it to -> core_%e_%p_%t mean core_your_execute_file_name_pid_timestemp
  • fix cmd : sudo bash -c 'echo core_%e_%p_%t > /proc/sys/kernel/core_pattern'

now run your exception , you can got core file .

  • maby you need search it : sudo find / core_ | grep core_

how to fine exception code by core dump file ?

======================================================

1. Question

Ngins server , HTTP post request with header -H 'Content-Length , not response .

But , if not Content-Length header, the result is normal .

2. Background & Environment

I'm exolore C++ Web Programming .

  • web-server : nginx
  • CGI(FastCGI) : fastcgipp 3.0
  • CGI Wrapper : spawn-fcgi
    • I didn't use FCGI Wrap which ngifix supplied .
    • I understand FCGI Wrap be drive by spawn-fcgi , Of course this is off topic .
  • My c++ application .

3. Example

without header Content-Length

curl -X POST 'http://104.225.154.215:8080/fcgi_test/' \
     -H 'Content-Length: 135' \
     -v \
'{
  "synthetics_condition": {
    "name": "Check Failure",
    "monitor_id": "XXX",
    "runbook_url": "XXX",
    "enabled": true
  }
}'
*   Trying 104.225.154.215...
* TCP_NODELAY set
* Connected to 104.225.154.215 (104.225.154.215) port 8080 (#0)
> POST /fcgi_test/ HTTP/1.1
> Host: 104.225.154.215:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 135
> 
* Empty reply from server
* Connection #0 to host 104.225.154.215 left intact
curl: (52) Empty reply from server
curl: (3) nested brace in URL position 29:
{
  "synthetics_condition": {
    "name": "Check Failure",
    "monitor_id": "XXX",
    "runbook_url": "XXX",
    "enabled": true
  }
}
                            ^
* Closing connection 0


我是页脚

c-c++语法.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

1. TEMP_FAILURE_RETRY(表达式)

涉及的知识点为 GNU-C 扩展

  • 位置:unsited.h
/* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno'
   set to EINTR.  */

# define TEMP_FAILURE_RETRY(expression) \
  (__extension__							      \
    ({ long int __result;						      \
       do __result = (long int) (expression);				      \
       while (__result == -1L && errno == EINTR);			      \
       __result; }))

作用:当表达式的值为为 -1 并且 errno 为 EINTR 的时候进入死循环,直到不满足循环条件。

extension 关键字

  • gun/c 的常用扩展语法
  • 该关键字gnu对c语言的扩展,我们都加上了__extension__关键字,如果不加__extension__关键字,当我们编译的是加上-pedantic选项时,会产生警告信息,__extension__关键字就是说使用gun对c语言的扩展,编译时加上-pedantic选项不要产生警告信息

复合语句

  • 标准C中,表达式指的是运算符和操作数的组合,而复合语句指的是由一个或多个被括在花括号里的语句构成的代码块。在标准C中,不允许将复合语句用于表达式中。
  • 在GNU C中,允许用小括号括起来的复合语句出现在一个表达式中。这个表达式的类型为复合语句中以分号结尾的最后一个子语句表达式的类型,其值也为最后子表达式的值。

我是页脚

2018-08-09- android.util.Log.md

我是页眉


[正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文](https://github.com/TomGarden/tom-notes/blob/master/_posts/Collections/Android/Android_API_DOC/2018-08-09- android.util.Log.md)


layout: post
title: null
date: 2018-08-09 14:25:03 +0800
categories: jekyll update
author: Tom


目录

  • jekyll 的 kmarkdown 负责解析
    {:toc}


android.util.Log

API 用于打印日志。

通常一应该是用 Log.v(),log.d(),log.w(),log.e 和 log.e() 方法写日志。然后你可以在 Logcat 查看日志

日志的优先级顺序为:

  • V(VERBOSE) — 详细(最低优先级)
  • D(DEBUG) — 调试
  • I(INFO) — 信息
  • W(WARN) — 警告
  • E(ERROR) — 错误
  • A — 断言

除非在开发期间Verbose(详细信息)永远不应该编译到应用中。Debug日志在运行的应用中应该被除去。ERROR/WARNING应该永远保留在应用中。

提示:在应用中声明 TAG 是一个不错的实践,声明之后用该 TAG 作为参数调用日志方法。

//声明
private static final String TAG = "MyActivity";
//调用
Log.v(TAG, "index=" + i);

当你构建的字符串传递到 Log.d,编译器使用一个 StringBuilder 至少发生三次分配:StringBuilder 本身,缓冲区,String 对象。实际上还有另一次缓冲分配和复制,对于 GC 的压力更大。就是说,如果你的日志消息被过滤掉,将Android系统将做大量工作并产生大量开销。


我是页脚

1.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)

  • 用于从给定的 dex jar apk 文件中解析出 class
    • dexPath 通过{@code File.pathSeparator}分隔代表待加载文件路径的变量 (jar/apk)
    • optimizedDirectory (路径)用于存放优化后的文件 not null
    • libraryPath 通过{@code File.pathSeparator}分隔代表待加载文件路径的变量 (native)

我是页脚

README.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

Android 系统源代码分析

好我们就开始娱乐了。

  1. 关于 Android 源代码,如果打开 https://source.android.com 你会发现一个新世界。
    • 这个世界如此的奇妙和纷繁多彩。

这个文件夹中的内容需要及时梳理和对外分享

分享到 tom-notes 的关联目录中

通过 AndroidStudio 查看 Android 源代码的动作细节


我是页脚

OS_Run_emulator.md

我是页眉


正则匹配链接[]()语法上有局限性 , 如有疑虑可查看本文原文

0x01. 运行编译 AOSP 之后生成 模拟器

下载 AOSP 编译完成后直接执行 emulator 即可运行刚刚编译好的镜像

在 aost/out 目录中可以找到启动模拟器所需要的景象文件 , 要启动这个模拟器 , 在编译完成后直接执行
emulator 即可

但是当设备重启后再想运行这个模拟器 :
0. cd aosp_path

  1. source build/envsetup.sh
  2. lunch 当时编译的那个版本号其他的没有测试
    • 我暂时用的这个 : aosp_x86-eng 第 23 个选项
  3. emulator
    • 可以通过 which emulator 来查看可执行文件位置

0x02. 运行环境

另外的说明, 我的移动硬盘有完整的代码和编译产物 , 内存不足的 PC 包含

  1. 未执行编译动作的源码(实际上在编译过程中由于内存不足失败, 执行了 m clean)
  2. 硬盘编译产物文件夹 aosp/out/target 拷贝到 PC

如果这种使用方式无法满足后续的需求再想办法清理 PC 硬盘或者换设备

  • 拷贝到 PC 就不用带太多零碎了 , 也不担心接触不良什么的硬件问题

0x03. 修改 emulator 参数

修改屏幕尺寸 , 参照 ~/.android/avd 文件中的配置文件 confit.ini 进行修改和验证即可

关于购买硬件运行编译版本镜像问题:

关键词: BL / CID / V版 / 美版 / 港版

参考 > 解决问题

  1. 直接运行编译时候的相关命令即可运行模拟器了

参考 > 没有解决问题但是扩大了了解面

  1. emulator 由两个执行文件
  2. emulator 用 sdk/emulator/emulator 执行黑屏
    • 我看应该是这个 emulator 版本过低 , 通过这个调整方式也没有解决问题
  3. 可能需要控制模拟器内核
  4. 购买硬件设备的经验
  5. 使用本地编译成功的镜像文件启动Android模拟器
  6. 直接运行编译时候的相关命令即可运行模拟器了

我是页脚

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.