屏幕自动化操作声明协议应用开发接入文档

复制页面

1. 引言与目标

本文档是屏幕自动化操作声明协议(SAEP,Screen Automation Execution Protocol)的官方接入指南,旨在帮助 Android 应用开发者理解并接入屏幕自动化操作声明功能。开发者可通过本指南完成策略声明、能力检测、Agent 信息查询和操作日志审计,在支持自动化协作的同时保护应用数据、业务资源与用户权益。

2. 屏幕自动化操作协议介绍

SAEP 是面向 GUI Agent 操作第三方应用的声明协议。它将应用保护要求转换为机器可解析的策略,由系统在操作前完成 Agent 身份校验和策略决策,在关键能力路径实施约束,并记录可审计的决策与执行结果。

协议解决的问题:

  • 让应用表达可操作边界:三方应用可声明哪些页面和操作允许 Agent 访问,哪些页面或能力需要禁止 GUI Agent 代理操作。
  • 让策略管理统一裁决:策略管理模块综合 Agent 身份、系统安全基线、应用声明策略和用户授权状态,得到本次操作的最终决策。
  • 让约束不可轻易绕过:限制由系统关键能力入口执行,不仅依赖 Agent 自律。
  • 让行为可以追溯:记录谁在什么时间、对哪个应用页面、请求了什么操作、命中了什么策略以及实际结果。

2.1 系统架构

Image

2.2 核心角色与概念

逻辑组件 所属层面 核心职责
Target App(三方应用) 应用生态 声明应用、Activity 和 Intent 级操作边界;查询已注册 Agent 及本应用审计日志。
Agent 策略管理 应用生态 以静态 Manifest 资源或动态更新方式表达限制规则,包含 default_policy 与 scope。
Agent 身份查询 应用生态 对系统侧 Agent 身份信息进行查询和管理。
GUI Agent Agent 生态 完成任务规划、页面理解和意图识别;执行前提交目标、动作和上下文,请求系统决策。
Agent 身份认证 系统控制面 管理 Agent 注册信息,校验包名、签名、UUID、可信等级和设备证明,并向声明应用提供查询。
策略管理模块 系统执行面 将决策落实到屏幕/虚拟显示、无障碍读取、点击、输入和注入等系统控制点。
Agent 动作执行 系统执行面 承载屏幕与虚拟显示、无障碍与页面读取、点击、输入和注入等实际能力;只接受策略管理模块放行后的请求。
TEE 服务 可信基础设施 保护可信身份和证明材料,关联 Agent 应用、实例身份与设备可信状态。
日志管理服务 审计基础设施 汇聚策略决策和 Agent 动作执行结果,补充系统可信字段,并按调用应用实施查询隔离。
安全存储 审计基础设施 保存策略、Agent 注册信息和审计记录,实施访问控制、完整性保护和生命周期管理。

2.3 系统基线

系统基线是 SAEP 的最低边界,由系统统一维护,优先于应用声明和 Agent 自身判断。它用于防止三方应用未声明策略、策略填写错误或 Agent 试图绕过时出现能力意外放开。

  • 身份基线:未注册、签名不匹配、可信证明失败或设备状态不满足要求的 Agent,应被拒绝进入受控执行链路。
  • 能力基线:截图、无障碍访问、点击与输入注入等高权限能力必须经过系统控制点。
  • 行为基线:涉及支付转账、账号认证、内容发布、删除、权限变更等高风险动作,可由系统要求用户二次确认、用户接管或拒绝执行。
  • 不可放宽:应用策略不得把系统基线的 BLOCK 或 CALL_USER 降级为 ALLOW。
  • 可审计:系统基线命中、执行阻断、降级和用户接管均应产生原因码与审计记录。

2.4 Agent 操作策略

