ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

第 51 章:AI、AppFunctions 与计算机控制

第 51 章:AI、AppFunctions 与计算机控制 Android 已经从一个仅能运行应用的平台,演进为能够理解应用行为的平台。一系列端侧智能服务将用户意图与应用行为关联起来:AppFunctions 框架允许助手通过强类型 RPC 契约调用应用的任意功能;计算机控制(Computer Control)为 AI 代理提供虚拟显示器,可在其上完成点击、滑动、截图操作;OnDeviceIntelligence 在隔离沙箱中运行大机器学习模型 —— 大语言模型以及其他生成式或大规模推理负载;NNAPI 向所有原生工作负载暴露硬件加速器。结合 AppSearch、内容捕获(Content Capture)、AdServices 以及联邦学习,这些子系统共同构成了 Android 的 AI 神经体系。本章逐层梳理完整调用链路:从公开 SDK 类,经由 AIDL 接口、system_server 服务实现,一直到另一端沙箱进程或 HAL 进程。每一条代码路径均对应当前 AOSP 源码树中的真实源文件。51.1 AOSP AI 全景概览在深入任一框架细节之前,先整体浏览 AOSP 全部 AI/ML 相关组件。下图列出主要子系统、跨进程边界以及组件之间的数据流。Mainline 模块 HAL / 驱动进程 隔离 / 沙箱进程 目标应用进程 system_server 应用进程 Binder IPC bindService Binder IPC 隔离 bind 调用 Binder IPC Binder IPC Binder IPC Binder IPC Binder IPC第三方 / 系统应用 AppFunctionManager OnDeviceIntelligenceManager NNAPI C API ComputerControlExtensions AppSearchManager TextClassifierManager ContentCaptureManager AppPredictionManager TopicsManagerAppFunctionManagerServiceImpl OnDeviceIntelligenceManagerService VirtualDeviceManager ComputerControlSession Service ContentCaptureManagerService TextClassificationManagerService AppPredictionManagerServiceAppFunctionService OnDeviceSandboxedInferenceService IsolatedTrainingService NNAPI HAL (IDevice) GPU / DSP / NPUAppSearch 模块 NeuralNetworks 模块 OnDevicePersonalization 模块 AdServices 模块51.1.1 AOSP 智能子系统分类表子系统API 等级是否 Mainline 模块用途AppFunctions16(引入),Android 17 趋于成熟否(框架内置)强类型跨应用函数调用,支持运行时注册与状态观测Computer Control16(Android 16)否(框架 + 扩展库)基于虚拟显示器实现 AI 驱动的 UI 自动化OnDeviceIntelligence15 及以上NeuralNetworks 模块沙箱化的大语言模型 / 机器学习推理NNAPI8.1 及以上NeuralNetworks 模块神经网络推理硬件加速AppSearch12 及以上AppSearch 模块端侧全文检索与索引Content Capture10 及以上否(框架内置)为智能服务实时捕获 UI 结构TextClassifier8.0 及以上否(框架内置)实体识别、语言检测AppPrediction10 及以上否(框架内置)基于使用行为的应用排序OnDevicePersonalization14 及以上ODP 模块联邦计算、隔离训练AdServices13 及以上AdServices 模块隐私保护广告定向(Topics、FLEDGE)51.1.2 跨子系统通用设计思路所有 AI 子系统都复用若干架构设计范式:进程隔离智能服务运行在隔离或沙箱进程。OnDeviceSandboxedInferenceService设置android:isolatedProcess="true"。IsolatedTrainingService在独立进程加载 TFLite。即使 ComputerControlSession 也基于与主显示器隔离的虚拟显示器工作。优先使用强类型契约,而非无约束 BundleAppFunctions 使用 AppSearch 提供的GenericDocument作为参数序列化格式。ODI 使用PersistableBundle承载特性与请求元数据。二者均鼓励 SDK 层封装强类型包装类。AppSearch 作为通用元数据存储AppFunction 元数据、应用预测数据、内容捕获智能数据,全部汇聚到 AppSearch 完成索引与检索。权限管控 + 白名单机制AppFunctions 执行受EXECUTE_APP_FUNCTIONS(或EXECUTE_APP_FUNCTIONS_SYSTEM)权限约束,同时配合平台AllowlistManager维护签名代理白名单。Computer Control 需要ACCESS_COMPUTER_CONTROL权限。ODI 需要USE_ON_DEVICE_INTELLIGENCE。AdServices 需要ACCESS_ADSERVICES_TOPICS。支持取消信号传递几乎全部异步 API 都会跨 Binder 传递ICancellationSignal,调用方可终止长时间推理或函数执行。51.2 AppFunctions 框架AppFunctions 框架在 Android 16 以 Beta 特性面世,Android 17 正式广泛可用。它提供一套标准化机制,让 AI 助手(代理)可以发现并调用任意目标应用暴露的功能。例如助手收到指令 “把 XYZ 保存到我的笔记”,框架会将请求路由至对应的AppFunctionService实现,助手无需在编译期依赖笔记应用。Android 17 对该框架做了大幅增强,不再局限于最初仅通过 Manifest 静态声明的模式。本章后续会详细介绍以下核心新增能力:运行时(动态)函数注册:应用可在 Activity 或 Service 中运行时注册 AppFunction 回调,不再必须声明独立AppFunctionService组件(registerAppFunction,受FLAG_ENABLE_DYNAMIC_APP_FUNCTIONS标记控制)。完备的发现、状态与观测 API,新增至AppFunctionManager:searchAppFunctions、getAppFunctionStates、getAppFunctionActivityStates、observeAppFunctions。访问管理框架:维护(代理,目标应用)二元组访问状态与标志位;提供面向用户的管理 UI;代理白名单交由平台AllowlistManager维护,不再使用 DeviceConfig 字符串。新增权限:DISCOVER_APP_FUNCTIONS(仅发现,不可执行)、EXECUTE_APP_FUNCTIONS_SYSTEM(特权系统代理,绕过白名单校验),保留原有EXECUTE_APP_FUNCTIONS。Android 17 源码目录概览:frameworks/base/core/java/android/app/appfunctions/ AppFunctionManager.java -- 客户端系统服务入口 AppFunctionService.java -- 静态目标应用抽象基类 AppFunction.java -- 运行时函数回调接口 RegisterAppFunctionRequest.java -- 运行时注册请求Parcelable ExecuteAppFunctionRequest.java -- 执行请求Parcelable ExecuteAppFunctionResponse.java -- 执行响应Parcelable AppFunctionException.java -- 分层异常错误体系 AppFunctionMetadata.java -- 静态+运行时函数元数据 AppFunctionName.java -- (包名,标识符)函数唯一标识 AppFunctionState.java -- 运行时启用/可见状态 AppFunctionActivityId.java -- Activity作用域函数键值 AppFunctionSearchSpec.java -- 检索查询条件 AppFunctionObserver.java -- 变更观测回调 AppFunctionAccessServiceInterface.java -- 访问校验本地服务 IAppFunctionManager.aidl -- system_server AIDL接口 IAppFunctionService.aidl -- 静态目标应用AIDL(oneway) IAppFunctionExecutor.aidl -- 动态注册执行器AIDL IExecuteAppFunctionCallback.aidl -- 异步结果回调AIDL ICancellationCallback.aidl -- 取消信号传输AIDL ... frameworks/base/services/appfunctions/ java/com/android/server/appfunctions/ AppFunctionManagerService.java -- SystemService封装 AppFunctionManagerServiceImpl.java -- IAppFunctionManager.Stub实现 RemoteServiceCallerImpl.java -- Service绑定逻辑 CallerValidatorImpl.java -- 权限+白名单校验 MetadataSyncAdapter.java -- AppSearch元数据同步 AppFunctionsLoggerWrapper.java -- statsd埋点日志 allowlist/SystemAppFunctionAllowlistReader.java -- AllowlistManager白名单读取 dynamic/MultiUserDynamicAppFunctionRegistry.java -- 运行时注册管理 reader/AppFunctionMetadataReader.java -- 静态/动态元数据读取 observer/AppFunctionMetadataObserver.java -- AppSearch变更观测器 ... frameworks/base/services/permission/java/com/android/server/permission/access/appfunction/ AppFunctionAccessService.kt -- 持久化(代理,目标)访问状态51.2.1 架构概览51.2.2 客户端:AppFunctionManagerAppFunctionManager以系统服务注册,服务名称Context.APP_FUNCTION_SERVICE。@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) @SystemService(Context.APP_FUNCTION_SERVICE) public final class AppFunctionManager {核心 API 为executeAppFunction(),接收四个入参。Android17 要求调用方具备两项执行权限之一;应用调用自身暴露的函数无需权限。@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_PERMISSION_V2) @RequiresPermission( anyOf = { Manifest.permission.EXECUTE_APP_FUNCTIONS, Manifest.permission.EXECUTE_APP_FUNCTIONS_SYSTEM }, conditional = true) @UserHandleAware public void executeAppFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull CancellationSignal cancellationSignal, @NonNull OutcomeReceiverExecuteAppFunctionResponse, AppFunctionException callback) {内部实现会将上层请求封装为ExecuteAppFunctionAidlRequest,补充调用者身份、时间戳信息。ExecuteAppFunctionAidlRequest aidlRequest = new ExecuteAppFunctionAidlRequest( request, mContext.getUser(), mContext.getPackageName(), /* requestTime= */ SystemClock.elapsedRealtime(), /* requestWallTime= */ System.currentTimeMillis());Binder 调用返回ICancellationSignal传输对象,绑定至客户端CancellationSignal,实现跨进程取消。ICancellationSignal cancellationTransport = mService.executeAppFunction( aidlRequest, new IExecuteAppFunctionCallback.Stub() { @Override public void onSuccess(ExecuteAppFunctionResponse result) { executor.execute(() - callback.onResult(result)); } @Override public void onError(AppFunctionException exception) { executor.execute(() - callback.onError(exception)); } }); if (cancellationTransport != null) { cancellationSignal.setRemote(cancellationTransport); }51.2.3 启用状态管理每个 AppFunction 具备三态生命周期:常量数值含义APP_FUNCTION_STATE_DEFAULT0恢复默认状态(通常为启用)APP_FUNCTION_STATE_ENABLED1显式启用APP_FUNCTION_STATE_DISABLED2显式禁用应用通过setAppFunctionEnabled()控制自身函数状态。@UserHandleAware public void setAppFunctionEnabled( @NonNull String functionIdentifier, @EnabledState int newEnabledState, @NonNull Executor executor, @NonNull OutcomeReceiverVoid, Exception callback) {启用状态以AppFunctionRuntimeMetadata文档持久化在 AppSearch,与描述函数 Schema 的AppFunctionStaticMetadata相互独立。setAppFunctionEnabled()仅对静态AppFunctionService对应的函数生效。通过registerAppFunction注册的运行时函数,生命周期与注册会话绑定,启用状态由registerAppFunction/AppFunctionRegistration.unregister控制;对动态函数调用本方法会抛出IllegalArgumentException。Android17 完整对外暴露运行时状态,不仅仅是启用位。AppFunctionStateParcelable 包含AppFunctionName、启用标记、可见性;可通过AppFunctionManager.getAppFunctionStates(...)批量读取。51.2.4 访问控制模型AppFunctions 访问模型分为三层校验:访问标志位是以(代理,目标应用)为单位存储的位掩码,常量定义在AppFunctionManager。标志位数值含义ACCESS_FLAG_PREGRANTED1系统预授权访问ACCESS_FLAG_UPGRADE_GRANTED1 1系统版本升级时授予ACCESS_FLAG_USER_GRANTED1 2用户通过 UI 显式授权ACCESS_FLAG_USER_DENIED1 3用户通过 UI 显式拒绝(优先级高于 PREGRANTED)ACCESS_FLAG_OTHER_GRANTED1 4ADB 或其他方式授权ACCESS_FLAG_OTHER_DENIED1 5ADB 或主动撤销拒绝Android17 代理白名单不再使用 DeviceConfig 字符串,改为平台AllowlistManager。它以SignedPackage(包名 + 证书摘要)为 Key,记录该代理允许访问的目标包集合,支持通配符代表全部目标包。AppFunctions 服务通过SystemAppFunctionAllowlistReader读取,内部使用 LruCache 按代理缓存结果。public class SystemAppFunctionAllowlistReader implements AppFunctionAllowlistReader { private final LruCacheSignedPackage, ArraySetString mCache; private final AllowlistManager mAllowlistManager; @Override public CompletableFutureBoolean isAllowlisted( String agentPackage, String targetPackageName, int userId) { ... } }CallerValidatorImpl执行前同时校验运行时权限与白名单。持有EXECUTE_APP_FUNCTIONS_SYSTEM的特权系统代理会跳过白名单;仅持有EXECUTE_APP_FUNCTIONS的代理必须出现在目标应用对应的白名单内。51.2.5 AIDL 接口定义框架定义两组 AIDL 接口:一组面向客户端,一组面向目标应用。IAppFunctionManager(客户端 → system_server)Android17 接口大幅扩充,增加发现、观测、运行时注册、访问管理相关接口。interface IAppFunctionManager { ICancellationSignal executeAppFunction( in ExecuteAppFunctionAidlRequest request, in IExecuteAppFunctionCallback callback); // 发现与观测 void observeAppFunctions( in AppFunctionAidlSearchSpec aidlSearchSpec, in IObserveAppFunctionChangesCallback callback); void unregisterAppFunctionObserver( in String callingPackage, in UserHandle userHandle, in IObserveAppFunctionChangesCallback callback); void getAppFunctionStates( in ListAppFunctionName appFunctionNames, in String callingPackageName, int targetUserId, in IGetAppFunctionStatesCallback callback); void getAppFunctionActivityStates( in ListAppFunctionActivityId activityIds, in String callingPackageName, int targetUserId, in IGetAppFunctionActivityStatesCallback callback); // 启用状态生命周期 void isAppFunctionEnabled( in String callingPackage, in String targetPackage, in String functionIdentifier, in UserHandle userHandle, in IIsAppFunctionEnabledCallback callback); void setAppFunctionEnabled( in String callingPackage, in String functionIdentifier, in UserHandle userHandle, int enabledState, in ISetAppFunctionEnabledCallback callback); // 运行时动态注册 void registerAppFunctions(in String packageName, in ListString functionIds, in IAppFunctionExecutor executor, in IBinder activityToken); void unregisterAppFunctions(in String packageName, in ListString functionIds, in IAppFunctionExecutor executor); // 访问管理 int getAccessRequestState(in String agentPackageName, int agentUserId, in String targetPackageName, int targetUserId); int getAccessFlags(in String agentPackageName, int agentUserId, in String targetPackageName, int targetUserId); boolean updateAccessFlags(in String agentPackageName, int agentUserId, in String targetPackageName, int targetUserId, int flagMask, int flags); void revokeSelfAccess(in String targetPackageName); ListString getValidAgents(int userId); ListString getValidTargets(int targetUserId); Intent createRequestAccessIntent(in String targetPackageName); void addOnAccessChangedListener(IOnAppFunctionAccessChangeListener listener, int userId); void removeOnAccessChangedListener(IOnAppFunctionAccessChangeListener listener, int userId); }注意区分查询回调IIsAppFunctionEnabledCallback和修改回调ISetAppFunctionEnabledCallback。运行时注册传递IAppFunctionExecutor,由系统直接调用,不再绑定独立组件。IAppFunctionService(system_server → 目标应用,oneway)oneway interface IAppFunctionService { void executeAppFunction( in ExecuteAppFunctionRequest request, in String callingPackage, in android.content.pm.SigningInfo callingPackageSigningInfo, in ICancellationCallback cancellationCallback, in IExecuteAppFunctionCallback callback); }oneway修饰至关重要:system_server 不会阻塞等待目标应用执行完成,结果全部经由IExecuteAppFunctionCallback回调返回。51.2.6 目标端:AppFunctionService目标应用继承AppFunctionService,实现唯一抽象方法:@MainThread public abstract void onExecuteFunction( @NonNull ExecuteAppFunctionRequest request, @NonNull String callingPackage, @NonNull SigningInfo callingPackageSigningInfo, @NonNull CancellationSignal cancellationSignal, @NonNull OutcomeReceiverExecuteAppFunctionResponse, AppFunctionException callback);服务内部做调用者校验:仅拥有BIND_APP_FUNCTION_SERVICE权限的 system_server 可以调用。if (context.checkCallingPermission(BIND_APP_FUNCTION_SERVICE) == PERMISSION_DENIED) { throw new SecurityException("Can only be called by the system server."); }Manifest 声明示例,必须指定绑定权限:service android:name=".YourService" android:permission="android.permission.BIND_APP_FUNCTION_SERVICE" intent-filter action android:name="android.app.appfunctions.AppFunctionService" / /intent-filter /service51.2.7 请求与响应序列化格式ExecuteAppFunctionRequest与ExecuteAppFunctionResponse均使用 AppSearch 的GenericDocument作为参数载体。该设计使函数参数可以用 Schema 描述,而 AppSearch 原生支持索引与查询该 Schema。请求结构体:public final class ExecuteAppFunctionRequest implements Parcelable { @NonNull private final String mTargetPackageName; @NonNull private final String mFunctionIdentifier; @NonNull private final Bundle mExtras; @NonNull private final GenericDocumentWrapper mParameters; @Nullable private final AppInteractionAttribution mAttribution;响应结构体:public final class ExecuteAppFunctionResponse implements Parcelable { public static final String PROPERTY_RETURN_VALUE = "androidAppfunctionsReturnValue"; @NonNull private final GenericDocumentWrapper mResultDocumentWrapper; @NonNull private final Bundle mExtras; @NonNull private final ListAppFunctionUriGrant mUriGrants;返回值存放在结果GenericDocument的PROPERTY_RETURN_VALUE键。Jetpack AppFunction SDK 提供强类型封装,负责打包、解析该文档。51.2.8 归因与交互日志每一次执行可以携带AppInteractionAttribution,描述触发本次调用的交互来源。Android17 将该类型从 appfunctions 包提升至android.app包,供整个应用交互 API 复用,开关标记为FLAG_ENABLE_APP_INTERACTION_API。public static final int INTERACTION_TYPE_OTHER = 0; // 需要自定义字符串 public static final int INTERACTION_TYPE_USER_QUERY = 1; public static final int INTERACTION_TYPE_USER_SCHEDULED = 2;归因包含交互类型、可选自定义类型字符串(类型为INTERACTION_TYPE_OTHER时使用)、可选交互 Uri,指向原始上下文。隐私 UI 依靠该信息向用户解释函数执行缘由。Android17 不会持久化每次调用的历史数据库,而是把每一次执行写入平台 metrics 流水线 statsd。system_server 中的AppFunctionsLoggerWrapper运行在共享后台执行器,为每一次成功或失败输出结构化事件,归一化处理归因常量并标记函数类型。static final int FUNCTION_TYPE_UNSPECIFIED = 0; static final int FUNCTION_TYPE_STATIC = 1; // AppFunctionService实现 static final int FUNCTION_TYPE_DYNAMIC_GLOBAL = 2; // registerAppFunction(Service/全局) static final int FUNCTION_TYPE_DYNAMIC_ACTIVITY = 3;// registerAppFunction(Activity作用域) void logAppFunctionSuccess( ExecuteAppFunctionAidlRequest request, ExecuteAppFunctionResponse response, int callingUid, long executionStartTimeMillis, @AppFunctionMetadata.AppFunctionType int appFunctionType) { ... }日志事件记录调用 UID、目标包、请求中提取的交互类型、函数类型(静态 / 动态、全局 / Activity 域)、响应码,以及绑定服务完成之后统计的执行耗时。51.2.9 错误处理AppFunctionException定义了分类错误码体系:// 请求类错误 1000‑1999 public static final int ERROR_DENIED = 1000; public static final int ERROR_INVALID_ARGUMENT = 1001; public static final int ERROR_DISABLED = 1002; public static final int ERROR_FUNCTION_NOT_FOUND = 1003; // 系统类错误 2000‑2999 public static final int ERROR_SYSTEM_ERROR = 2000; public static final int ERROR_CANCELLED = 2001; public static final int ERROR_ENTERPRISE_POLICY_DISALLOWED = 2002; // 应用类错误 3000‑3999 public static final int ERROR_APP_UNKNOWN_ERROR = 3000;getErrorCategory()将错误码区间映射为错误分类:public int getErrorCategory() { if (mErrorCode = 1000 mErrorCode 2000) return ERROR_CATEGORY_REQUEST_ERROR; if (mErrorCode = 2000 mErrorCode 3000) return ERROR_CATEGORY_SYSTEM; if (mErrorCode = 3000 mErrorCode 4000) return ERROR_CATEGORY_APP; return ERROR_CATEGORY_UNKNOWN; }51.2.10 System Server 实现薄的SystemService:AppFunctionManagerService.java,负责发布 Binder 服务到Context.APP_FUNCTION_SERVICE,转发用户生命周期。业务逻辑主体在AppFunctionManagerServiceImpl,继承IAppFunctionManager.Stub,协调各个协作类。public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub { private final RemoteServiceCallerIAppFunctionService mRemoteServiceCaller; private final CallerValidator mCallerValidator; private final AppFunctionsLoggerWrapper mLoggerWrapper; private final IUriGrantsManager mUriGrantsManager; private final UriGrantsManagerInternal mUriGrantsManagerInternal; private final MultiUserDynamicAppFunctionRegistry mDynamicAppFunctionRegistry; private final AppFunctionMetadataReader mAppFunctionMetadataReader; private final AppFunctionMetadataObserver mAppFunctionMetadataObserver; private final VisibilityHelper mVisibilityHelper; private final ActivityTaskManagerInternal mActivityTaskManagerInternal; // 访问校验委托给权限子系统 private final AppFunctionAccessServiceInterface mAppFunctionAccessService; ...关键支撑类说明:类名职责RemoteServiceCallerImpl绑定目标AppFunctionService,管理连接生命周期CallerValidatorImpl强制校验EXECUTE_APP_FUNCTIONS/EXECUTE_APP_FUNCTIONS_SYSTEM权限,校验白名单MetadataSyncAdapter应用包变更时,同步静态函数元数据至 AppSearchAppFunctionPackageMonitor监听应用安装 / 更新 / 卸载事件MultiUserDynamicAppFunctionRegistry保存每个用户下registerAppFunction运行时注册项AppFunctionMetadataReader读取静态(AppSearch)与动态元数据,用于发现与状态查询AppFunctionMetadataObserver基于 AppSearch 变更事件驱动observeAppFunctions回调SystemAppFunctionAllowlistReader通过AllowlistManager解析签名代理白名单AppFunctionsLoggerWrapper为每一次执行输出 statsd 埋点事件AppFunctionAccessService(权限子系统)持久化(代理,目标)访问状态与标志位51.2.11 通过 AppSearch 实现函数发现应用安装、更新或设备开机时,MetadataSyncAdapter从目标应用AppFunctionService提取函数元数据,作为AppFunctionStaticMetadata文档索引存入 AppSearch。代理应用通过查询 AppSearch 完成函数发现。51.2.12 SafeOneTimeExecuteAppFunctionCallback关键防御封装,保证回调有且仅有一次被交付。public class SafeOneTimeExecuteAppFunctionCallback { private final AtomicBoolean mOnResultCalled = new AtomicBoolean(false); @NonNull private final IExecuteAppFunctionCallback mCallback; @Nullable private final CompletionCallback mCompletionCallback; @Nullable private final BeforeCompletionCallback mBeforeCompletionCallback; private final AtomicLong mExecutionStartTimeAfterBindMillis = new AtomicLong(); public void onResult(@NonNull ExecuteAppFunctionResponse result) { if (!mOnResultCalled.compareAndSet(false, true)) { Log.w(TAG, "Ignore subsequent calls to onResult/onError()"); return; } try { if (mBeforeCompletionCallback != null) { mBeforeCompletionCallback.beforeOnSuccess(result); } mCallback.onSuccess(result); if (mCompletionCallback != null) { mCompletionCallback.finalizeOnSuccess( result, mExecutionStartTimeAfterBindMillis.get()); } } catch (RemoteException ex) { Log.w(TAG, "Failed to invoke the callback", ex); } } public void onError(@NonNull AppFunctionException error) { if (!mOnResultCalled.compareAndSet(false, true)) { Log.w(TAG, "Ignore subsequent calls to onResult/onError()"); return; } try { mCallback.onError(error); if (mCompletionCallback != null) { mCompletionCallback.finalizeOnError( error, mExecutionStartTimeAfterBindMillis.get()); } } catch (RemoteException ex) { Log.w(TAG, "Failed to invoke the callback", ex); } }该设计模式必要性:目标应用属于第三方代码,可能错误多次调用回调。AtomicBoolean.compareAndSet()保证仅第一次调用生效。捕获RemoteException:如果回调进程在结果返回前已死亡,异常仅打日志,不会崩溃 system_server。完成钩子:BeforeCompletionCallback与CompletionCallback允许 system_server 在回调交付前后执行附加逻辑(埋点日志、URI 授权、访问历史记录)。public interface CompletionCallback { void finalizeOnSuccess( ExecuteAppFunctionResponse result, long executionStartTimeMillis); void finalizeOnError( AppFunctionException error, long executionStartTimeMillis); } public interface BeforeCompletionCallback { void beforeOnSuccess(ExecuteAppFunctionResponse result); }耗时统计:mExecutionStartTimeAfterBindMillis记录服务绑定完成之后的执行开始时刻,区分绑定开销与真正业务执行耗时。禁用机制:提供disable(),请求被取消或超时时阻止后续回调交付。51.2.13 executeAppFunction 实现深度解析system_server 的executeAppFunction是整个框架最核心路径,逐行解析从 AIDL 入口到绑定目标服务的完整链路。步骤 1:入口与初始校验@Override public ICancellationSignal executeAppFunction( @NonNull ExecuteAppFunctionAidlRequest requestInternal, @NonNull IExecuteAppFunctionCallback executeAppFunctionCallback) { int callingUid = Binder.getCallingUid(); int callingPid = Binder.getCallingPid(); final SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback = initializeSafeExecuteAppFunctionCallback( requestInternal, executeAppFunctionCallback, callingUid); String validatedCallingPackage; try { validatedCallingPackage = mCallerValidator.validateCallingPackage(requestInternal.getCallingPackage()); mCallerValidator.verifyTargetUserHandle( requestInternal.getUserHandle(), validatedCallingPackage); } catch (SecurityException exception) { safeExecuteAppFunctionCallback.onError( new AppFunctionException( AppFunctionException.ERROR_DENIED, exception.getMessage())); return null; }SafeOneTimeExecuteAppFunctionCallback包装,保证无论目标应用多次应答还是崩溃,只返回一次成功 / 错误。步骤 2:线程池异步执行,不阻塞 Binder 线程ICancellationSignal localCancelTransport = CancellationSignal.createTransport(); THREAD_POOL_EXECUTOR.execute( () - { try { executeAppFunctionInternal( requestInternal, callingUid, callingPid, localCancelTransport, safeExecuteAppFunctionCallback, executeAppFunctionCallback.asBinder()); } catch (Exception e) { safeExecuteAppFunctionCallback.onError( mapExceptionToExecuteAppFunctionResponse(e)); } }); return localCancelTransport; }任务提交至THREAD_POOL_EXECUTOR,避免占用 Binder 线程池。步骤 3:权限与状态基础校验(工作线程)@WorkerThread private void executeAppFunctionInternal(...) { // 企业策略校验 if (!mCallerValidator.verifyEnterprisePolicyIsAllowed(callingUser, targetUser)) { safeExecuteAppFunctionCallback.onError( new AppFunctionException( AppFunctionException.ERROR_ENTERPRISE_POLICY_DISALLOWED, ...)); return; } // 目标包名校验非空 if (TextUtils.isEmpty(targetPackageName)) { safeExecuteAppFunctionCallback.onError( new AppFunctionException( AppFunctionException.ERROR_INVALID_ARGUMENT, ...)); return; }步骤 4:链式 Future 完成权限校验 + AppSearch 读取启用状态实现使用AndroidFuture.thenCompose()做非阻塞权限校验,紧接着查询 AppSearch 获取函数启用状态。mCallerValidator .verifyCallerCanExecuteAppFunction( callingUid, callingPid, targetUser, requestInternal.getCallingPackage(), targetPackageName, requestInternal.getClientRequest().getFunctionIdentifier()) .thenCompose(canExecuteResult - { if (canExecuteResult == CAN_EXECUTE_APP_FUNCTIONS_DENIED) { return AndroidFuture.failedFuture( new SecurityException("Caller does not have permission")); } return isAppFunctionEnabled( functionIdentifier, targetPackageName, getAppSearchManagerAsUser(userHandle), THREAD_POOL_EXECUTOR) .thenApply(isEnabled - { if (!isEnabled) { throw new DisabledAppFunctionException("Disabled"); } return canExecuteResult; }); })步骤 5:服务解析与绑定.thenAccept(canExecuteResult - { int bindFlags = Context.BIND_AUTO_CREATE; if (canExecuteResult == CAN_EXECUTE_APP_FUNCTIONS_ALLOWED_HAS_PERMISSION) { bindFlags |= Context.BIND_FOREGROUND_SERVICE; } Intent serviceIntent = mInternalServiceHelper.resolveAppFunctionService( targetPackageName, targetUser); // 授予隐式可见性,允许目标看到调用方 mPackageManagerInternal.grantImplicitAccess( grantRecipientUserId, serviceIntent, grantRecipientAppId, callingUid, /* direct= */ true); bindAppFunctionServiceUnchecked( requestInternal, serviceIntent, targetUser, localCancelTransport, safeExecuteAppFunctionCallback, bindFlags, callerBinder, callingUid); })关键点:调用方具备EXECUTE_APP_FUNCTIONS权限时,使用BIND_FOREGROUND_SERVICE提升目标服务进程优先级。自调用(同一包名)不会获得该优先级提升。51.2.14 RemoteServiceCaller 模式RemoteServiceCallerImpl实现一次性 Service 绑定模式:public class RemoteServiceCallerImplT implements RemoteServiceCallerT { public boolean runServiceCall( Intent intent, int bindFlags, UserHandle userHandle, long cancellationTimeoutMillis, CancellationSignal cancellationSignal, RunServiceCallCallbackT callback, IBinder callerBinder) { OneOffServiceConnection serviceConnection = new OneOffServiceConnection(intent, bindFlags, userHandle, cancellationTimeoutMillis, cancellationSignal, callback, callerBinder); return serviceConnection.bindAndRun(); }OneOffServiceConnection是自定义ServiceConnection,行为:调用Context.bindServiceAsUser()连接目标服务设置取消监听器,超时后执行 unbind监听调用方 Binder 死亡,调用方进程死亡则自动取消回调完成后自动解绑private class OneOffServiceConnection implements ServiceConnection, ServiceUsageCompleteListener { public boolean bindAndRun() { boolean bindServiceResult = mContext.bindServiceAsUser(mIntent, this, mFlags, mUserHandle); if (bindServiceResult) { mCancellationSignal.setOnCancelListener(() - { mCallback.onCancelled(); mHandler.postDelayed(mCancellationTimeoutRunnable, mCancellationTimeoutMillis); }); mDirectServiceVulture = () - { Slog.w(TAG, "Caller process onDeath signal received"); mCancellationSignal.cancel(); }; mCallerBinder.linkToDeath(mDirectServiceVulture, 0); } return bindServiceResult; }该模式保证资源一定被清理,无论调用方崩溃、目标应用崩溃或者用户主动取消。51.2.15 多用户支持实现完整支持多用户。每个用户拥有:独立 AppSearch 数据库,保存静态函数元数据独立PackageMonitor监听包变更MultiUserDynamicAppFunctionRegistry中独立分片保存运行时注册项权限子系统持久化独立的(代理,目标)访问状态与标志位public void onUserUnlocked(TargetUser user) { if (enableDynamicAppFunctions()) { mAppFunctionMetadataObserver.registerAppSearchObserverForUser(user); } else { registerAppSearchObserver(user); } trySyncRuntimeMetadata(user.getUserHandle(), ...); PackageMonitor pkgMonitorForUser = AppFunctionPackageMonitor.registerPackageMonitorForUser( mContext, user, mAppFunctionMetadataObserver); mPackageMonitors.append(user.getUserIdentifier(), pkgMonitorForUser); mDynamicAppFunctionRegistry.onUserUnlocked(user, ...); } public void onUserStopping(@NonNull TargetUser user) { if (enableDynamicAppFunctions()) { mAppFunctionMetadataObserver.unregisterAppSearchObserverForUser(user); } else { MetadataSyncPerUser.removeUserSyncAdapter(user.getUserHandle()); } mPackageMonitors.get(user.getUserIdentifier()).unregister(); mPackageMonitors.delete(user.getUserIdentifier()); } public void onUserStopped(@NonNull TargetUser user) { mDynamicAppFunctionRegistry.onUserStopped(user); }动态函数标记开启时,每个用户的 AppSearch 观察者由AppFunctionMetadataObserver持有,变更事件同时分发给内部元数据缓存以及客户端observeAppFunctions回调。运行时注册表以 userId 为 key;当用户停止,该用户下全部注册项被销毁。51.2.16 代理白名单架构Android17 代理白名单不再是 DeviceConfig 与 Settings.Secure 字符串拼接,改用平台AllowlistManager,白名单 ID 为ALLOWLIST_ID_APP_FUNCTION。输入签名代理包,返回该代理可访问的目标包集合。AppFunctions 服务通过SystemAppFunctionAllowlistReader消费该能力。读取器将代理最新签名证书哈希封装为SignedPackage,向AllowlistManager查询合法目标包;查询结果放入 LruCache 缓存,相同代理重复执行可省去一次 IPC。@Override public CompletableFutureBoolean isAllowlisted( String agentPackageName, String targetPackageName, int userId) { if (agentPackageName.equals(targetPackageName)) { return AndroidFuture.completedFuture(true); // 自身函数永远允许 } SignedPackage agentSignedPackage = new SignedPackage(agentPackageName, /* certificate digest */ ...); maybeStartAllowlistListener(); return getValidTargetPackages(agentSignedPackage) .thenApply(allowlistTargets - allowlistTargets.contains(WILDCARD_PACKAGE_NAME) || allowlistTargets.contains(targetPackageName)); }三条关键行为:自访问隐式放行:代理与目标包相同,应用永远可以调用自身函数。通配符目标:白名单配置通配符包名,代理可访问全部目标。变更监听:首次使用注册OnAllowlistChangedListener;白名单更新时缓存自动失效,不再只在开机阶段读取配置字符串。51.2.17 AppFunction 响应中的 URI 授权当目标应用在响应中返回 content URI,框架可以为调用代理授予临时 URI 权限。private final IUriGrantsManager mUriGrantsManager; private final UriGrantsManagerInternal mUriGrantsManagerInternal; private final IBinder mPermissionOwner; // 构造函数中初始化 mPermissionOwner = mUriGrantsManagerInternal.newUriPermissionOwner("appfunctions");响应中的AppFunctionUriGrant指明需要向代理授予哪些 URI。授权经由mUriGrantsManager.grantUriPermissionFromOwner完成,绑定到 AppFunctions 专属 permission owner。权限有效期直到 owner 释放或者设备重启。51.2.18 Shell 命令支持服务实现onShellCommand(),用于开发者调试。@Override public void onShellCommand( FileDescriptor in, FileDescriptor out, FileDescriptor err, @NonNull String[] args, ShellCallback callback, @NonNull ResultReceiver resultReceiver) { new AppFunctionManagerServiceShellCommand(mContext, this) .exec(this, in, out, err, args, callback, resultReceiver); }adb 命令:adb shell cmd app_function51.2.19 服务启动与生命周期本框架属于SystemService。AppFunctionManagerService.onStart(),当AppFunctionManagerConfiguration.isSupported(context)为 true 时,把 Binder 服务发布到Context.APP_FUNCTION_SERVICE;开启 App Interaction API 标记时,额外发布本地服务AppInteractionService。@Override public void onStart() { if (AppFunctionManagerConfiguration.isSupported(getContext())) { publishBinderService(Context.APP_FUNCTION_SERVICE, mServiceImpl); } if (Flags.enableAppInteractionApi()) { publishLocalService(AppInte
返回列表