01-18-09 接口稳定性保障

张开发
2026/4/15 0:33:13 15 分钟阅读

分享文章

01-18-09 接口稳定性保障
01-18-09 接口稳定性保障接口稳定性概述Android API稳定性是生态系统健康的基石确保数百万应用长期稳定运行。稳定性目标1. 向后兼容 - 旧应用在新系统运行 - Public API不随意修改 2. 行为一致 - 相同输入产生相同输出 - 无意外的行为变更 3. 文档准确 - API行为与文档一致 - 边界条件明确 4. 长期维护 - 废弃有预告 - 渐进式移除CTS兼容性测试CTS测试框架/** * CTS测试用例 * cts/tests/tests/app/src/android/app/cts/ActivityManagerTest.java */RunWith(AndroidJUnit4.class)publicclassActivityManagerTest{privateActivityManagermActivityManager;privateContextmContext;BeforepublicvoidsetUp(){mContextInstrumentationRegistry.getInstrumentation().getTargetContext();mActivityManager(ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);}/** * 测试getMemoryInfo()稳定性 */TestpublicvoidtestGetMemoryInfo(){ActivityManager.MemoryInfomemoryInfonewActivityManager.MemoryInfo();mActivityManager.getMemoryInfo(memoryInfo);// 验证返回值合法性assertTrue(availMem should be positive,memoryInfo.availMem0);assertTrue(totalMem should be positive,memoryInfo.totalMem0);assertTrue(availMem should totalMem,memoryInfo.availMemmemoryInfo.totalMem);assertTrue(threshold should be positive,memoryInfo.threshold0);// 验证行为一致性ActivityManager.MemoryInfomemoryInfo2newActivityManager.MemoryInfo();mActivityManager.getMemoryInfo(memoryInfo2);// 两次调用结果应该接近允许小误差longdeltaMath.abs(memoryInfo.availMem-memoryInfo2.availMem);assertTrue(Memory info should be consistent,delta100*1024*1024);// 100MB}/** * 测试API可用性 */TestpublicvoidtestApiAvailability(){// 测试API在声明的minSdkVersion上可用if(Build.VERSION.SDK_INTBuild.VERSION_CODES.M){// Android 6.0: isLowRamDevice应该可用try{booleanisLowRammActivityManager.isLowRamDevice();// API调用成功}catch(NoSuchMethodErrore){fail(isLowRamDevice() should be available on API Build.VERSION.SDK_INT);}}}/** * 测试废弃API行为 */TestSuppressWarnings(deprecation)publicvoidtestDeprecatedApiBehavior(){// 废弃的getRunningTasks()ListActivityManager.RunningTaskInfotasksmActivityManager.getRunningTasks(10);assertNotNull(getRunningTasks() should not return null,tasks);// targetSdk M (23)只返回自己的任务ApplicationInfoappInfomContext.getApplicationInfo();if(appInfo.targetSdkVersionBuild.VERSION_CODES.M){assertTrue(Should only return own tasks for targetSdk 23,tasks.size()1);if(!tasks.isEmpty()){assertEquals(Should be own package,mContext.getPackageName(),tasks.get(0).baseActivity.getPackageName());}}}/** * 测试异常处理 */TestpublicvoidtestExceptionHandling(){try{// 传入非法参数mActivityManager.getRunningTasks(-1);fail(Should throw IllegalArgumentException for negative maxNum);}catch(IllegalArgumentExceptione){// 预期异常}}/** * 测试权限检查 */TestpublicvoidtestPermissionCheck(){// 没有权限时应抛出SecurityExceptiontry{mActivityManager.forceStopPackage(com.example.other);fail(Should throw SecurityException without permission);}catch(SecurityExceptione){// 预期异常}}}CTS测试覆盖CTS测试范围 1. API功能测试 - 正常输入输出 - 边界条件 - 异常处理 2. 行为一致性测试 - 多次调用结果一致 - 不同设备行为一致 3. 向后兼容性测试 - 旧应用在新系统运行 - targetSdk行为正确 4. 权限测试 - 权限检查正确 - SecurityException正确抛出 5. 性能测试 - API响应时间 - 资源消耗API Review流程API Council审查Android API Review流程 1. 提交API变更 ├─ 代码实现 ├─ JavaDoc文档 ├─ CTS测试用例 └─ API变更说明 2. API Council审查 ├─ 命名规范 ├─ 接口设计 ├─ 向后兼容性 ├─ 文档完整性 └─ 安全性 3. API Review反馈 ├─ Approve: 批准合并 ├─ Request Changes: 需要修改 └─ Reject: 拒绝 4. 合并到主分支 └─ 更新API版本号API设计检查清单API设计检查清单 **正确做法** - 命名规范 - 类名UpperCamelCase - 方法名lowerCamelCase - 常量UPPER_SNAKE_CASE - 包名全小写无下划线 **正确做法** - 接口设计 - 最小化原则只暴露必要的API - 语义化原则命名清晰明确 - 一致性原则与现有API风格一致 **正确做法** - 向后兼容 - 不修改现有Public API签名 - 新增方法提供默认实现 - 废弃API标记Deprecated **正确做法** - 文档 - JavaDoc完整 - 参数说明 - 返回值说明 - 异常说明 - 示例代码 **正确做法** - 安全性 - 权限检查 - 输入验证 - 数据加密 **正确做法** - 性能 - 避免阻塞主线程 - 资源及时释放 - 缓存机制 **正确做法** - 测试 - 单元测试 - CTS测试用例 - 性能测试API版本号管理API Level定义/** * API Level管理 * frameworks/base/api/current.txt */// API Level定义文件示例packageandroid.app{// Android 1.0 (API 1)publicclassActivityextendsandroid.view.ContextThemeWrapper{ctorpublicActivity();methodpublicvoidfinish();methodpublicvoidstartActivity(android.content.Intent);}// Android 5.0 (API 21) 新增publicclassActivityManager{methodpublicjava.util.Listandroid.app.ActivityManager.AppTaskgetAppTasks();}// Android 6.0 (API 23) 新增publicclassActivityManager{methodpublicbooleanisLowRamDevice();}// Android 5.0 (API 21) 废弃publicclassActivityManager{methodDeprecatedpublicjava.util.Listandroid.app.ActivityManager.RunningTaskInfogetRunningTasks(int);}}API变更检测# 检测API变更# build/make/tools/apicheck.sh# 生成当前APImakeupdate-api# 检查API兼容性makecheckapi# 输出示例# ******************************# You have tried to change the API from what has been previously approved.## To make these errors go away, you have two choices:# 1) You can add hide javadoc comments to the methods, etc. listed in the# errors above.## 2) You can update current.txt by executing the following command:# make update-api## ******************************# 比较API差异diffframeworks/base/api/current.txt\out/target/common/obj/PACKAGING/public_api.txt接口稳定性保障机制SystemApi隔离/** * SystemApi隔离 * frameworks/base/core/java/android/app/ActivityManager.java */publicclassActivityManager{/** * Public API - 对所有应用开放 */publicListRunningAppProcessInfogetRunningAppProcesses(){try{returngetService().getRunningAppProcesses();}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * System API - 仅系统应用可用 * hide */SystemApiRequiresPermission(Manifest.permission.FORCE_STOP_PACKAGES)publicvoidforceStopPackage(StringpackageName){try{getService().forceStopPackage(packageName,UserHandle.myUserId());}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * Internal API - 仅Framework内部使用 * hide */publicvoidforceStopPackageAsUser(StringpackageName,intuserId){try{getService().forceStopPackage(packageName,userId);}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}}hide隐藏内部API/** * hide标记 */publicclassInternalUtils{/** * 内部实现方法 - 不对外暴露 * hide */publicstaticvoidinternalMethod(){// 实现细节}/** * 内部使用的常量 * hide */publicstaticfinalintINTERNAL_FLAG0x1000;}TestApi测试API/** * TestApi标记 */publicclassTestUtils{/** * 仅测试使用的API * hide */TestApipublicstaticvoidresetForTesting(){// 重置状态仅用于测试}}行为稳定性保障输入验证/** * 输入验证确保行为稳定 * frameworks/base/core/java/android/app/ActivityManager.java */publicclassActivityManager{/** * 获取运行中的任务 */publicListRunningTaskInfogetRunningTasks(intmaxNum){// 参数验证if(maxNum0){thrownewIllegalArgumentException(maxNum must be non-negative, got: maxNum);}// 限制最大值防止资源耗尽if(maxNum100){maxNum100;}try{returngetService().getTasks(maxNum);}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * 设置进程重要性 */publicvoidsetProcessImportant(IBindertoken,intimportance){// 验证token非空if(tokennull){thrownewNullPointerException(token cannot be null);}// 验证importance范围if(importanceIMPORTANCE_FOREGROUND||importanceIMPORTANCE_GONE){thrownewIllegalArgumentException(Invalid importance value: importance);}try{getService().setProcessImportant(token,importance);}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}}默认值处理/** * 默认值确保行为稳定 */publicclassConfiguration{/** * 屏幕方向 */publicintorientationORIENTATION_UNDEFINED;/** * 屏幕密度 */publicintdensityDpiDENSITY_DPI_UNDEFINED;/** * 安全的获取方法返回默认值 */publicintgetOrientation(){returnorientation!ORIENTATION_UNDEFINED?orientation:ORIENTATION_PORTRAIT;// 默认竖屏}/** * 安全的设置方法验证输入 */publicvoidsetOrientation(intorientation){if(orientation!ORIENTATION_UNDEFINEDorientation!ORIENTATION_PORTRAITorientation!ORIENTATION_LANDSCAPE){thrownewIllegalArgumentException(Invalid orientation: orientation);}this.orientationorientation;}}异常处理一致性/** * 异常处理一致性 */publicclassPackageManager{/** * 获取应用信息 * throws NameNotFoundException 如果包不存在 */publicApplicationInfogetApplicationInfo(StringpackageName,intflags)throwsNameNotFoundException{try{ApplicationInfoaigetApplicationInfoAsUser(packageName,flags,getUserId());if(ainull){thrownewNameNotFoundException(packageName);}returnai;}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * 异常应该 * 1. 文档明确说明 * 2. 类型一致 * 3. 消息清晰 */}接口演进策略新增方法推荐/** * 新增方法保持兼容 */publicinterfaceCallback{// Android 1.0 原始方法voidonSuccess(Stringresult);voidonError(interrorCode);// Android 6.0 新增方法 - 默认实现defaultvoidonProgress(intprogress){// 默认空实现不影响旧代码}// Android 10 新增方法 - 默认实现defaultvoidonCancel(){// 默认空实现}}// 旧代码仍然可用classOldImplementationimplementsCallback{OverridepublicvoidonSuccess(Stringresult){}OverridepublicvoidonError(interrorCode){}// 不需要实现onProgress和onCancel}方法重载/** * 方法重载保持兼容 */publicclassNotificationManager{// Android 4.0 原始方法publicvoidnotify(intid,Notificationnotification){notify(null,id,notification);}// Android 4.1 新增tag参数publicvoidnotify(Stringtag,intid,Notificationnotification){// 实际实现notifyAsUser(tag,id,notification,UserHandle.myUserId());}// 旧代码调用notify(id, notification)仍然有效}新增类/** * 新增类不影响兼容性 */// Android 5.0 之前使用旧类classOldNetworkInfo{booleanisConnected();}// Android 5.0 新增新类classNetworkCapabilities{booleanhasCapability(intcapability);booleanhasTransport(inttransport);}// 两个类共存旧代码继续使用OldNetworkInfo稳定性监控API使用统计/** * API使用统计 */objectApiUsageStats{privatevalusageMapConcurrentHashMapString,AtomicLong()/** * 记录API调用 */funrecordApiCall(api:String){usageMap.getOrPut(api){AtomicLong(0)}.incrementAndGet()}/** * 获取统计数据 */fungetUsageStats():MapString,Long{returnusageMap.mapValues{it.value.get()}}/** * 废弃API使用监控 */funreportDeprecatedApiUsage(api:String,replacement:String){Log.w(DeprecatedApi,API$apiis deprecated, use$replacementinstead)recordApiCall(deprecated:$api)// 上报到监控系统Analytics.logEvent(deprecated_api_usage,Bundle().apply{putString(api,api)putString(replacement,replacement)})}}总结接口稳定性保障机制CTS兼容性测试自动化验证API行为API Review流程人工审查API设计API Level管理版本号标识APISystemApi/hide隔离内部API输入验证确保行为一致默认值处理避免意外行为异常一致性文档明确异常类型API演进策略新增方法提供默认实现方法重载保留旧签名新增类不影响旧类废弃标记Deprecated 文档渐进式移除6-8年时间跨度稳定性最佳实践完整的CTS测试覆盖严格的API Review流程清晰的JavaDoc文档充分的输入验证一致的异常处理API使用监控Android 16 (API 36) 稳定性保障变化CTS测试增强Android 16 CTS 测试新增覆盖 - 前台服务类型验证测试 - 后台Activity启动限制测试 - 隐私API访问审计测试 - 新增 VTSVendor Test Suite对 HAL 接口的稳定性验证接口稳定性监控增强应用兼容性框架App Compatibility Framework// Android 16应用兼容性框架进一步扩展// 可以在开发者选项中针对单个应用切换行为// 系统通过 AppCompatChange 控制每个兼容性开关// 开发者可以查询当前启用的兼容性变更valchangesAppCompatChanges.getEnabledChanges()changes.forEach{change-Log.d(Compat,Change:${change.name}, enabled:${change.isEnabled})}API Review 流程更新Android 16 API Review 新增检查项 - 是否影响应用兼容性框架 - 是否需要在 AppCompat 中提供回退开关 - 对 targetSdk 分层行为的影响评估 - 隐私影响评估Privacy Impact Assessment关键要点接口稳定性通过CTS测试、API Review和严格的演进策略保障确保Android生态系统健康发展

更多文章