Agent 操作策略描述“某个 Agent 在当前上下文中能否对目标应用执行某项 GUI 操作”。最终结果至少由以下四类输入共同决定:

  1. Agent 身份与可信状态:Agent UUID、包名、签名摘要、Agent 类型、可信等级和设备健康证明。
  2. 系统基线:系统对红线行为和高风险能力的统一限制。
  3. 应用声明策略:应用静态或动态提供的 default_policy 与 scope。
  4. 用户授权与任务上下文:用户是否对当前任务和具体高风险步骤作出有效确认。

应用策略可在三个作用域表达:

作用域 匹配对象 示例
App 整个应用 Agent 在本应用可在任意页面执行该操作。
Activity 指定页面 登录页禁止截图和输入,支付确认页完全禁止操作。
Intent 指定业务意图 限制内容修改、最终发布、删除或激励权益领取。

策略合并遵循三个稳定原则:系统基线不可放宽、多个命中结果取更严格值、解析失败回退到可用的默认策略。由于方案材料对 App、Activity、Intent 的简单顺序表述存在差异,开发者不应依赖“后写覆盖前写”;应让敏感页面显式声明限制,并通过目标镜像的验收用例确认最终 Effective Policy。

2.5 决策、强制执行与用户接管

决策 系统行为 应用与 Agent 预期
ALLOW 允许调用对应系统能力,并记录正常执行结果。 仍需继续通过应用业务鉴权;不代表免除用户授权。
BLOCK 在 PEP 阻断操作,返回明确拒绝且不应回退到旁路能力。 停止自动操作,向用户说明限制,不尝试换通道绕过。
CALL_USER 暂停自动化并展示系统级确认或接管界面。 等待用户亲自确认或操作,确认只覆盖所展示的具体步骤。
CLARIFY 当前材料中用于表达澄清或软性约束。 具体语义和是否对外开放必须以目标 SDK/API 包为准。

强制执行应位于系统控制的关键路径。例如:应用级禁用可阻止目标应用进入 Agent 虚拟屏;页面禁止截图可增加安全图层;输入限制可在 InputManager 等路径阻断模拟注入。意图级约束是否已具备完整系统强制能力取决于目标版本,不能仅凭 Agent 返回“已遵守”完成验收。

2.6 审计闭环

策略决策和实际执行必须同时进入审计链路,才能识别“决策允许但执行失败”“决策拒绝但 Agent 尝试绕过”等差异。审计事件至少应关联 Agent 身份、会话与步骤、目标包和 Activity、操作意图、能力类型、策略版本、决策结果、执行结果及原因码。

  • 系统侧记录:由系统服务和关键执行点补充调用方 UID、时间戳、执行结果等可信字段。
  • 最小披露:不记录原始截图、用户输入敏感个人信息或完整控件树等隐私原文。
  • 应用隔离:三方应用只能查询与自身应用相关的日志。
  • 版本边界:日志查询、导出和保留阈值以目标系统版本实际能力为准。

3. 接入准备

3.1 支持系统版本

项目 当前状态
支持系统版本 ObricUI 2.2 版本及以上

3.2 API 总览

三方应用可通过以下系统接口和配置入口接入 SAEP。调用前应先检测协议状态;接口不存在、调用异常或返回不可用时,应按 SAEP 不可用处理,并继续执行应用自身的控制。

