模型交付

Android 模型下载跨卷安全落位与改名

最终落位是独立于网络传输的发布阶段;不能假定改名成功、跨卷原子或文件已通过完整性校验。

审核状态: 内容已校验;中文稿供用户审核 · 2026-10-07 · Fact IDs: COVE-DOWNLOAD-01, COVE-MODEL-02

直接回答

模型下载的最终落位是接收字节之后的独立发布阶段。应用必须证明临时文件完整、已配置的完整性检查通过、目标路径所在卷兼容、最终文件操作确实成功,并且后续运行时能打开预期制品。Android 的 File.renameTo 会返回布尔值;API 文档列出同一挂载点等常见失败条件,并要求检查返回值。调用改名函数不代表模型已经出现在目标位置。尤其不能假设内部存储中的临时文件能够原子改名到可移动 SD 卡。选择改名之前应检查源文件和目标目录所在文件系统。如果二者不同,应使用有文档依据的复制与校验流程,确保空间足够容纳两份文件,以唯一候选路径在目标卷写入替换文件,关闭后验证目标字节及任何已配置的可信摘要,再按明确策略提升。候选路径和最终制品路径不得覆盖唯一可用的旧模型;在目标和应用状态提交前,源文件与旧模型保持不变。API 26 及后续版本的 Files.move 搭配 StandardCopyOption.ATOMIC_MOVE 请求文件系统原子移动;不支持时应把异常视为移动失败,而不是隐式复制。API 合约还说明,指定 ATOMIC_MOVE 时其他选项会被忽略;如果目标已存在,究竟替换还是失败由实现决定。不要依赖 REPLACE_EXISTING 来保护旧模型,应使用唯一候选/最终路径,验证后再按明确策略提交。每次运行都记录最终目的地、临时源、操作类型、返回值或异常、源/目标卷、可用空间观测、预期制品身份、实际长度、摘要状态和清理结果。Cove 的 ModelDownloader 会将下载内容写入配置存储目录下的临时制品;如果配置了 SHA-256,则可选地验证摘要,随后调用 renameTo 指向最终目标。当前 Gemma E2B 的摘要值为空,因此不能把这条配置描述成一定会执行摘要校验。当前检查到的源码调用 renameTo 时,没有用它的布尔结果控制完成状态;这是代码观察,不是设备结果,也不是已修复声明。测试时应在传输完成但最终落位之前强制失败,模拟目标卷写满、目标不可写、源目标属于不同卷,以及复制或提升过程中进程中断。确认旧模型仍完整,应用返回可恢复状态,而不是发出 Completed。重启后不能只因曾有临时路径就相信目标制品存在;再次加载前应校验文件身份、长度和已配置摘要。如果移动 API 报告失败,不能因为源文件存在就返回成功。需要复制时,要让源和目标保持为不同文件,待目标验证并提交持久状态后再清理源文件。清理陈旧临时文件时,应按制品身份和维护策略谨慎执行,不要删除仍由其他下载任务持有的文件。界面状态应分开表示字节接收、完整性校验、最终落位与模型可用。下载完成不等于存储提升成功,更不等于运行时加载成功。测试矩阵应包括:摘要已知的测试制品、未配置摘要、错误摘要、短传输、同卷替换、跨卷拒绝或复制、空间不足、每个阶段的进程死亡、目标文件冲突,以及恢复后的第二次加载。报告结论只适用于已测文件系统和 Android 构建。安全流程是固定来源身份;下载到选定卷上的临时路径;复查长度及完整性;创建唯一命名的目标候选;验证操作成功且目标字节一致;用选定运行时打开制品;完成检查后才更新持久状态;并且在替换提交前清理临时数据但保留旧模型。本文讲的是文件落位语义,不认证 Cove 当前实现,也不支持任何全设备兼容声明。

传输已完成,但移动到最终模型路径失败

网络数据流达到预期字节数,但目标路径位于另一个外部卷,且设备空间接近不足。应用仍有一个较旧但可用的模型,不能仅因临时文件存在就报告成功。

决策

把传输完成与存储落位分成两个状态;检查实际移动或复制结果,并在切换模型就绪状态前验证最终路径。

预期结果

移动失败会保留先前可用模型并提示可恢复的存储错误;单纯传输完成不会显示成已安装、已验证和可加载。

需要收集的证据

只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:

  • 临时与最终文件的卷和路径
  • rename/copy 返回值与最终字节
  • 失败恢复及旧模型保留结果

收到完整字节流还不够;最终落盘、完整性、运行时加载和恢复路径也必须验证。

