| 21 | }; |
| 22 | |
| 23 | export class UpdateContext { |
| 24 | private context: common.UIAbilityContext; |
| 25 | private rootDir: string; |
| 26 | private preferences!: preferences.Preferences; |
| 27 | private static DEBUG: boolean = false; |
| 28 | private static isUsingBundleUrl: boolean = false; |
| 29 | private static ignoreRollback: boolean = false; |
| 30 | private static cachedPackageVersion: string = ''; |
| 31 | private static cachedBuildTime: string = ''; |
| 32 | // 单例:确保 bundle provider 与 TurboModule 共用同一份 preferences 内存状态, |
| 33 | // 避免 RNOH RN 实例重建后两处 UpdateContext 各自持有 preferences 缓存导致读写分裂。 |
| 34 | private static instance: UpdateContext | null = null; |
| 35 | private static instanceCounter: number = 0; |
| 36 | private readonly instanceId: string; |
| 37 | |
| 38 | public static getInstance(context: common.UIAbilityContext): UpdateContext { |
| 39 | if (!UpdateContext.instance) { |
| 40 | UpdateContext.instance = new UpdateContext(context); |
| 41 | } |
| 42 | return UpdateContext.instance; |
| 43 | } |
| 44 | |
| 45 | private constructor(context: common.UIAbilityContext) { |
| 46 | this.context = context; |
| 47 | this.rootDir = context.filesDir + '/_update'; |
| 48 | this.instanceId = `uc#${++UpdateContext.instanceCounter}`; |
| 49 | |
| 50 | try { |
| 51 | if (!fileIo.accessSync(this.rootDir)) { |
| 52 | fileIo.mkdirSync(this.rootDir); |
| 53 | } |
| 54 | } catch (e) { |
| 55 | console.error('Failed to create root directory:', e); |
| 56 | } |
| 57 | this.initPreferences(); |
| 58 | this.trace('ctor'); |
| 59 | this.syncStateWithBinaryVersion( |
| 60 | this.getPackageVersion(), |
| 61 | this.getBuildTime(), |
| 62 | ); |
| 63 | } |
| 64 | |
| 65 | /** |
| 66 | * 诊断日志:打印本实例 id 与关键状态,用于定位 preferences 多实例 / 状态分裂问题。 |
| 67 | * 通过 hilog 输出,prefix=pushy,可在 hilog 中按 "UpdateContext" 过滤。 |
| 68 | */ |
| 69 | private trace(point: string): void { |
| 70 | const snap = this.getStateSnapshot(); |
| 71 | logger.info( |
| 72 | 'UpdateContext', |
| 73 | `trace id=${this.instanceId} ${point}` + |
| 74 | ` pkg=${snap.packageVersion} bt=${snap.buildTime}` + |
| 75 | ` cv=${snap.currentVersion} lv=${snap.lastVersion}` + |
| 76 | ` ft=${snap.firstTime} fto=${snap.firstTimeOk}` + |
| 77 | ` rb=${snap.rolledBackVersion}` + |
| 78 | ` flm=${this.readString('firstLoadMarked')}` + |
| 79 | ` uuidSet=${!!this.readString('uuid')}`, |
| 80 | ); |
nothing calls this directly
no outgoing calls
no test coverage detected