所属类 API 签名 API 描述
android.security.obric.robots.RobotsHelperStub public static RobotsHelperStub getInstance() 获取 SAEP 状态查询接口的单例对象。
android.security.obric.robots.RobotsHelperStub public boolean isRobotsEnabled(android.content.Context context) 通过应用 Context 查询 SAEP 是否启用;true 表示启用。
android.security.obric.robots.RobotsHelperStub public boolean isRobotsEnabled() 不传入 Context 查询 SAEP 是否启用;由系统实现侧获取上下文。
android.content.ContentResolver public int update(android.net.Uri uri, android.content.ContentValues values, java.lang.String where, java.lang.String[] selectionArgs) 向 SAEP Policy Provider 提交动态策略;返回成功更新的记录数。
android.security.obric.agentmanager.AgentManagerStub public static AgentManagerStub getInstance() 获取可信 Agent 查询接口的单例对象。
android.security.obric.agentmanager.AgentManagerStub public java.util.List<java.lang.String> listRegisteredAgents() 查询设备中已注册 Agent 的 UUID 列表。
android.security.obric.agentmanager.AgentManagerStub public java.lang.String getAgentInfo(java.lang.String agentUuid) 根据 Agent UUID 查询对应的注册身份信息,结果为 JSON 字符串。
android.security.obric.audit.SecurityAuditManagerStub public static SecurityAuditManagerStub getInstance() 获取安全审计日志查询接口的单例对象。
android.security.obric.audit.SecurityAuditManagerStub public java.util.List<java.lang.String> queryLogs(long startTimeMs, long endTimeMs, java.lang.String targetIntent, java.lang.String targetActivity) 按时间、操作意图和目标 Activity 查询与调用应用自身相关的审计日志。

4. 接入流程

4.1 SAEP 协议的工作逻辑

Image

4.2 第一步:检测 SAEP 是否可用

应用应在进入依赖 SAEP 的功能前查询协议状态。返回 true 表示当前系统侧功能生效;返回 false 表示功能被云端关闭、系统版本不支持或暂不可用。检测失败时按“不支持”处理,并继续依赖应用自身安全控制。

// 判断 SAEP 协议功能当前是否生效(通过 Context 版本)
// 返回 true 表示生效,false 表示已被云端关闭或不可用
public static boolean isRobotsEnabled(Context context)

SAEP 状态查询(当前材料中的反射方式)

try {
    Class<?> clazz =
        Class.forName("android.security.obric.robots.RobotsHelperStub");
    Method getInstance = clazz.getDeclaredMethod("getInstance");
    getInstance.setAccessible(true);
    Object instance = getInstance.invoke(null);

    // 方式一:带 Context 参数版本
    Method methodWithCtx = clazz.getDeclaredMethod("isRobotsEnabled",
        Context.class);
    methodWithCtx.setAccessible(true);
    boolean enabled = (Boolean) methodWithCtx.invoke(instance, context);
    Log.d(TAG, "SAEP protocol enabled: " + enabled);
} catch (Exception e) {
    Log.e(TAG, "isRobotsEnabled failed: " + e.getMessage());
}

4.3 第二步:设定策略

4.3.1 策略结构

字段 类型 必填 说明
schema string 是 固定格式:AGRP-Policy/1.0。Android GUI Robots 协议(AGRP,Android GUI Robots Policy)。
policy_version int 是 策略版本号由应用自增;动态更新不得回滚。
package string 否 设置管控规则的应用包名。
updated_at string 是 Unix 毫秒级时间戳字符串,用于记录 Policy 更新时间。
default_policy object 是 解析失败时的回落策略,必须可用。
scope object 否 应用级、Activity 页面级和 Agent 意图级细化规则。

顶层字段表只声明到 default_policy 和 scope。以下按当前策略示例及现有联调代码补齐 app、activities 两个维度的嵌套字段;未由正式 Schema 定义的必填、缺省与覆盖语义继续标为“未定义”。

app 维度字段

字段路径 类型 说明
default_policy.app object 当前示例中的应用级默认回落策略容器;目前仅确认顶层 default_policy 必填。
default_policy.app.global_disable boolean true 表示禁止全部 Agent 操作。
default_policy.app.screenshot_disable boolean true 表示禁止截图或屏幕帧。
default_policy.app.input_disable boolean true 表示禁止点击、文本输入等模拟输入。
scope.app object 应用级细化策略容器;随非必填的 scope 整体省略。
scope.app.global_disable boolean 当前策略示例已使用;语义同上。
scope.app.screenshot_disable boolean 现有联调代码支持,主策略示例未展示;正式支持范围以 Schema 为准。
scope.app.input_disable boolean 现有联调代码支持,主策略示例未展示;正式支持范围以 Schema 为准。

activities 维度字段

