Android 12:在 ActivityStarter 层拦截分享、搜索与 HTTP 外链

场景:客户自研 Launcher,需要在系统侧限制第三方应用通过 TextView 链接跳转、文本/图片分享等路径离开业务界面。Android 12 起,与「能否启动 Activity」强相关的逻辑集中在 wm 模块的 ActivityStarter 中,适合在此做统一拦截。

1. 背景与入口位置

  • Android 12 变更 :应用启动相关逻辑中,ActivityStarter 已从传统 am 侧迁移到窗口管理侧,源码路径为:
    frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
  • 拦截思路 :在解析 Intent、得到可启动目标(ResolveInfo 等)之后,根据 action、data 等特征直接放弃解析结果(例如将 rInfo 置空),使后续流程无法找到可启动组件,等价于「禁止启动」。

2. 拦截分享、网页搜索与 http(s) 浏览

在 ActivityStarter 中合适位置(需与你们工程里 err、intent、rInfo 等变量生命周期一致)增加类似逻辑:对 ACTION_SEND / ACTION_SEND_MULTIPLE / ACTION_WEB_SEARCH 一律忽略;对 ACTION_VIEW 且 data scheme 为 http/https 的,除打日志外可在主线程弹出提示,并同样清空解析结果。

frameworks\base\services\core\java\com\android\server\wm\ActivityStarter.java

java 复制代码
// 屏蔽发送、分享及搜索
String action = intent.getAction();
Context context = mService.mUiContext;  // 获取可用于弹 Toast 等的 UI 上下文
if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)
        || Intent.ACTION_WEB_SEARCH.equals(action)) {
    Slog.w(TAG, "ignore an intent: " + intent);
    rInfo = null;
} else if (Intent.ACTION_VIEW.equals(action) && intent.getData() != null) {
    String scheme = intent.getData().getScheme();
    if (scheme != null && scheme.startsWith("http")) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, "该功能暂不可使用", Toast.LENGTH_SHORT).show();
            }
        });
        rInfo = null;
        Slog.w(TAG, "ignore an intent: " + intent);
    }
}

说明要点:

  • ACTION_SEND / ACTION_SEND_MULTIPLE:覆盖系统分享、多选分享等入口。
  • ACTION_WEB_SEARCH:覆盖「网页搜索」类 Intent。
  • ACTION_VIEW + http:覆盖浏览器打开链接;若业务仍允许 tel:、mailto: 等,可在分支中按 scheme 细化。
  • rInfo = null 后需保证与原有错误码、err 赋值逻辑一致,避免出现不一致的启动结果(需结合你们补丁前后完整编译与 CTS/冒烟验证)。

3. mUiContext 从何而来(ActivityTaskManagerService)

截图对应 ActivityTaskManagerService 构造函数片段:系统在创建 ATMS 时会保存当前系统进程的 ActivityThread,并从中取出 系统 UI 上下文 ,供需要与用户界面交互的系统服务使用(例如上述 Toast)。

frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java

java 复制代码
public ActivityTaskManagerService(Context context) {
    mContext = context;
    mFactoryTest = FactoryTest.getMode();
    mSystemThread = ActivityThread.currentActivityThread();
    mUiContext = mSystemThread.getSystemUiContext();
    // ... ClientLifecycleManager、WindowOrganizerController 等初始化
}

因此 ActivityStarter 里通过 mService.mUiContext(具体字段名以你们分支为准)拿到的,本质上是 ActivityThread.currentActivityThread() 关联的 getSystemUiContext(),与「普通应用进程里用 Activity 拿到的 Context」不是同一路径,但足以支撑系统侧轻量 UI 提示(仍须遵守多用户、显示层级等系统限制)。

4. 验证建议

  • 合并冲突 :ActivityStarter 在版本迭代中 diff 较多,建议基于同一 Android 12 基线打补丁并做 rebase 记录。
  • 日志 :保留 Slog.w(TAG, "ignore an intent: " + intent) 便于现场抓取完整 Intent,排查误杀。
  • 范围 :若仅针对「指定包名」拦截,可在上述判断外再增加 callingPackage / userid 等条件,避免影响系统组件或白名单应用。
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
XUEYUAN52123 天前
ASN 自治系统号风控:平台如何通过 IP 所属自治域批量识别代理流量
python·网络协议·http·网络安全·socks5
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas