Health Connect: Floor sync-start at 2015 instead of epoch 0

The start point derived from the oldest activity sample was guarded only by
timestamp > 0. A bogus near-epoch sample timestamp passes that guard and
resolves the start to ~1970, triggering a full historical resync. Floor it at
2015-01-01; Gadgetbridge predates that, so any earlier sample is not real
device data. Reuses the indexed getFirstActivitySample(after) query so the
bogus head rows are skipped at the DB level.
This commit is contained in:
Gideon Zenz
2026-06-02 18:04:41 +02:00
parent b9fb161fad
commit b862b7c9f8
@@ -497,6 +497,11 @@ class HealthConnectUtils {
private const val INITIAL_DELAY_MS = 1000L
private const val HC_SYNC_TAG = "[HC_SYNC]"
// Floor the sync-start at 2015 (Gadgetbridge predates it). A bogus near-epoch sample
// timestamp otherwise resolves the start to ~1970 and triggers a full historical resync.
private const val MIN_VALID_SAMPLE_SECONDS = 1420070400L // 2015-01-01T00:00:00Z
private const val MIN_VALID_SAMPLE_MILLIS = MIN_VALID_SAMPLE_SECONDS * 1000
private fun getSyncTimestampRange(
context: Context,
gbDevice: GBDevice,
@@ -683,10 +688,10 @@ class HealthConnectUtils {
): Instant? {
return when (val provider = getProviderForDataType(deviceCoordinator, device, db, dataType)) {
is TimeSampleProvider<*> -> {
provider.firstSample?.timestamp?.takeIf { it > 0 }?.let { Instant.ofEpochMilli(it) }
provider.firstSample?.timestamp?.takeIf { it > MIN_VALID_SAMPLE_MILLIS }?.let { Instant.ofEpochMilli(it) }
}
is SampleProvider<*> -> { // For ActivitySample based providers
provider.getFirstActivitySample(0)?.timestamp?.takeIf { it > 0 }?.let { Instant.ofEpochSecond(it.toLong()) }
provider.getFirstActivitySample(MIN_VALID_SAMPLE_SECONDS.toInt())?.timestamp?.takeIf { it > MIN_VALID_SAMPLE_SECONDS }?.let { Instant.ofEpochSecond(it.toLong()) }
}
is BaseActivitySummaryDao -> {
val deviceEntity = DBHelper.getDevice(device, db.daoSession) ?: return null