字段路径 类型 说明
scope.activities object / map Activity 页面级规则集合;使用完整 Activity 类名作为动态键,不是数组。
scope.activities.<完整 Activity 类名> object 单个页面的规则条目,例如 com.example.bank.LoginActivity。
scope.activities.<Activity>.name string 面向用户展示的页面中文名称。
scope.activities.<Activity>.page_scope object Activity 页面级限制项容器。
scope.activities.<Activity>.page_scope.global_disable boolean true 表示禁止该页面全部 Agent 操作。
scope.activities.<Activity>.page_scope.screenshot_disable boolean true 表示禁止该页面截图或屏幕帧。
scope.activities.<Activity>.page_scope.input_disable boolean true 表示禁止该页面点击、文本输入等模拟输入。

agent_intents 维度字段

字段路径 类型 说明
scope.agent_intents object Agent 意图级别;针对声明的意图场景,会在整个应用全局生效。

4.3.2 支持的限制项

字段 true 的含义 典型用途
global_disable 禁止全部 Agent 操作 整个应用不允许 GUI Agent 操作。
screenshot_disable 禁止截图/屏幕帧 登录、支付确认、隐私展示等敏感页面。
input_disable 禁止点击、文本输入等模拟输入 密码、验证码、权限变更等页面。
modify_content 限制修改内容或设置 昵称、通讯录、权限、设备与支付开关等。
post_content 限制最终发送/发布 可辅助编辑,但不能代替用户完成最终发布。
delete_content 限制最终删除 可帮助定位或选择对象,但不能执行删除。
account_incentive 限制激励权益操作 签到、抽奖、秒杀、任务、积分或奖励领取。

统一语义:上述字段均以 true 表示“限制/禁止”,以 false 表示“不由该字段限制”,若未设定对应字段时将按照 false 进行处置。false 不代表系统最终一定允许,系统安全基线和其他更严格规则仍可拒绝操作,如支付场景。

4.3.3 优先级与失败回退

  • 系统基线不可放宽:应用策略不能把系统基线的拒绝或用户确认结果降级为允许。
  • 最严格结果生效:多个命中规则冲突时,从严处置。
  • 全局禁用优先:global_disable=true 时,不再依赖截图或输入子项来放开能力。
  • 解析失败安全回退:Schema 不支持、JSON 解析失败或结构异常时,使用 default_policy,并记录回退原因。
  • 版本单调递增:低于当前系统缓存版本的动态策略不得覆盖高版本。

4.3.4 策略示例

文件:res/raw/agent_saep_policy.json

{
  "schema": "AGRP-Policy/1.0",
  "policy_version": 1,
  "package": "com.example.bank",
  "updated_at": "1772191606000",
  "default_policy": {
    "app": {
      "global_disable": true,
      "screenshot_disable": false,
      "input_disable": true
    }
  },
  "scope": {
    "app": {
      "global_disable": false
    },
    "activities": {
      "com.example.bank.LoginActivity": {
        "name": "登录界面",
        "page_scope": {
          "global_disable": true,
          "screenshot_disable": true,
          "input_disable": true
        }
      },
      "com.example.bank.PayConfirmActivity": {
        "name": "支付确认界面",
        "page_scope": {
          "screenshot_disable": true
        }
      }
    },
    "agent_intents": {
      "modify_content": false,
      "delete_content": false,
      "account_incentive": true,
      "post_content": false
    }
  }
}

4.4 第三步:接入静态策略(推荐)

静态声明是当前材料推荐的基础接入方式。系统在应用安装或更新时读取并缓存策略,不依赖应用进程已启动。

文件:AndroidManifest.xml

<application
    ... >

    <meta-data
        android:name="com.obric.agentrobots.POLICY_JSON"
        android:resource="@raw/agent_saep_policy" />

    ...
</application>

本节按当前接口材料使用 @raw/agent_saep_policy.json。开发者可根据自身代码规范对资源名称进行自定义命名。

4.5 第四步:动态更新策略(可选)

