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(){mContext=InstrumentationRegistry.getInstrumentation().getTargetContext();mActivityManager=(ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);}/** * 测试getMemoryInfo()稳定性 */@TestpublicvoidtestGetMemoryInfo(){ActivityManager.MemoryInfomemoryInfo=newActivityManager.MemoryInfo();mActivityManager.getMemoryInfo(memoryInfo);// 验证返回值合法性assertTrue("availMem should be positive",memoryInfo.availMem>0);assertTrue("totalMem should be positive",memoryInfo.totalMem>0);assertTrue("availMem should <= totalMem",memoryInfo.availMem<=memoryInfo.totalMem);assertTrue("threshold should be positive",memoryInfo.threshold>0);// 验证行为一致性ActivityManager.MemoryInfomemoryInfo2=newActivityManager.MemoryInfo();mActivityManager.getMemoryInfo(memoryInfo2);// 两次调用结果应该接近(允许小误差)longdelta=Math.abs(memoryInfo.availMem-memoryInfo2.availMem);assertTrue("Memory info should be consistent",delta<100*1024*1024);// 100MB}/** * 测试API可用性 */@TestpublicvoidtestApiAvailability(){// 测试API在声明的minSdkVersion上可用if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){// Android 6.0+: isLowRamDevice应该可用try{booleanisLowRam=mActivityManager.isLowRamDevice();// API调用成功}catch(NoSuchMethodErrore){fail("isLowRamDevice() should be available on API "+Build.VERSION.SDK_INT);}}}/** * 测试废弃API行为 */@Test@SuppressWarnings("deprecation")publicvoidtestDeprecatedApiBehavior(){// 废弃的getRunningTasks()List<ActivityManager.RunningTaskInfo>tasks=mActivityManager.getRunningTasks(10);assertNotNull("getRunningTasks() should not return null",tasks);// targetSdk >= M (23):只返回自己的任务ApplicationInfoappInfo=mContext.getApplicationInfo();if(appInfo.targetSdkVersion>=Build.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.List<android.app.ActivityManager.AppTask>getAppTasks();}// Android 6.0 (API 23) 新增publicclassActivityManager{methodpublicbooleanisLowRamDevice();}// Android 5.0 (API 21) 废弃publicclassActivityManager{method@Deprecatedpublicjava.util.List<android.app.ActivityManager.RunningTaskInfo>getRunningTasks(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 - 对所有应用开放 */publicList<RunningAppProcessInfo>getRunningAppProcesses(){try{returngetService().getRunningAppProcesses();}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * System API - 仅系统应用可用 * @hide */@SystemApi@RequiresPermission(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_FLAG=0x1000;}@TestApi测试API
/** * TestApi标记 */publicclassTestUtils{/** * 仅测试使用的API * @hide */@TestApipublicstaticvoidresetForTesting(){// 重置状态,仅用于测试}}行为稳定性保障
输入验证
/** * 输入验证确保行为稳定 * frameworks/base/core/java/android/app/ActivityManager.java */publicclassActivityManager{/** * 获取运行中的任务 */publicList<RunningTaskInfo>getRunningTasks(intmaxNum){// 参数验证if(maxNum<0){thrownewIllegalArgumentException("maxNum must be non-negative, got: "+maxNum);}// 限制最大值,防止资源耗尽if(maxNum>100){maxNum=100;}try{returngetService().getTasks(maxNum);}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}/** * 设置进程重要性 */publicvoidsetProcessImportant(IBindertoken,intimportance){// 验证token非空if(token==null){thrownewNullPointerException("token cannot be null");}// 验证importance范围if(importance<IMPORTANCE_FOREGROUND||importance>IMPORTANCE_GONE){thrownewIllegalArgumentException("Invalid importance value: "+importance);}try{getService().setProcessImportant(token,importance);}catch(RemoteExceptione){throwe.rethrowFromSystemServer();}}}默认值处理
/** * 默认值确保行为稳定 */publicclassConfiguration{/** * 屏幕方向 */publicintorientation=ORIENTATION_UNDEFINED;/** * 屏幕密度 */publicintdensityDpi=DENSITY_DPI_UNDEFINED;/** * 安全的获取方法,返回默认值 */publicintgetOrientation(){returnorientation!=ORIENTATION_UNDEFINED?orientation:ORIENTATION_PORTRAIT;// 默认竖屏}/** * 安全的设置方法,验证输入 */publicvoidsetOrientation(intorientation){if(orientation!=ORIENTATION_UNDEFINED&&orientation!=ORIENTATION_PORTRAIT&&orientation!=ORIENTATION_LANDSCAPE){thrownewIllegalArgumentException("Invalid orientation: "+orientation);}this.orientation=orientation;}}异常处理一致性
/** * 异常处理一致性 */publicclassPackageManager{/** * 获取应用信息 * @throws NameNotFoundException 如果包不存在 */publicApplicationInfogetApplicationInfo(StringpackageName,intflags)throwsNameNotFoundException{try{ApplicationInfoai=getApplicationInfoAsUser(packageName,flags,getUserId());if(ai==null){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{privatevalusageMap=ConcurrentHashMap<String,AtomicLong>()/** * 记录API调用 */funrecordApiCall(api:String){usageMap.getOrPut(api){AtomicLong(0)}.incrementAndGet()}/** * 获取统计数据 */fungetUsageStats():Map<String,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管理:版本号标识API
- @SystemApi/@hide:隔离内部API
- 输入验证:确保行为一致
- 默认值处理:避免意外行为
- 异常一致性:文档明确异常类型
API演进策略
- 新增方法:提供默认实现
- 方法重载:保留旧签名
- 新增类:不影响旧类
- 废弃标记:@Deprecated + 文档
- 渐进式移除:6-8年时间跨度
稳定性最佳实践
- 完整的CTS测试覆盖
- 严格的API Review流程
- 清晰的JavaDoc文档
- 充分的输入验证
- 一致的异常处理
- API使用监控
Android 16 (API 36) 稳定性保障变化
CTS测试增强
Android 16 CTS 测试新增覆盖: - 前台服务类型验证测试 - 后台Activity启动限制测试 - 隐私API访问审计测试 - 新增 VTS(Vendor Test Suite)对 HAL 接口的稳定性验证接口稳定性监控增强
应用兼容性框架(App Compatibility Framework)
// Android 16:应用兼容性框架进一步扩展// 可以在开发者选项中针对单个应用切换行为// 系统通过 AppCompatChange 控制每个兼容性开关// 开发者可以查询当前启用的兼容性变更valchanges=AppCompatChanges.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生态系统健康发展
