记一次在AOSP上装Google Play的尝试
记一次在AOSP上装Google Play的尝试结果
背景
最近在工作中有需要用到 Google Play 来验证一些事情。
但是我手中的测试机Pixel5刷了 AOSP 是不具备 Google Play 的环境的。
经过多次调研 & 尝试在 AOSP 上安装 Google Play都已失败告终
1.NikeGapps(Pixel 5 不能刷 Recovery)
2.bitgapps(Pixel 5 不能刷 Recovery)
3.microGapps(存在一些兼容问题)
在无意间发现了一篇文章StackOverflow
文章大致内容是说可以通过提取官方镜像中的 APK,导入到 AOSP 中。
虽然这篇文章很早之前都看过,但是觉得比较麻烦,就没尝试。
本文章也算是最终尝试的记录。(要是还不行我真撂挑子了 这个 GP 谁爱装谁装了 : )
过程12.14日——失败确认官方镜像的版本通过Settings -> About Phone -> Build Number 可知AOSP 的版本
我的是 TQ3A.230901.001.C2 其实也就是 androi ...
SurfaceViewSync机制
Android13 SurfaceView Sync机制引入
1.当我是一名初级Android开发者的时候,有一个概念一直灌输给我——Android是单线程渲染,有且只有主线程能渲染UI.
实际上并不是如此,除开普通的普通的View如TextView,ImageView .
Android其实是支持子线程渲染的——SurfaceView.
2.SurfaceView的渲染帧不跟随View渲染,也就是说不归ViewRootImpl管。单独的Surface,单独渲染
特立独行是有代价的,SurfaceView的异步绘制会带来一些UI呈现的问题。
比如View渲染和SurfaceView的渲染不同步,只要SurfaceView or View渲染任意一个渲染快了就会导致UI呈现上的不一致。
假如有一个需求场景:简单来说是一个视频播放的页面,其中包含一些普通的控件 & 用于播放视频的SurfacView.具体的需求如下
需要播放器和页面中的其他控件一起渲染。因为SurfaceView渲染早了会导致只有一个光秃秃的视频在播,渲染晚了SurfaceView会有黑屏。这都是不好的用户体 ...
Magisk基础
Magisk基础项目源代码地址
Magisk是什么?有什么用?
Magisk是一个开源的用于获取Root权限的框架
Magisk可以用于获取手机Root权限
Magisk如何使用
具体的使用可见手册
官方手册
简单来说:
环境需要:
已经解除BootLoader锁。
已经安装adb、fastboot工具(以及驱动)
系统boot镜像
使用步骤:
根据是否有ramdisk分区确认初始镜像,如果有获取系统的boot/init_boot镜像,如果没有获取recovery镜像
使用Magisk App对初始进行进行patch操作
使用fastboot刷入boot/init_boot/recovery镜像
Magisk项目源代码环境配置
具体内容可见
官方手册
1.设置环境
先下载Magisk项目
1git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git
然后下载Magisk定制的ndk
1./build.py ndk
2.编译项目
12345678910 ...
Compose源码环境搭建
Compose源码环境搭建
进行Compose源代码环境构建。
Compose Compiler:1.5.1
前言
为什么需要使用Linux作为搭建环境?(指跑源代码)
这肯定不是我想用Linux开发,因为Compose项目的限制
a. 我们可以看一部分project的manifest声明,发现什么?项目依赖了ios的sdk,linux的sdk,就是没有Windows。这想表明什么就不言而喻了
b. 通过查看Compose项目的一部分的文件你也能发现一些端倪,没有gradlew.bat?所以使用Windows跑环境会有一些问题的。
(不清楚是否能跑。但是绝对是要做一些配置的。)
为什么选择配置Compose Compiler的Release环境?
很简单,如果你拉取最新的commit项目未必能跑起来,是否稳定你只能求助开发者。
这是因为开发分值是feature最多的分值,而且你不清楚他是否是开发完成的,这种项目的不稳定因素肯定就尽可能控制下。
(问就是踩过坑。)
Release的版本号为什么选择1.5.1
我们可以查看下目前的Compose Compiler Rel ...
Gradle构建流程
Gradle构建流程
前面我们分析了Gradle的Daemon启动。后续我们需要对Gradle的构建流程进行分析(粗略分析)
缘起
前面分析到,Gradle的Daemon启动源于Client Connector连接。
由于Client连接了Server,Server在没有启动的时候才会进行Fork启动。
启动后的Server并不会构建,因为Server也不知道Client要干嘛,因为Server还没有Client的构建信息。
所以接下来会介绍Gradle构建的触发。
(其实上部分Daemon启动的解析中有提到——也就是Connect accept过程会触发构建流程)
1234567891011121314151617181920212223242526272829303132public class DaemonTcpServerConnector implements DaemonServerConnector { // ...... @Override public Address start(final IncomingConnection ...
Gradle Daemon启动分析
Gradle Server Start
Server的启动主要是进行初始化和环境的准备
主要可以分为如下几个过程
Bootstrap:启动进程,设置ClassLoader
Init:初始化成员,初始化Socket
Wait:进程keep-alive,防止main线程死亡,休眠等待。
Bootstrap
前面分析到了Gradle会通过ProcessBuilder开启一个Deamon进程
并调用shell
12java -cp *gradle-launcher-7.6.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon
BootStrap
和Client启动类似
12345public class GradleDaemon { public static void main(String[] args) { ProcessBootstrap.run("org.gradle.launcher.daemon.bootstrap.DaemonMain", args) ...
ShadowHook原理分析
ShadowHook原理分析
初始化
无论是使用Native初始化还是Java进行初始化。最后其实都会调用到shadowhook_init方法
init的实际初始化逻辑包含如下几个过程
errno init
信号量处理初始化(sigsegv、sigbus)
enter、exit初始化
mode相关初始化
a) shared: safe_init + hub_init
b) unique: linker_init
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152int shadowhook_init(shadowhook_mode_t mode, bool debuggable) { bool do_init = false; // check是否没有初始化 if (__predict_true(SHADOWHOOK_ERRNO_UNINIT == shadowhook_init_errno)) { s ...
Shadowhook基础使用
ShadowHook
什么是ShadowHook
请看官网
ShadowHook 是一个 Android inline hook 库,它支持 thumb、arm32 和 arm64。
基础概念inline-hook
Inline-hook 通过直接修改目标函数的机器指令来实现。通常情况下,会将目标函数的开头几条指令替换为跳转指令,指向一段插入的代码。这段插入的代码可以执行额外的操作,例如记录函数参数、修改函数返回值,或者完全改变函数的执行逻辑。
——from Gemini(快说:谢谢Gemini)
Android 的Native Hook技术有两类,PLT Hook & Inline Hook
PLT Hook用于有外部的依赖库调用的Hook。
Inline Hook用于Hook内部库的调用
如下是是PLT Hook和Inline Hook的使用场景以及区别
Plt Hook
Inline Hook
shadow hook
Shadow hook是一个Inline Hook框架。
Shadow Hook基础使用Quick Start
Note: 具体可见 ...
bhook基础原理分析
BHook原理解析基础概念PLT/GOT hook
BHook是一个plt/got hook框架。
plt/got hook是指,利用动态链接过程的特点。
即——使用PLT表作为跳板查got表来查询被调用函数的地址在哪。
如果我们修改GOT表内的地址就可以实现劫持函数的执行过程。
示例
test.c
1234567#include <stdio.h>void sayHell() { printf("Hello World");}int main() { sayHello();}
PLT/GOT hook前
hook 后
Relocation
即重定位,讲符号引用转化为直接引用。
说直白点就是:
编译器在编译一个库函数调用的时候,编译器本身是不知道你调用的地址在哪,所以会直接用0填充
于此同时他会在.rela中生成一条记录(我们暂且称之为“坑位“),告知来着,哪个函数调用需要填充地址。
Relocation即填坑的过程。
静态链接
对于 ...
使用C/C++解析ELF文件
ELF文件解析
关于ELF文件我们可以看下面这张大图(总结地很到位)
Note:
由于目前x86 64位架构为主流,后续分析主要是基于Elf64进行分析、介绍
Demo 源代码地址
结构体介绍
文件包含(usr/include/elf.h)
1#include <elf.h>
准备工作
12345#include <stdio.h>int main() { printf("Hello World!");}
1gcc test.c -o test
Elf64_Ehdr
结构体
12345678910111213141516171819#define EI_NIDENT (16)typedef struct{ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf64_Half e_type; /* Object file type */ Elf64_H ...