当策略需要随用户状态、云控或业务条件变化时,可通过系统 Provider 更新。当前初稿示例 URI 为:

content://com.obric.agentrobots.provider/policy

请求参数:

  • policy:完整策略 JSON 字符串。
  • version:整数版本号,必须高于当前已生效版本。

动态策略更新

private static final Uri POLICY_UPDATE_URI =
    Uri.parse("content://com.obric.agentrobots.provider/policy");

/**
 * 通过 ContentProvider 更新策略
 *
 * @param context 上下文
 * @param policy 策略 JSON 字符串
 * @param version 版本号
 * @return 更新影响的行数,负数表示失败
 */
public static int updatePolicy(Context context, String policy, int version) {
    ContentValues values = new ContentValues();
    values.put("policy", policy);
    values.put("version", version);
    return context.getContentResolver().update(
        POLICY_UPDATE_URI, values, null, null);
}

应用必须在本地完成 JSON Schema 校验后再提交。更新失败时保留上一有效版本,不得先清空旧策略;失败结果要进入应用自身监控。

错误码 处理建议
E_ACCESS_DENIED 检查调用包名、签名和权限。
E_INVALID_ARGUMENT 检查参数、JSON 与版本类型。
E_POLICY_PARSE_ERROR / E_POLICY_VALIDATION 检查字段名、Schema、枚举值和 JSON 合法性;注意原材料中的 POLICTY 拼写可能是实现兼容项。
E_POLICY_VERSION_ROLLBACK 生成更高版本号后重试,禁止复用旧版本。
E_POLICY_NOT_MORE_RESTRICTIVE 策略包含无法收敛的放宽项;保持原策略并按镜像规则调整。
E_SIGNATURE_INVALID 检查包签名与登记信息。
E_RATE_LIMITED 建议合并更新,避免频繁调用。
E_STORAGE_UNAVAILABLE / E_INTERNAL_ERROR 保留上一有效策略,记录告警并稍后重试。

开发者可以根据自身应用工程情况选择静态策略声明或动态更新,两种方案保证至少有一个接入即可。推荐开发者使用静态策略声明进行更新,系统会在应用包安装和更新时自动捕获最新的策略文件。

4.6 第五步:查询可信 Agent

系统提供端侧已注册 Agent 列表和指定 Agent 信息查询。

4.6.1 接口定义

package android.security.obric.agentmanager;

public class RobotsHelperStub {
    /**
     * 获取指定Agent的信息
     *
     * @param agentUuid Agent的 UUID
     * @return Agent信息的 JSON 字符串
     */
    public String getAgentInfo(String agentUuid) {
    }

    /**
     * 获取已注册的Agent列表
     *
     * @return 已注册Agent的 UUID 列表
     */
    public List<String> listRegisteredAgents() {
    }
}

系统提供在端侧已经注册的可信 Agent 进行查询。查询结果可能包含 Agent 名称、UUID、应用包名、签名摘要、Agent 类型、可信等级和版本等信息。应用应将该信息用于展示和审计关联,不应自行把“已注册”推导为对任意业务动作已获授权。

4.6.2 查询流程

Image

4.6.3 调用示例

以下代码保留原文的异常处理和反射调用方式。正式 SDK 可用后应优先改用稳定的编译期接口。

1. 获取已注册的 UUID

try {
    Class<?> stubClazz =
        Class.forName("android.security.obric.agentmanager.AgentManagerStub");
    Method getInstanceMethod = stubClazz.getDeclaredMethod("getInstance");
    getInstanceMethod.setAccessible(true);
    Object stub = getInstanceMethod.invoke(null);

    Method listMethod = stubClazz.getDeclaredMethod("listRegisteredAgents");
    listMethod.setAccessible(true);

    List<String> uuids = (List<String>) listMethod.invoke(stub);
    // uuids 即已注册的AgentUUID 列表
} catch (Exception e) {
    e.printStackTrace();
}

2. 通过 UUID 获取对应 Agent 应用信息

