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 等条件,避免影响系统组件或白名单应用。
相关推荐
mg6688 分钟前
安卓玩机工具----安卓手机变成桌面电脑!多窗口镜像+音频投射+游戏操控,无需 Root
android·智能手机·电脑
peakmain944 分钟前
异常处理 - Native 层的崩溃捕获机制及实现 (一)
android·性能优化
木头左2 小时前
【Android】听写播放器改版:中英文书写速度拆项与「正在读」高亮
android·room·media3·jetpack compose·听写
好的佩奇3 小时前
Dart 之方法、操作符与可调用对象
android·flutter·dart
恋猫de小郭3 小时前
Flutter Impeller Vulkan 内存持续上涨,问题没想到是文字阴影
android·前端·flutter
张小姐的猫13 小时前
【MySQL】访问 & 数据流动原理
android·数据库·mysql·adb·1024程序员节
其实防守也摸鱼15 小时前
个人学习 Pwn 思路:从基础到漏洞利用的进阶路径
大数据·前端·人工智能·chrome·算法·安全·网络安全
朱涛的自习室16 小时前
212 个需求、22 万行代码:Agent 接管开源项目的 19 天
android·前端·人工智能
AI 编程助手GPT19 小时前
curl 返回成功就能收文件?用本地 HTTP 验证错误页与超时
网络·网络协议·http