本文分三篇。本篇提供一个最小的修改案例。更详细的修改请参考篇三:

http://blog.csdn.net/aimingoo/article/details/7939132

(前三节有关背景介绍请至:http://blog.csdn.net/aimingoo/article/details/7939093)

4、修改前的准备工作
=======
这里介绍一些Android上的逆向工程的基础。首先,我们要操作Phone.apk,它其实也就是一个.zip文件,其中包括四个主要信息:
  - 资源文件:res\*.*和resources.arsc
  - 代码文件:classes.dex
  - 应用描述:AndroidManifest.xml
  - 签名信息:META-INF\*.*
apktool这个工具可以处理前三种数据,而签名信息则必须使用一个signapk.jar(有些工具包称为AutoSign)。

1)解包(缺省至Phone目录)
apktool d -f Phone.apk

注意我们接下来的修改都不会动到资源,所以事实上也可以不解开其中的资源文件。可以这样使用命令行:
apktool d -f -r Phone.apk

这样在编译回去的时候会快一点,而且也可以避免一些错误。——但很多时候的修改需要对照着资源文件来看,所以你也可以解一份有资源文件的版本放在旁边作参照。

2) 编译回.apk(指定从Phone目录)
apktool b -f Phone Phone2.apk

3) 对Phone2.apk加签名
java -jar signapk.jar platform.x509.pem platform.pk8 Phone2.apk Phone2_signed.apk

注意这时使用的签名文件为platform.x509.pem和platform.pk8,而不是我们平常用的testkey*.*。这是很关键的一处:Phone.apk必须使用platform.*来签名。

5、修改:初步
=======
我们将Phone.apk解到Phone目录之后。可以找到如下子目录:
Phone\smali\com\android\phone\

我们接下来主要修改两个文件:
CallCard.smali
InCallScreen.smali
注意这里的*.smali是另一种格式的源代码,它反编译自Dalvik虚拟机中执行码(opcode)。基本上,你可以认为这*.smali就是汇编代码(基于寄存器的虚拟机引擎)。好吧,但我们既然要“原生的”,那么就只好来改改这些汇编代码了。:(

1)对InCallScreen.smali只需要做一处修改
---------
找到:

 .field private mMainFrame:Landroid/view/ViewGroup;

改成:

 .field public mMainFrame:Landroid/view/ViewGroup;

我们需要在CallCard.smali中访问这个成员,所以它必须是公开的(public)。

2) 修改CallCard.smali,针对updateDisplayForPerson()方法
---------
找到:

 .method private updateDisplayForPerson(Lcom/android/internal/telephony/CallerInfo; ...

在该方法中,找到唯一一处showCachedImage()调用:

 invoke-static {v0, v1}, Lcom/android/phone/CallCard;->showCachedImage(Landroid/widget/ImageView;Lcom/android/internal/telephony/CallerInfo;)Zmove-result v4if-nez v4, :cond_2

注意两点,一是我们要修改这个:

 if-nez v4, :cond_2

所以要先记下这个cond_2。第二点,上面的v0, v1, v4可能在具体的代码中有所不同,这也要留意,查找时不能依据这些寄存器。而修改时,也要注意寄存器的冲突和使用,有修改经验的就不多言了;没有经验的,则要仔细回顾一下汇编语言的知识。

接下来,我们改动上述一行,使之变成为:

## ===》》》if-eqz v4, :cond_20move-object/from16 v0, p0move-object/from16 v5, p4invoke-virtual {v0, v1, v5}, Lcom/android/phone/CallCard;->showCachedBackground(Lcom/android/internal/telephony/CallerInfo;Lcom/android/internal/telephony/Call;)Zmove-result v4goto :cond_2:cond_20
## end fix.

这里,if-nez变成了if-eqz,而:cond_20这一标签用于插入一段代码,当这些代码执行完成时,仍然会到:

 goto :cond_2

这就是上面要记住cond_2的原因。至于:cond_20是可以随意取的,编译程序是按16进制自动升序来编号这些标签,而0x20号标签一般已经比较大了,不会与现有的标签冲突。当然,写成cond_30或cond_50也行的。

此外,这里还必须要注意v0, v5, v1和v4这四个寄存器的使用,必须参考这里的代码上下文为决定使用哪些个空闲的寄存器。其中v1是继承使用了前面的寄存器值,如果此前v1中不是放着CallerInfo的话,则要根据上下文再调整。反正,如果寄存器用错了的话……哈哈……Crash~~

【注:有一个简单的法子可以避免用错寄存器的问题,就是在将方法开始处的.locals nnn这里的nnn值改大几个,需要用几个寄存器,就加上几个。然后在我们插入的代码中,只使用最后的这几个寄存器号,也就不会冲突了。例如原来是.locals 4,改成.locals 8,则v4,v5,v6,v7这新添加的4个寄存器号,就总是安全的。】

3) 修改CallCard.smali,针对updatePhotoForCallState()方法
---------
这里的修改与上一例是相似的,只不过是针对updatePhotoForCallState()方法而已。找到:

    invoke-static {v9, v3}, Lcom/android/phone/CallCard;->showCachedImage(Landroid/widget/ImageView;Lcom/android/internal/telephony/CallerInfo;)Zmove-result v9if-nez v9, :cond_2  ## 《《《《===修改此处