try {
    Class<?> stubClazz =
        Class.forName("android.security.obric.agentmanager.AgentManagerStub");
    Method getInstanceMethod = stubClazz.getDeclaredMethod("getInstance");
    getInstanceMethod.setAccessible(true);
    Object stub = getInstanceMethod.invoke(null);

    Method getInfoMethod = stubClazz.getDeclaredMethod("getAgentInfo",
        String.class);
    getInfoMethod.setAccessible(true);

    String uuid = "<YOUR_AGENT_UUID>";
    String info = (String) getInfoMethod.invoke(stub, uuid);
    // info 即该Agent的详情信息(JSON 字符串)
} catch (Exception e) {
    e.printStackTrace();
}

4.7 第六步:查询本应用审计日志

系统与 Agent 会统一记录所有 Agent 的操作日志。作为被操作方,你的应用也将被赋予查询相关日志的权限。应用只能查询与自身包名相关的记录。建议在后台线程异步查询,按时间窗口分页或分批处理,避免阻塞主线程。

系统将提供一个标准接口,允许你查询与你的应用相关的 Agent 操作记录。支持查询范围如下:

  1. 时间维度
  2. 页面维度
  3. 意图维度

4.7.1 日志查询流程

Image

  • 建议使用后台线程异步查询,避免阻塞应用主进程。
  • 仅允许应用查询自身包名相关日志。
  • 失败返回空列表的语义需与正式 SDK 区分“无数据”和“查询失败”。

4.7.2 接口定义

package android.security.obric.audit;

public class SecurityAuditManagerStub {
    /**
     * 查询调用方自己的审计日志。
     *
     * @param startTimeMs 日志开始时间戳(毫秒);0 表示不限制
     * @param endTimeMs 日志结束时间戳(毫秒);0 表示不限制
     * @param targetIntent 查询意图;为空则不按意图过滤
     * @param targetActivity 查询目标 Activity;为空则不按 Activity 过滤
     * @return 原始 JSON 日志字符串列表;失败返回空列表
     */
    public List<String> queryLogs(long startTimeMs, long endTimeMs,
        String targetIntent, String targetActivity) {
    }
}

4.7.3 日志字段

分类 字段名 类型 是否可空 说明
agent_identify(Agent 身份) agent_name String 否 Agent 名称。
agent_identify(Agent 身份) agent_uuid String 否 Agent 实例的唯一标识,来自其身份声明。
agent_identify(Agent 身份) pkg_sha256 String 否 Agent 应用签名的 SHA256。
agent_identify(Agent 身份) agent_type Enum 否 Agent 类型(如 ASSISTIVE_EXECUTION、AUTONOMOUS)。
agent_identify(Agent 身份) trust_level Enum 否 Agent 的可信等级(如 TRUSTED_TEE、UNTRUSTED),由系统层 TEE 决定并填充。
agent_identify(Agent 身份) package_name String 否 发起调用的进程 UID 及其包名,由系统填充。
agent_identify(Agent 身份) agent_version String 是 Agent app 的版本号。
agent_identify(Agent 身份) agent_md5 String 是 Agent app 的 apk 文件哈希。
agent_identify(Agent 身份) proof_signature String 否 由 TEE 产出,针对 Agent 注册的可信身份证明签名。
agent_decision(操作记录与决策记录) log_source String 否 日志来源:agent:Agent 决策日志;framework:InputManagerService 和 WindowsManager 插桩日志。
agent_decision(操作记录与决策记录) timestamp String 否 日志的时间戳。
agent_decision(操作记录与决策记录) event_id String 否 单次事件的全局唯一标识符。
agent_decision(操作记录与决策记录) session_id String 否 Agent 的会话 ID,用于关联一个任务流程中的所有事件。
agent_decision(操作记录与决策记录) step_id String 否 Agent 操作的步骤 id。
agent_decision(操作记录与决策记录) target_package String 否 操作目标应用的包名。
agent_decision(操作记录与决策记录) target_activity String 是 操作目标应用的 Activity 名称。
agent_decision(操作记录与决策记录) intent_type String 是 Agent 的操作意图分类(如 ACCOUNT_AUTH、ASSET_TRANSACTION)。若未进行意图判断,该字段为空。
agent_decision(操作记录与决策记录) decision_outcome Enum 否 云侧返回决策结果:BLOCK、CALL_USER、CLARIFY、ALLOW。
agent_decision(操作记录与决策记录) user_authorization_type Enum 是 用户授权类型:CALL_USER、EXPLICIT_AGREEMENT、AUTO_EXECUTION。
agent_decision(操作记录与决策记录) action_type String 否 本次操作使用的核心能力(如 SCREENSHOT、CLICK)。
agent_decision(操作记录与决策记录) action_args List 否 本次操作的参数;截图场景传入 activity。
agent_decision(操作记录与决策记录) policy String 是 原始策略管理 json 原文。若目标应用不存在管控策略,此处为空。
agent_decision(操作记录与决策记录) reason_code String 是 Agent 决策原因,如 APP_POLICY_GLOBAL、SYSTEM_BASELINE、APP_POLICY_ACTIVITY、APP_POLICY_INTENT、NULL。策略更新:如 MANIFEST、CONTENT_PROVIDER。
agent_decision(操作记录与决策记录) duration_ms Long 是 操作执行耗时(毫秒)。操作被拒绝/用户接管场景下,默认值为 0。