实施流程

  1. 固定来源和目标身份. 记录制品版本、临时路径、目标路径、目标卷、现有文件状态、预期长度、摘要配置及拥有该临时文件的下载任务。
  2. 判断改名及已存在目标的语义. 核对 Android API 合约和源/目标挂载点。File.renameTo 返回布尔值,跨挂载点可能失败。API 26 起的 Files.move 与 ATOMIC_MOVE 请求原子移动;该选项会忽略其他选项,目标已存在时是替换还是失败由实现决定。使用唯一目标候选,不依赖 REPLACE_EXISTING 保护旧模型。
  3. 跨卷复制但不改动源文件. 需要跨卷复制时,在目标卷写入唯一候选文件,关闭后验证目标字节及任何已配置可信摘要。目标制品与应用状态提交前,源文件和旧活动模型都保持不变;若无法原子提升,就明确失败或执行独立测试过的非原子策略。
  4. 检查最终落位结果. 检查所用移动 API 返回的布尔值或异常,验证最终路径和内容;若操作失败或只剩临时源文件,就不能发出模型完成状态。
  5. 验证中断后的恢复. 在每个阶段注入进程死亡、空间不足、权限丢失和目标冲突;重新启动后再次验证候选文件,只清理陈旧且由应用拥有的临时数据。

让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。

验收标准

  • 移动或复制明确成功且最终路径身份与字节已验证后,才发送最终模型状态。
  • 显式测试跨卷行为;原子移动失败不会被描述为原子复制回退,任何复制候选都在目标端验证且提交前保留源文件与旧模型。
  • 空间不足、摘要错误、短传输、中断和目标冲突均保留旧模型与用户数据。
  • 日志分别记录字节接收、摘要验证、最终落位、运行时加载和清理,不声称未验证支持。

决策对照表

维度选择或证据解读方式
调用 rename 后忽略结果乐观落位不安全:API 可能失败,最终只剩临时文件。
检查同挂载点改名结果条件式提升检查布尔结果并验证最终路径;挂载点相同本身不能证明原子性。
API 26+ 使用 ATOMIC_MOVE请求文件系统原子移动文件系统不支持时 API 可以抛错;它不承诺复制回退或可移植的替换行为。
跨卷复制到新候选文件复制、验证后再提升这是独立的非原子流程:保留源和旧模型,验证目标字节,再按明确策略提交。
验证前替换当前模型破坏性更新会在新文件完整可用前移除旧制品。

需要避免的失败模式

  • 忽略 renameTo 的返回值
  • 假定内部存储与 SD 卡之间可原子改名
  • 校验新文件前删除唯一可用旧制品

还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。

最小复现记录

层级记录内容
设备厂商、型号、芯片、内存档位、操作系统版本
软件应用版本和 Git 提交号
模型系列、变体、版本、格式、文件长度、摘要、量化方式
运行时名称、版本、请求后端及实际后端证据
工作负载样例版本、输入摘要、提示词摘要、输出策略
结果完成、失败、取消、回退及保护隐私的诊断信息

发布检查表

  • ☐ 主要搜索问题已回答,且没有未经支持的数字。
  • ☐ 所有模型文件和运行时版本均已固定。
  • ☐ 代表性任务和失败处理策略均有说明。
  • ☐ 生命周期、取消、清理和回退均已测试。
  • ☐ 用户内容与网络边界均有说明。
  • ☐ 结论只适用于被记录的配置。
  • ☐ 新增测试结果时链接到原始方法或证据。

来源与相关证据

中文部署与排错专题见。奇连 AI 端侧专题。

常见问题

File.renameTo 能保证原子移动吗?

不能。Android 文档列出可能失败的情况,包括路径处于不同挂载点,并要求检查布尔返回值。不能假定跨卷改名具有原子语义,也不能因为源文件仍存在就报告成功。

目标文件已存在时 ATOMIC_MOVE 会怎样处理?

API 26 起 Files.move 搭配 StandardCopyOption.ATOMIC_MOVE 请求原子操作;不支持时可能抛出 AtomicMoveNotSupportedException。包括 REPLACE_EXISTING 在内的其他选项会被忽略,目标替换还是操作失败由实现决定。应使用唯一候选/最终制品路径,验证并提交前保留旧模型,否则拒绝更新;原子移动失败不会自动变成原子复制。

下载完成等于模型已安装吗?

不等于。还需通过完整性检查、最终落位成功,并由运行时打开文件,之后才可以报告模型就绪。网络传输结束仅代表字节接收阶段完成。

移动新文件前能否先删除旧模型?

如果旧模型是唯一可用副本,就不能。等替换文件在最终目录验证通过并且应用状态提交后,再考虑清理旧文件,以免失败时用户失去可用版本。

Cove 会对每个 Gemma 下载做 SHA-256 校验吗?

不会。当前 Gemma E2B 的 SHA-256 配置为空。当前源码会调用 renameTo,但不使用其布尔返回值决定完成状态;这是代码观察,不代表设备上的实际结果,也不表示实现已修复。