改动上面最后一行。变成:

## ===》》》if-eqz v9, :cond_20move-object/from16 v5, p1invoke-virtual {p0, v3, v5}, Lcom/android/phone/CallCard;->showCachedBackground(Lcom/android/internal/telephony/CallerInfo;Lcom/android/internal/telephony/Call;)Zmove-result v9goto :cond_2:cond_20
## end fix.

4) 添加新上面代码所需要的方法:showCachedBackground()
---------
上面两段函数都调用了一个方法,这个showCachedBackground()是我们这里“来电全屏大头贴”的主要功能实现代码。其它的修改,其实只是插个桩而已。代码如下,把它直接插到CallCard.smali这个文件的某个方法前/后面就可以了(我一般将它放在showCachedImage()函数声明的后面):

##
## 【主函数:更新全屏大头贴】
##
.method public showCachedBackground(Lcom/android/internal/telephony/CallerInfo;Lcom/android/internal/telephony/Call;)Z.locals 6.parameter "ci".parameter "call".prologueinvoke-virtual {p2}, Lcom/android/internal/telephony/Call;->getState()Lcom/android/internal/telephony/Call$State;move-result-object v0invoke-virtual {v0}, Lcom/android/internal/telephony/Call$State;->isAlive()Zmove-result v0if-nez v0, :cond_0:goto_0return v0:cond_0if-nez p1, :cond_1:goto_1const/4 v0, 0x0goto :goto_0:cond_1iget-boolean v2, p1, Lcom/android/internal/telephony/CallerInfo;->isCachedPhotoCurrent:Zif-eqz v2, :goto_1iget-object v2, p1, Lcom/android/internal/telephony/CallerInfo;->cachedPhoto:Landroid/graphics/drawable/Drawable;if-eqz v2, :goto_1iget-object v3, p0, Lcom/android/phone/CallCard;->mInCallScreen:Lcom/android/phone/InCallScreen;const/16 v4, 0xF0invoke-virtual {v2}, Landroid/graphics/drawable/Drawable;->getIntrinsicWidth()Imove-result v5if-lt v5, v4, :goto_1const/16 v4, 0xF0invoke-virtual {v2}, Landroid/graphics/drawable/Drawable;->getIntrinsicHeight()Imove-result v5if-lt v5, v4, :goto_1iget-object v3, v3, Lcom/android/phone/InCallScreen;->mMainFrame:Landroid/view/ViewGroup;if-eqz v3, :goto_1invoke-virtual {v3, v2}, Landroid/view/ViewGroup;->setBackgroundDrawable(Landroid/graphics/drawable/Drawable;)Vconst/16 v2, 0x8iget-object v3, p0, Lcom/android/phone/CallCard;->mPhoto:Landroid/widget/ImageView;invoke-virtual {v3, v2}, Landroid/widget/ImageView;->setVisibility(I)V##    const/16 v2, 0x0
##    invoke-virtual {p0, v2}, Lcom/android/phone/CallCard;->setPersonInfoStyle(Z)Vgoto :goto_0
.end method

