This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

fix: stub MLKit Clearcut auto-upload path (v4.15.5)

Previous stubs (v4.15.3-4) covered the writeLog path. New crash hits
a different Clearcut subsystem: the periodic auto-uploader that flushes
counters on a timer independent of pose detection, matching the "ran for
a while before crashing" symptom.

Stack:
-[MLKITx_CCTClearcutMetaLogger logCounters:] +56
-[MLKITx_CCTClearcutAutoCounters flushCountersToLoggerInternal] +88
MLKITx__prm_dispatch_sync_named_cstr +56
-[MLKITx_CCTClearcutAutoCounters flushCountersToLogger] +84
-[MLKITx_CCTClearcutMetaLogger flushCountersToLogger] +32
-[MLKITx_CCTClearcutUploader finishUploadAndCallHandlers] +260
-[MLKITx_CCTClearcutUploader flushThenUploadWithCompletionHandler:isOnForeground:] +1324

Stubs added at three levels (each independently installed):

1. -[MLKITx_CCTClearcutUploader startAutoUpload]
No-op. Prevents the timer from starting at all — the cleanest
short-circuit if it runs before the uploader has started.

2. -[MLKITx_CCTClearcutUploader
flushThenUploadWithCompletionHandler:isOnForeground:]
No-op + invoke completion handler with success — handles the
foreground-entry trigger that bypasses the timer.

3. -[MLKITx_CCTClearcutMetaLogger logCounters:]
Deepest fallback right at the crash site — drops counters silently.

All telemetry dropped; pose detection unaffected.

Version 4.15.5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+68 -1
+1 -1
posedetection/build.gradle.kts
··· 4 4 5 5 mavenPublishing { 6 6 publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) 7 - coordinates("com.performancecoachlab.posedetection", "posedetection-compose", "4.15.4") 7 + coordinates("com.performancecoachlab.posedetection", "posedetection-compose", "4.15.5") 8 8 9 9 pom { 10 10 name.set("Pose Detection")
+67
posedetection/src/nativeInterop/mlkitRedirect/MLKitResourceRedirect.m
··· 25 25 static void _pd_mlkit_noop_log(id, SEL, id, id); 26 26 static void _pd_mlkit_noop_writelog(id, SEL, id, id, id, id, id, id, id); 27 27 static id _pd_mlkit_compute_url(Class, SEL, id, id, id); 28 + static void _pd_mlkit_noop_start_auto_upload(id, SEL); 29 + static void _pd_mlkit_noop_flush_upload(id, SEL, id, BOOL); 30 + static void _pd_mlkit_noop_log_counters(id, SEL, id); 28 31 29 32 static BOOL _pd_logger_stubbed = NO; 30 33 static BOOL _pd_writer_stubbed = NO; 31 34 static BOOL _pd_fileutil_stubbed = NO; 35 + static BOOL _pd_uploader_start_stubbed = NO; 36 + static BOOL _pd_uploader_flush_stubbed = NO; 37 + static BOOL _pd_metalogger_stubbed = NO; 32 38 33 39 static void _pd_install_clearcut_stub(void) { 34 40 // 1. -[MLKITx_CCTClearcutLogger log:completion:] (high-level entry) ··· 82 88 } 83 89 } 84 90 } 91 + // 4. Auto-upload path (separate from writeLog — fires on a periodic 92 + // timer, not per pose detection). Stub at three levels so any call 93 + // into the chain gets neutralized before reaching the broken 94 + // logCounters / flushCounters code. 95 + Class uploader = NSClassFromString(@"MLKITx_CCTClearcutUploader"); 96 + if (uploader) { 97 + if (!_pd_uploader_start_stubbed) { 98 + Method m = class_getInstanceMethod(uploader, 99 + @selector(startAutoUpload)); 100 + if (m) { 101 + method_setImplementation(m, (IMP)_pd_mlkit_noop_start_auto_upload); 102 + _pd_uploader_start_stubbed = YES; 103 + } 104 + } 105 + if (!_pd_uploader_flush_stubbed) { 106 + Method m = class_getInstanceMethod(uploader, 107 + @selector(flushThenUploadWithCompletionHandler:isOnForeground:)); 108 + if (m) { 109 + method_setImplementation(m, (IMP)_pd_mlkit_noop_flush_upload); 110 + _pd_uploader_flush_stubbed = YES; 111 + } 112 + } 113 + } 114 + if (!_pd_metalogger_stubbed) { 115 + Class meta = NSClassFromString(@"MLKITx_CCTClearcutMetaLogger"); 116 + if (meta) { 117 + Method m = class_getInstanceMethod(meta, 118 + @selector(logCounters:)); 119 + if (m) { 120 + method_setImplementation(m, (IMP)_pd_mlkit_noop_log_counters); 121 + _pd_metalogger_stubbed = YES; 122 + } 123 + } 124 + } 85 125 } 86 126 87 127 __attribute__((visibility("default"))) ··· 153 193 static id _pd_mlkit_compute_url(Class self, SEL _cmd, 154 194 id logContextDir, id context, id bundleId) { 155 195 return logContextDir; 196 + } 197 + 198 + // MLKit also starts a periodic auto-upload timer that crashes when it 199 + // reaches CCTClearcutMetaLogger logCounters:. Separate code path from 200 + // writeLog. We stub it at multiple levels for belt-and-braces: 201 + // top: -[MLKITx_CCTClearcutUploader startAutoUpload] 202 + // — cleanest, prevents the timer from starting 203 + // middle: -[MLKITx_CCTClearcutUploader 204 + // flushThenUploadWithCompletionHandler:isOnForeground:] 205 + // — invoked directly when foreground-entering; no-op + call 206 + // completion 207 + // bottom: -[MLKITx_CCTClearcutMetaLogger logCounters:] 208 + // — crash site itself; fallback if upper stubs miss it 209 + static void _pd_mlkit_noop_start_auto_upload(id self, SEL _cmd) { 210 + // Do nothing — auto-upload stays off. 211 + } 212 + 213 + static void _pd_mlkit_noop_flush_upload(id self, SEL _cmd, 214 + id completion, BOOL isForeground) { 215 + if (completion) { 216 + void (^block)(BOOL) = completion; 217 + block(YES); 218 + } 219 + } 220 + 221 + static void _pd_mlkit_noop_log_counters(id self, SEL _cmd, id counters) { 222 + // Do nothing — counters are silently dropped. 156 223 } 157 224 158 225 @interface NSBundle (PoseDetectionMLKitRedirect)