4.7.4 调用示例

List<String> logs = new ArrayList<>();
try {
    Class<?> clazz =
        Class.forName("android.security.obric.audit.SecurityAuditManagerStub");
    Method method = clazz.getDeclaredMethod("queryLogs",
        long.class, long.class, String.class, String.class);
    method.setAccessible(true);
    Object ret = method.invoke(null, startMs, endMs, intentParam,
        activityParam);
    if (ret instanceof List) {
        logs.addAll((List<String>) ret);
        //TO DO: 实现业务逻辑
    }
} catch (Exception e) {
    Log.e(TAG, "queryLogs error: " + e.getMessage());
}

4.7.5 日志留存

日志存储在端侧安全区域,日志存储规则满足以下任意一个条件将会进行滚动删除。

  • 存储时长:默认 60 天。
  • 存储大小:数据库超过 100 MB。
  • 存储总量:数据总量超过 10 万条。

5. 常见问题

配置策略未生效

  • 确认目标设备确实启用 SAEP,参考 4.1 检测 SAEP 是否可用。
  • 确认 Manifest 中 meta 声明与要求一致,资源已打包进 APK。
  • 检查 JSON 合法性、字段拼写、schema 与 policy_version。

动态策略更新失败

  • 确认 URI、调用权限、包名/签名和策略版本号。
  • 版本号必须单调递增;不要用时间戳截断后充当 int。
  • 对频控错误退避重试;对解析和校验错误不要无条件重试。

Agent 查询或日志查询反射失败

  • 确认当前系统镜像包含对应 Framework API。
  • 对照交付 API 包确认类名、静态/实例方法和参数签名。

声明允许后 Agent 仍被拒绝

应用声明只表达应用侧边界,不能覆盖系统安全基线、Agent 身份校验、用户授权或业务风控。请结合日志中的 decision_outcome 与 reason_code 定位。

6. Demo 示例

为便于开发者理解并验证 SAEP 接入流程,我们提供开源示例工程 SAEP Demo,包含以下功能:

  • 协议状态查询:查询当前设备是否启用 SAEP。
  • 静态策略声明:展示 Manifest 配置方式及随 APK 打包的策略文件。
  • 动态策略更新:构建并提交本应用的策略配置。
  • 可信 Agent 查询:获取已注册的 Agent UUID 列表及对应身份信息。
  • 本地审计日志查询:按时间、Activity 和意图等条件查询与本应用相关的操作记录。

源码地址

平台 仓库地址
GitHub bytedance/SAEP-demo
Gitee ByteDance/SAEP-demo