6、对初步修改的说明
=======
除了2、3步中的插桩代码之外,整个功能其实就依赖一个完全手写汇编的showCachedBackground()。它需要操作到当前类CallCard的

 CallCard.InCallScreen.mMainFrame

成员。而该成员在InCallScreen类中被声明为private,所以需要在第1步中把InCallScreen中的该声明改成public。

showCachedBackground()的思路很简单。由于CallCard.smali总是要从“联系人”中装载头像,而此前我们已经用“HD Contact Photos”把这个头像存成了“高清、全屏大头贴(图片)”,那么就只要将这个取出来的头像贴在背景上就可以了。

高清全屏来电大头贴,不就是把大头贴在背景上嘛。^^.

所以在分析整个Phone.apk时,我发现它原本取到一个mPhoto之后,为了便于显示就将它存在CallerInfo.cachedPhoto里了。既如此,那么在原有流程的updatePhotoForCallState()与updateDisplayForPerson()方法中,当它调用showCachedImage()来显示了图片之后,我们也就只需要把这个图片在背景上“贴”一下就可以了。

而这个背景,就是:CallCard.InCallScreen.mMainFrame

很简单嘛。

上面的showCachedBackground()汇编代码翻译成java代码就是:

public boolean showCachedBackground(CallerInfo paramCallerInfo, Call paramCall)
{// 电话是在用状态(来电或呼出或接通)boolean bool = paramCall.getState().isAlive();// paramCallerInfo.isCachedPhotoCurrent有效bool = bool && (paramCallerInfo != null) && paramCallerInfo.isCachedPhotoCurrent;if (bool) {Drawable localDrawable = paramCallerInfo.cachedPhoto;if ((localDrawable.getIntrinsicWidth() < 240) || (localDrawable.getIntrinsicHeight() < 240)) {bool = false}else {// 置mMainFrame的背景this.mInCallScreen.mMainFrame.setBackgroundDrawable(localDrawable);// 使mPhoto不显示(原来的头像就不必显示了嘛)this.mPhoto.setVisibility(8);// 修改作个人信息的显示风格(备用,后文解释)// setPersonInfoStyle(false);}}return bool;
}

