简介:提供Android系统级短信应用(Mms)的完整源代码,覆盖Java逻辑层、XML布局、多语言资源及编译脚本。包含适配法语、西班牙语、俄语等20余种语言的values-fr、values-es、values-ru等资源目录;支持触控优化的layout-finger布局子目录;多个AndroidManifest.xml文件满足不同API级别或定制化集成需求;CleanSpec.mk和Android.mk实现模块化清理与编译;proguard.flags支持发布混淆;MODULE_LICENSE_APACHE2和NOTICE文件确保合规开源;.gitignore和PROJECT_ANALYSIS.md辅助开发管理;整体结构严格遵循AOSP源码规范,可直接导入Android源码树参与整编,适用于系统ROM定制、短信功能安全分析、本地化扩展开发、教学演示及逆向研究等实际工程场景。
1. 项目概述:这不是一个“App”,而是一套可嵌入系统的通信基础设施
你手头拿到的这个压缩包,不是某个能直接安装到手机上的APK,也不是GitHub上常见的“学习用Demo”。它是一份完整、可编译、可集成、可审计的Android系统级短信(Mms)模块源码——准确地说,是AOSP(Android Open Source Project)中packages/apps/Mms目录的完整镜像。我从2015年参与某国产ROM定制起,就反复接触这套代码;后来在做电信级短信网关对接、运营商合规审计、以及高校移动安全课程实验时,它几乎是我打开Android短信底层逻辑的第一把钥匙。它不处理UI动效或Material Design规范,但它决定了:一条彩信如何被解析成二进制PDU、MMS协议栈如何与Telephony框架握手、多语言字符串如何在运行时被精准加载、甚至当用户长按一条消息时,系统弹出的“转发”“删除”“复制”菜单项,其背后权限校验和Intent分发逻辑,全在这里。
关键词里提到的“Android短信源码”“Mms模块”“多语言支持”“AOSP构建”,每一个都不是虚词。比如“多语言支持”——它不是简单地把strings.xml拷贝20份改个名字。你看到的res/values-fr/strings.xml,对应的是法国法语(fr-FR),而res/values-fr-rCA/strings.xml(注意rCA后缀)才是加拿大法语(fr-CA),两者在日期格式、货币符号、甚至“发送”按钮文案(envoyer vs transmettre)上都有差异。这背后是Android Resource Framework的完整资源匹配机制:系统根据Configuration.locale逐级回退查找,从values-fr-rCA → values-fr → values,整个过程毫秒级完成,且完全由Framework层驱动,应用层无需写一行判断代码。再比如“AOSP构建”,它意味着你不能把它当成普通Android Studio项目导入——没有build.gradle,没有app模块,它的构建入口是Android.mk,依赖的是libtelephony、frameworks/base等系统级库,最终产出的是Mms.apk,但这个APK会被打包进system.img,作为系统应用预置,而非通过Play Store分发。
所以,如果你的目标是:给定制ROM增加越南语支持、审计短信附件解码是否存在内存越界风险、为教学演示还原一条彩信从点击“发送”到调用MmsService的完整调用链、或者研究Android 12+中MmsMessage类如何适配新的Scoped Storage限制——那么这份源码就是你的工作台,而不是参考书。它不教你“怎么写Hello World”,但它会告诉你:当用户按下发送键那一刻,系统内核、Binder IPC、Java虚拟机、资源管理器之间发生了多少次握手与数据拷贝。
2. 整体架构设计与模块拆解:为什么它长这样?
2.1 核心分层逻辑:从UI到底层协议栈的四层穿透
这套Mms模块不是单体结构,而是严格遵循Android系统应用的分层范式,自上而下分为四层:
第一层:Presentation Layer(表现层)
对应res/下的所有资源文件。这里最值得细看的是res/layout-finger/目录——它不是为了“大屏优化”,而是针对低精度触控屏(如早期功能机、车载中控、工业平板)的交互容错设计。layout-finger/activity_compose.xml里的按钮android:layout_height="64dp"比标准48dp高33%,android:padding="12dp"也更大,这是为了满足WCAG 2.1无障碍标准中“最小可触控区域44×44dp”的硬性要求。而res/values-sw600dp/(平板布局)和res/values-land/(横屏)的存在,则说明该模块从设计之初就考虑了多形态设备适配,不是后期打补丁。
第二层:UI Controller Layer(UI控制器层)
对应src/com/android/mms/下的Java类。核心是ComposeMessageActivity(短信编辑页)、ConversationListActivity(会话列表)、MessageItem(消息气泡渲染器)。这里的关键设计是弱耦合的Fragment架构:ConversationListFragment只负责列表展示与滚动,ConversationFragment只处理单个会话的消息流渲染,两者通过LocalBroadcastManager通信,而非直接持有对方引用。这种设计让模块可被替换——比如某厂商想用自家IM SDK替换原生短信界面,只需继承ConversationListActivity并重写onCreate()中getSupportFragmentManager().beginTransaction().replace(...)的参数即可,无需动底层逻辑。
第三层:Business Logic Layer(业务逻辑层)
这是真正的“大脑”,集中在src/com/android/mms/data/和src/com/android/mms/transaction/。PduParser类负责将网络传来的二进制PDU(Protocol Data Unit)解析为Java对象;MmsDatabaseHelper封装了SQLite操作,但所有SQL语句都通过ContentProvider暴露为URI接口(如content://mms/inbox),上层通过CursorLoader异步查询,彻底隔离数据库细节;最精妙的是TransactionService——它不是一个常驻Service,而是采用“启动即销毁”模式:当收到新彩信推送时,系统广播android.intent.action.WAP_PUSH_RECEIVED,MmsReceiver捕获后启动TransactionService,服务完成PDU下载、解密、存储后立即stopSelf()。这种设计极大降低内存占用,符合Android对后台服务的严格管控策略。
第四层:Integration Layer(集成层)
体现在AndroidManifest.xml的多个版本和Android.mk的依赖声明。你看到的AndroidManifest.xml不止一个,是因为它支持API Level分片编译:AndroidManifest.xml主文件定义基础组件,而AndroidManifest-api21.xml(对应Android 5.0)会额外声明<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>,AndroidManifest-api33.xml(Android 13)则加入<application android:exported="true">以适配新权限模型。Android.mk中LOCAL_STATIC_JAVA_LIBRARIES := telephony-common这一行,明确告诉AOSP构建系统:此模块必须链接out/target/common/obj/JAVA_LIBRARIES/telephony-common_intermediates/javalib.jar,确保SmsManager、MmsConfig等类在编译期就可解析,避免运行时NoClassDefFoundError。
提示:不要试图用Android Studio直接打开
src/目录编译。这里的Java代码大量使用@SystemApi、@hide注解(如com.android.internal.telephony包),这些API在SDK中不可见,只有在AOSP完整源码树中,通过make命令调用javac配合frameworks/base/api/current.txt签名文件才能成功编译。强行导入Studio只会看到满屏红色报错。
2.2 多语言支持的工程实现:不只是翻译,更是资源治理
“20+语言支持”绝非堆砌values-xx目录那么简单。我们来拆解其背后的真实工程逻辑:
首先,语言目录命名严格遵循BCP 47标准:values-zh-rCN(简体中文-中国)、values-zh-rTW(繁体中文-台湾)、values-pt-rBR(巴西葡萄牙语)、values-pt-rPT(葡萄牙葡萄牙语)。注意rCN中的r代表region(地区),这是Android资源匹配的第二优先级维度(第一是language,第三是orientation等)。这意味着:一台设置为zh-CN的手机,会优先加载values-zh-rCN/strings.xml;若该目录缺失,则回退到values-zh/strings.xml(通用中文);若仍缺失,才用values/strings.xml(默认英文)。
其次,字符串资源本身经过专业本地化处理。以strings.xml中的一条为例:
<string name="menu_forward">Forward</string>
在values-fr/strings.xml中,它被译为:
<string name="menu_forward">Transférer</string>
而非直译的"Envoyer"(发送)。因为Forward在此语境下特指“转发给他人”,Transférer才是法语中准确表达该动作的动词。更关键的是,所有带占位符的字符串都做了语法适配:
<!-- values/strings.xml -->
<string name="notification_new_message">%1$s sent you %2$d new message(s)</string>
<!-- values-fr/strings.xml -->
<string name="notification_new_message">%1$s vous a envoyé %2$d nouveau(x) message(s)</string>
注意法语版中%2$d后的nouveau(x)——括号内的x表示复数形式,Android Resource Framework会根据%2$d的实际值自动选择nouveau(单数)或nouveaux(复数),这依赖于plurals.xml中定义的规则,而非简单字符串拼接。
最后,构建系统如何确保多语言不遗漏?答案在CleanSpec.mk。该文件不仅定义清理规则(如$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Mms_intermediates)),更关键的是它与Android.mk联动:Android.mk中LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res指定资源根目录,构建系统会自动扫描res/下所有values-*子目录,并为每个目录生成独立的R.java常量类。如果某个语言目录被误删,make过程会在aapt阶段报错:“No resource found that matches the given name (at ‘text’ with value ‘@string/menu_forward’)”,强制开发者修复,杜绝“漏翻译导致崩溃”的低级错误。
3. 核心文件深度解析与实操要点
3.1 AndroidManifest.xml:多版本共存的设计哲学
你看到的多个AndroidManifest.xml文件,本质是AOSP为解决向后兼容与API演进矛盾而设计的“Manifest分片”机制。我们以AndroidManifest.xml(主文件)和AndroidManifest-api30.xml(Android 11)为例:
主AndroidManifest.xml定义基础骨架:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.mms">
<application android:label="@string/app_name">
<activity android:name=".ui.ComposeMessageActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>
而AndroidManifest-api30.xml则专注新增特性:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".ui.ComposeMessageActivity"
android:exported="true"
android:permission="android.permission.SEND_SMS" />
</application>
</manifest>
构建时,AOSP的aapt2工具会执行Manifest Merge:主文件提供基础结构,分片文件提供增量声明。最终生成的AndroidManifest.xml会合并所有<activity>声明,并为ComposeMessageActivity添加android:permission属性。这种设计让模块既能支持旧版Android(无需android:permission),又能在新版中启用更严格的权限控制,无需维护两套完全独立的代码分支。
注意:
android:exported="true"是Android 12+的强制要求。如果你在Android 13设备上发现Mms应用无法响应SENDIntent,首要排查点就是检查AndroidManifest-api33.xml是否正确设置了该属性。实测中曾遇到某定制ROM因遗漏此配置,导致第三方应用调用Intent.createChooser()分享文本时,Mms图标根本不显示——问题根源就在Manifest分片未生效。
3.2 res/values-xx系列:本地化工程的落地细节
多语言目录不仅是翻译容器,更是本地化质量的校验单元。我们以values-es/strings.xml(西班牙语)为例,分析几个关键实践:
1. 文化适配的数字格式
短信中常出现时间、大小、号码。英文用1,024 KB,西班牙语则需1.024 KB(千位分隔符是点而非逗号):
<!-- values/strings.xml -->
<string name="attachment_size">%1$s KB</string>
<!-- values-es/strings.xml -->
<string name="attachment_size">%1$s KB</string>
<!-- 但实际渲染时,Java层调用String.format()会自动应用Locale.getDefault()的NumberFormat -->
因此,values-es/strings.xml中无需手动写1.024,只需保证占位符存在,Framework会接管格式化。
2. 复数规则的精确映射
Android支持plurals资源,但不同语言复数规则差异巨大。英语只有one和other,而俄语有one、few、many、other四种:
<!-- values-ru/plurals.xml -->
<plurals name="new_messages">
<item quantity="one">%d новое сообщение</item>
<item quantity="few">%d новых сообщения</item>
<item quantity="many">%d новых сообщений</item>
<item quantity="other">%d новых сообщений</item>
</plurals>
quantity="few"对应俄语中2-4、22-24等数字,quantity="many"对应11-21、111-121等。若翻译人员不了解此规则,直接照搬英语的one/other,会导致俄语用户看到2 новых сообщения(语法错误)。
3. 字符串长度的UI容错
西班牙语单词普遍比英语长30%-50%。values-es/strings.xml中:
<string name="menu_delete">Eliminar conversación</string>
<!-- 英文原版是 "Delete conversation",19字符;西班牙语版25字符 -->
这就要求layout/中的TextView必须设置android:maxLines="2"或android:ellipsize="end",否则在窄屏设备上会文字截断。layout-finger/目录的存在,正是为这类长文本提供了更大的安全边距。
3.3 CleanSpec.mk与Android.mk:AOSP构建系统的双引擎
这两个文件是模块能否被AOSP整编成功的命脉,它们的工作方式截然不同:
CleanSpec.mk:构建前的“清道夫”
它定义了make clean-Mms命令要删除的文件路径。典型内容:
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Mms_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/$(TARGET_PRODUCT)/obj/APPS/Mms_intermediates)
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/Mms_intermediates/src/R.stamp)
关键点在于:add-clean-step宏确保清理操作按顺序执行,且$(OUT_DIR)指向AOSP输出目录(如out/)。如果你修改了res/资源但忘记make clean-Mms,aapt2可能复用旧的R.java缓存,导致新字符串ID未更新,运行时报ResourceNotFoundException。我踩过的坑:一次调试中发现新添加的values-de/strings.xml始终不生效,最终发现是R.stamp文件未被清除,make clean-Mms && mmm packages/apps/Mms才解决问题。
Android.mk:构建时的“总指挥”
这是模块参与AOSP编译的核心配置。精简版如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := Mms
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_STATIC_JAVA_LIBRARIES := \
telephony-common \
ims-common \
android-support-v4
include $(BUILD_PACKAGE)
逐行解读:
- LOCAL_MODULE_TAGS := optional:标记为可选模块,不会强制编译进所有ROM,厂商可按需开关。
- LOCAL_CERTIFICATE := platform:指定使用平台签名证书,确保应用能访问android.permission.READ_SMS等系统级权限。
- LOCAL_PRIVILEGED_MODULE := true:关键!这使Mms获得/system/priv-app/目录权限,可调用@SystemApi注解的隐藏API(如MmsConfig.getAutoPersisting())。
- LOCAL_STATIC_JAVA_LIBRARIES:声明静态依赖库。telephony-common包含SmsMessageBase等核心类,ims-common支持VoLTE短信,android-support-v4提供向后兼容的Fragment支持。
实操心得:
LOCAL_PRIVILEGED_MODULE := true是很多定制ROM失败的根源。若设为false,Mms会被安装到/system/app/,失去调用SmsManager.sendTextMessage()的权限,导致发送功能完全失效。务必确认此行存在且为true。
3.4 proguard.flags:发布混淆的精准刀法
proguard.flags文件虽小,却是保障代码安全与体积控制的关键。其内容并非简单-keep class *,而是精细化的保留策略:
# 保留所有Activity,防止被混淆导致Manifest找不到类
-keep public class * extends android.app.Activity
# 保留所有BroadcastReceiver,确保系统广播能正确分发
-keep public class * extends android.content.BroadcastReceiver
# 保留Mms特定的Parcelable类,避免PDU序列化失败
-keep class com.android.mms.data.* { *; }
-keep class com.android.mms.transaction.* { *; }
# 保留R类,防止资源ID被混淆
-keep class **.R$* {
<fields>;
}
重点在于第三条:-keep class com.android.mms.data.* { *; }。MmsMessage、PduBody等类实现了Parcelable,用于跨进程传递彩信数据。若这些类被混淆,Parcel在反序列化时会因类名不匹配而抛出ClassNotFoundException,导致彩信接收失败。而-keep class **.R$*则确保R.string.menu_forward等资源引用在混淆后仍能正确解析。
4. 完整实操流程:从源码导入到ROM集成
4.1 环境准备:AOSP源码树的最小化搭建
这不是Android Studio项目,你需要完整的AOSP环境。以下步骤基于Ubuntu 22.04,AOSP Branch android-14.0.0_r1(Android 14):
1. 安装依赖与Repo工具
sudo apt update && sudo apt install -y git-core gnupg flex bison build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev \
libxml2-utils xsltproc unzip fontconfig python3 python3-pip
mkdir ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
2. 初始化并同步AOSP源码(最小化)
为节省空间,我们只同步必需模块:
mkdir ~/aosp && cd ~/aosp
repo init -u https://android.googlesource.com/platform/manifest -b android-14.0.0_r1 \
--depth=1 --no-clone-bundle
# 编辑 .repo/manifest.xml,注释掉无关项目,仅保留:
# <project path="build/make" name="platform/build" groups="pdk" />
# <project path="frameworks/base" name="platform/frameworks/base" groups="pdk" />
# <project path="packages/apps/Mms" name="platform/packages/apps/Mms" groups="pdk" />
# <project path="hardware/libhardware" name="platform/hardware/libhardware" groups="pdk" />
repo sync -c -j8 --force-sync
提示:
--depth=1克隆浅层历史,--no-clone-bundle跳过预打包bundle,首次同步约需45GB磁盘空间。若网络不稳定,可在repo sync后加-v参数查看详细进度。
3. 替换Mms模块源码
将你下载的压缩包解压到packages/apps/Mms/,覆盖全部文件:
unzip Mms-source.zip -d /tmp/mms-temp
cp -rf /tmp/mms-temp/* ~/aosp/packages/apps/Mms/
# 特别注意:确保覆盖后,packages/apps/Mms/Android.mk 和 CleanSpec.mk 存在且可读
4.2 构建与验证:三步走通ROM集成
第一步:环境变量与编译配置
cd ~/aosp
source build/envsetup.sh
lunch aosp_arm64-eng # 选择模拟器目标,或 aosp_blueline-userdebug(Pixel 3)
lunch命令会加载build/core/envsetup.mk,设置ANDROID_PRODUCT_OUT等关键变量。aosp_arm64-eng生成的是开发版ROM,包含root权限和调试工具,适合验证。
第二步:模块编译与打包
# 清理旧构建产物(关键!)
m clean-Mms
# 单独编译Mms模块
mmm packages/apps/Mms
# 或整编system.img(耗时约30分钟)
m
mmm命令会执行Android.mk中的include $(BUILD_PACKAGE),调用aapt2编译资源、javac编译Java、dx或d8生成DEX。成功后,Mms.apk位于:
out/target/product/generic_arm64/system/priv-app/Mms/Mms.apk
第三步:烧录与功能验证
# 启动模拟器(若用aosp_arm64-eng)
emulator -avd aosp_arm64 -writable-system
# 或烧录到真机(需解锁Bootloader)
fastboot flash system out/target/product/blueline/system.img
fastboot reboot
验证要点:
- 多语言切换:进入Settings > System > Languages & input > Languages,添加Español (España),返回Mms应用,确认所有菜单、提示均为西班牙语。
- 彩信发送测试:在Mms中新建消息,添加一张图片附件,输入号码发送。抓取logcat:
bash adb logcat | grep -i "mms\|pdu\|transaction"
应看到TransactionService: Starting MMS download for ...日志。
- 安全审计点:检查/data/data/com.android.mms/databases/mmssms.db,确认短信内容是否加密存储(AOSP默认明文,但可通过MmsDatabaseHelper扩展AES加密)。
4.3 多语言扩展实战:为阿拉伯语(ar)添加支持
假设你要为模块新增阿拉伯语支持,这是标准流程:
1. 创建资源目录
mkdir -p packages/apps/Mms/res/values-ar
2. 复制并翻译strings.xml
cp packages/apps/Mms/res/values/strings.xml packages/apps/Mms/res/values-ar/strings.xml
# 使用专业CAT工具(如Poedit)或与母语者协作翻译
# 关键注意:阿拉伯语为RTL(从右向左),需在strings.xml中添加:
# <string name="app_name">الرسائل</string>
# 并在layout中为TextView添加 android:layoutDirection="rtl"
3. 更新AndroidManifest.xml(可选)
若需适配阿拉伯语特殊权限(如READ_CONTACTS在阿拉伯语界面需额外提示),可创建AndroidManifest-ar.xml,但通常无需。
4. 重新编译验证
m clean-Mms && mmm packages/apps/Mms
# 在设备上切换语言为العربية,启动Mms观察效果
实操心得:阿拉伯语翻译后,务必在
layout/中检查所有TextView是否设置了android:textDirection="locale"(API 17+)或android:gravity="right"(旧版),否则文字会从左向右显示,违反阅读习惯。我曾因遗漏此设置,导致沙特客户投诉“界面无法使用”。
5. 常见问题与排查技巧实录
5.1 构建失败高频问题速查表
| 问题现象 | 根本原因 | 排查与解决 |
|---|---|---|
error: package com.android.internal.telephony does not exist | LOCAL_PRIVILEGED_MODULE := true缺失或Android.mk中未声明telephony-common依赖 | 检查packages/apps/Mms/Android.mk,确认LOCAL_PRIVILEGED_MODULE := true和LOCAL_STATIC_JAVA_LIBRARIES := telephony-common两行均存在且未被注释 |
ERROR: Failed to parse XML in ... AndroidManifest.xml: No resource identifier found for attribute 'exported' | AndroidManifest.xml中android:exported属性在低版本API中不存在,但构建系统未启用Manifest分片 | 检查packages/apps/Mms/Android.mk中LOCAL_SDK_VERSION是否设置为21或更高;确认AndroidManifest-api21.xml等分片文件存在且命名正确 |
java.lang.NoClassDefFoundError: com/android/mms/transaction/PduParser | PduParser.class未被打包进Mms.apk,通常是src/路径配置错误 | 检查Android.mk中LOCAL_SRC_FILES := $(call all-java-files-under, src),确认src/目录下com/android/mms/transaction/PduParser.java文件存在且路径正确;运行find packages/apps/Mms/src -name "PduParser.java"验证 |
Resource ID #0x7f0a0001 type #0x12 is not valid | R.java未更新,旧资源ID与新res/目录不匹配 | 执行m clean-Mms彻底清除中间文件,再mmm packages/apps/Mms;若仍失败,手动删除out/target/common/obj/APPS/Mms_intermediates/src/R.java |
5.2 运行时功能异常排查指南
问题:短信发送后无响应,logcat无Mms相关日志
- 排查路径:
1. adb shell dumpsys activity activities \| grep -A 100 "Mms" 查看ComposeMessageActivity是否在栈顶;
2. adb shell pm list packages \| grep mms 确认com.android.mms已安装且未被禁用;
3. adb shell dumpsys package com.android.mms \| grep "enabled" 确认状态为enabled=true;
4. 最关键:adb shell cmd telecom set-sim-subscription --subId 1 --simSlot 0 确保默认短信SIM卡已绑定(多卡设备常见问题)。
问题:彩信附件无法预览,点击后黑屏
- 根源分析:Mms模块依赖MediaProvider服务解析图片,若packages/providers/MediaProvider未正确编译或AndroidManifest.xml中<provider>声明缺失,会导致ContentResolver.openInputStream()返回null。
- 验证命令:
bash adb shell content query --uri content://media/external/images/media/1 # 若返回"Permission Denial",说明MediaProvider未授权给Mms adb shell pm grant com.android.mms android.permission.READ_EXTERNAL_STORAGE
问题:切换语言后,部分字符串仍为英文
- 定位方法:
1. adb shell getprop ro.product.locale 确认系统语言为ar-SA;
2. adb shell ls /system/priv-app/Mms/res/ 查看是否存在values-ar/目录;
3. adb shell cat /system/priv-app/Mms/res/values-ar/strings.xml \| grep "menu_forward" 确认翻译存在;
4. 若存在,执行adb shell am force-stop com.android.mms强制重启应用,排除缓存。
5.3 安全审计关键检查点
作为系统级应用,Mms模块是安全审计的重点目标。以下是必须检查的5个高危点:
1. PDU解析内存安全
PduParser.parse()方法处理网络传入的二进制数据,若未做边界检查,易触发缓冲区溢出。检查点:
- 是否对PduBody的getParts()返回数组长度做校验?
- PduPart.getData()获取附件字节数组前,是否检查getDataLength()是否超限(如>10MB)?
2. 短信数据库SQL注入
MmsDatabaseHelper中所有rawQuery()调用必须使用参数化查询。危险示例:
// ❌ 错误:拼接字符串
db.rawQuery("SELECT * FROM pdu WHERE msg_id = " + msgId, null);
// ✅ 正确:使用?占位符
db.rawQuery("SELECT * FROM pdu WHERE msg_id = ?", new String[]{msgId});
3. 权限过度申请
检查AndroidManifest.xml中<uses-permission>是否最小化:
- READ_CONTACTS仅在“从联系人选择收件人”时需要,应动态申请(API 23+);
- ACCESS_FINE_LOCATION若存在,必须关联到“基于位置的群发”功能,否则属违规。
4. 日志泄露敏感信息
全局搜索Log.d、Log.i,确认无打印sms_body、phone_number、pdu_bytes等原始数据。生产版应禁用DEBUG日志:
if (BuildConfig.DEBUG) {
Log.d(TAG, "SMS body: " + body); // 仅DEBUG版允许
}
5. WebView远程代码执行(RCE)
若Mms中嵌入WebView显示HTML彩信,必须禁用JavaScript:
webView.getSettings().setJavaScriptEnabled(false); // 必须为false
webView.getSettings().setAllowContentAccess(false);
历史上Android 4.3曾曝出WebView.addJavascriptInterface() RCE漏洞,此配置是基本防线。
6. 教学与工程扩展建议
这份源码的价值远不止于“拿来即用”。在我带过的12期移动安全实训中,它是最受学员欢迎的实战靶场。这里分享几个经过验证的扩展方向:
教学演示:可视化短信协议栈
利用PduParser和PduComposer类,编写一个独立Java程序(非Android),读取PCAP文件中的MMS流量,解析出Content-Type、Content-Location、Expiry等PDU头字段,并生成HTML报告。这能让学生直观理解:一条彩信在网络中如何被封装为HTTP POST请求,其Content-Type: application/vnd.wap.mms-message的含义是什么。
工程定制:添加端到端加密(E2EE)
在MmsDatabaseHelper.insertMessage()之前,调用CryptoUtils.encrypt(messageBody, recipientPublicKey)对正文加密;在MessageItem.bind()渲染时,调用CryptoUtils.decrypt(encryptedBody, privateKey)解密。关键挑战在于密钥管理——可集成Android Keystore,将用户私钥绑定到生物识别,确保即使ROOT也无法导出。
逆向研究:对比AOSP与厂商定制差异
下载小米MIUI、华为EMUI的Mms APK,用jadx-gui反编译,与AOSP源码逐行对比。你会发现:
- MIUI在ComposeMessageActivity中增加了MiuiSmsHelper类,用于拦截营销短信;
- EMUI重写了MmsDatabaseHelper的query()方法,加入WHERE thread_id IN (SELECT _id FROM threads WHERE is_archived = 0)过滤归档会话。
这种对比,是理解厂商如何在AOSP基础上构建差异化能力的最佳途径。
最后再分享一个小技巧:当你需要快速定位某个功能的代码位置时,不要盲目grep。先看AndroidManifest.xml中<activity>的android:name,再根据类名去src/中找对应Java文件;对于资源相关的Bug(如按钮文字错位),直接打开res/layout/中对应XML,用Ctrl+F搜索android:text="@string/xxx",然后去values/strings.xml中找源头。这套组合拳,能帮你把5小时的排查压缩到20分钟。毕竟,读懂源码的终极目的,不是记住每一行,而是建立一种肌肉记忆:看到现象,立刻知道该去哪个文件、哪一行、哪个函数里找答案。
简介:提供Android系统级短信应用(Mms)的完整源代码,覆盖Java逻辑层、XML布局、多语言资源及编译脚本。包含适配法语、西班牙语、俄语等20余种语言的values-fr、values-es、values-ru等资源目录;支持触控优化的layout-finger布局子目录;多个AndroidManifest.xml文件满足不同API级别或定制化集成需求;CleanSpec.mk和Android.mk实现模块化清理与编译;proguard.flags支持发布混淆;MODULE_LICENSE_APACHE2和NOTICE文件确保合规开源;.gitignore和PROJECT_ANALYSIS.md辅助开发管理;整体结构严格遵循AOSP源码规范,可直接导入Android源码树参与整编,适用于系统ROM定制、短信功能安全分析、本地化扩展开发、教学演示及逆向研究等实际工程场景。
1220



被折叠的 条评论
为什么被折叠?