Android玩乐系列:修改汇编代码支持原生高清来电大头贴(二)相关推荐

  1. Android玩乐系列:修改汇编代码支持原生高清来电大头贴(一)

    [ 本文分三篇.本篇重在介绍"全屏来电大头贴"的问题,想直接切入技术细节的请径直前往篇二: http://blog.csdn.net/aimingoo/article/detail ...

  2. Android玩乐系列:修改汇编代码支持原生高清来电大头贴(三)

    [ 本文分三篇.本篇介绍更复杂的定制过程. ] (接下来进一步细化上一篇的修改,前六节请参见:http://blog.csdn.net/aimingoo/article/details/7939116 ...

  3. android11内置壁纸,iPhone11官方自带原生高清壁纸

    iPhone11官方自带原生高清壁纸,苹果iPhone 11/Pro/Max默认原生主题壁纸.在凌晨的发布会中新推出了几款新的iPhone手机,其中还为大家推出了几款新的原生高清壁纸,小编为大家第一时 ...

  4. 【移植Linux 3.4.2内核之四】修改内核代码支持YAFFS文件系统

    上一篇文章,我们从0制作jffs2文件系统,因为我们的内核本身就支持iffs2文件系统,但是它不支持yaffs文件系统.今天我们就来修改内核代码,让内核支持yaffs文件系统的格式. 1.首先我们获取 ...

  5. 爬虫入门,带你用30行代码爬取高清美女写真,附安装包+源码

    1.准备工作 1 高清壁纸:https://www.36992.com/girls/list-1.html 2 Python环境 Python3.9新特性: 字典"并集"运算符 类 ...

  6. android怎么监听多点触摸_110寸高清触摸一体机

    110寸高清触摸一体机也是叫110寸会议平板,110寸高清触控一体机,110寸教学培训触控一体机,110寸展厅触摸一体机,110寸高清交互会议机,110寸展示查询触摸一体机,110寸移动壁挂触控显示屏 ...

  7. 如何评价2022年数维杯国际赛C题【如何使用大脑结构诊断阿尔茨海默病】【D题:拉尼娜事件】思路模型代码全套资料+高清代码结果图+完整源程序+论文

    资料获取方式我放到下面了,欢迎小伙伴一起学习交流 2022数维杯国际赛C题:https://mbd.pub/o/bread/Y5yVlp1x2022年数维杯国际赛[D题:拉尼娜事件]思路模型代码全套资 ...

  8. android 相机功能修改,Android11不再支持更改默认相机程序,再也不能用美颜相机拍照了...

    据悉,最细Android11系统将不再支持更改默认相机程序,原因是以保护隐私为由,据悉更新了安卓11之后你就再也不能用各种美颜相机拍照,只能使用默认相机拍照了,具体情况如何快和Xda小编一起看看吧. ...

  9. html2canvas源码修改,html2canvas把div保存高清图的方法代码

    http://www.bootcdn.cn/(可以搜索html2canvans) 1.选择html2canvas版本(这个版本可以放大倍数保证图片清晰) 默认生成的canvas图片在retina设备上 ...

最新文章

  1. IDEA 打可执行jar包(maven项目)
  2. Linux中的cron计划任务配置详解
  3. C风格字符串与C++风格字符串
  4. Android 6.0 源代码编译实践
  5. volatile学习
  6. Ubuntu安装vbox(virtualbox)
  7. 回忆NWT开工,还要吾亲自布网线
  8. 【运动学】基于matlab匀变速直线运动规律【含Matlab源码 978期】
  9. 计算机组成原理课程要求及目的,计算机组成原理-教学大纲
  10. Matlab美图秀秀
  11. 关于CityEngine导入shp数据
  12. 企业全面运营管理沙盘模拟心得_企业经营沙盘模拟心得体会
  13. win10前置耳机插孔没声音_iqoo耳机突然没声音-杰讯手机维修中心
  14. docx4j文档差异比较
  15. 苹果更新失败无法连接服务器未响应,iPhone 更新失败怎么办?更新 iOS 常见的错误代码及解决方法(二)...
  16. Vue.filter过滤器存储单位换算按KB 、M、 G显示字节大小
  17. vs2013编译ffmpeg之二十六 opus、shine
  18. 国际宏观变化20221204
  19. 带缓冲的输入/输入流
  20. Spring-循环依赖(circular dependencies)

热门文章

  1. 小黑子—Java从入门到入土过程:第六章
  2. 什么是Java面向对象(实例详解)
  3. sort函数怎么用mysql_实例详解sort()函数的原理和使用方法
  4. 学习一下秒杀系统的设计,以及需要考虑的问题
  5. 《动手学深度学习》戴口罩的胡萝卜组 - 户建坤 第一次打卡 (线性, Softmax, 多层感知机, 文本预处理, 语言模型, RNN)
  6. 初探机器学习之使用百度EasyDL定制化模型
  7. 【数据可视化】 D3+ArcGIS 迁徙图实现
  8. Windows Server 2008 R2域控组策略设置禁用USB
  9. Android 中替换开机动画(附动画包)
  10. ThinkPHP开发手册学习笔记