From f713b3b5a8bb6afa5cdfb615853e129aaf5d37cf Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 23 Sep 2026 06:15:30 +0000 Subject: [PATCH 1/5] chore(submodule): bump aw-server-rust to 05c7b38 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Picks up ActivityWatch/aw-server-rust#721: send HTTP headers before serializing large exports, so "Export all buckets as JSON" on ~500k events opens the connection during processing instead of waiting for the full body. Native Android fetch (ActivityWatch/aw-android#304) already streams the body to a cache file; without this bump it still blocks on headers until serialization finishes. Also picks up: - ActivityWatch/aw-server-rust#718 — aw-sync dedupe CLI (JNI path unused) - ActivityWatch/aw-server-rust#719 — aw-sync v2 writer, feature-flagged - ActivityWatch/aw-server-rust#720 — install-ndk.sh macOS readlink - aw-webui bump to #988 (not #993) ActivityWatch/aw-android#228 Git-Session-Id: ba128b8a-fc85-51b5-90c0-4c7a4beaed85 --- aw-server-rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aw-server-rust b/aw-server-rust index 70ba50dd..05c7b384 160000 --- a/aw-server-rust +++ b/aw-server-rust @@ -1 +1 @@ -Subproject commit 70ba50ddc3852acadfb5e90ab20d54e04d8a60b2 +Subproject commit 05c7b384945688192c95b7fb6d512f6c6672edb8 From b908cfdb99c5b48026df5404c6598be16a65740d Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 23 Sep 2026 06:47:59 +0000 Subject: [PATCH 2/5] fix(test): skip sanitized-hostname rewrite in upgrade-with-history The test already set hasMigratedHostname, but startup uses the distinct sanitizedHostnameMigratedTo flag. Without it, Java opens the 17MB seeded sqlite.db while the rust worker switches journal_mode to WAL, hits SQLITE_BUSY, panics, and leaves events/count returning 500. Git-Session-Id: 523c0c0e-38a3-5992-bcb3-bf6bf0d76080 --- .../java/net/activitywatch/android/UpgradeWithHistoryTest.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt b/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt index e499a10a..7e918b0d 100644 --- a/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt +++ b/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt @@ -88,6 +88,11 @@ class UpgradeWithHistoryTest { context.getSharedPreferences(AWPreferences.PREFERENCES_NAME, Context.MODE_PRIVATE).edit() .putBoolean("isFirstTime", false) .putBoolean("hasMigratedHostname", true) + // Distinct from hasMigratedHostname: without this, startup opens sqlite.db + // from Java to rewrite bucket hostnames while the rust worker is switching + // journal_mode to WAL. On this 17MB seed that races SQLITE_BUSY, the worker + // panics, and events/count stays 500 for the rest of the test. + .putString("sanitizedHostnameMigratedTo", hostname) .putBoolean("hasMigratedWatcherAndroidBucketNames", false) .putBoolean("hasRequestedNotificationPermission", true) .commit() From 4954f320b5de4e1658a0e1cf6136326fbf2be189 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 23 Sep 2026 07:18:36 +0000 Subject: [PATCH 3/5] chore(ci): re-trigger E2E after emulator flake on rotation test Git-Session-Id: 7e8e From f4cce4ca224696d6470b9be62d6f5c578a09261b Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 23 Sep 2026 07:47:45 +0000 Subject: [PATCH 4/5] fix(test): close seed statement so rust can exclusive-lock sqlite.db UpgradeWithHistoryTest left the compiled INSERT statement open. SQLiteStatement holds a SQLiteClosable ref, so db.close() did not drop the last reference and the Java connection stayed alive. rust then panicked on the v6 exclusive index migration (`database is locked`) and events/count stayed 500 for the rest of the 60s wait. Also delete leftover -wal/-shm after close. Git-Session-Id: 858a0c7e-764d-5961-a03a-156ec4922b8d --- .../android/UpgradeWithHistoryTest.kt | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt b/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt index 7e918b0d..b4197d99 100644 --- a/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt +++ b/mobile/src/androidTest/java/net/activitywatch/android/UpgradeWithHistoryTest.kt @@ -187,28 +187,38 @@ class UpgradeWithHistoryTest { ) val insert = db.compileStatement("INSERT INTO events(bucketrow, starttime, endtime, data) VALUES (?, ?, ?, ?)") - val data = """{"app":"com.android.chrome","package":"com.android.chrome","classname":"x"}""" - // 2024-01-01T00:00:00Z in nanoseconds; events are back to back and disjoint. - val start = 1_704_067_200L * 1_000_000_000L - db.beginTransaction() try { - for (i in 0 until LEGACY_EVENTS) { - val s = start + i * EVENT_NS - bind(insert, 1, s, s + EVENT_NS - 1, data) + val data = """{"app":"com.android.chrome","package":"com.android.chrome","classname":"x"}""" + // 2024-01-01T00:00:00Z in nanoseconds; events are back to back and disjoint. + val start = 1_704_067_200L * 1_000_000_000L + db.beginTransaction() + try { + for (i in 0 until LEGACY_EVENTS) { + val s = start + i * EVENT_NS + bind(insert, 1, s, s + EVENT_NS - 1, data) + } + val cutover = start + LEGACY_EVENTS * EVENT_NS + bind(insert, 1, cutover - EVENT_NS / 2, cutover + EVENT_NS / 2, data) + for (i in 0 until DESTINATION_EVENTS) { + val s = cutover + i * EVENT_NS + bind(insert, 2, s, s + EVENT_NS - 1, data) + } + db.setTransactionSuccessful() + } finally { + db.endTransaction() } - val cutover = start + LEGACY_EVENTS * EVENT_NS - bind(insert, 1, cutover - EVENT_NS / 2, cutover + EVENT_NS / 2, data) - for (i in 0 until DESTINATION_EVENTS) { - val s = cutover + i * EVENT_NS - bind(insert, 2, s, s + EVENT_NS - 1, data) - } - db.setTransactionSuccessful() } finally { - db.endTransaction() + // SQLiteStatement holds a SQLiteClosable ref on the database. + // db.close() only drops one ref, so an unclosed statement keeps + // the Java connection alive. rust then panics on BEGIN EXCLUSIVE + // for the v6 index (`database is locked`) and events/count stays 500. + insert.close() } } finally { db.close() } + File(file.path + "-wal").delete() + File(file.path + "-shm").delete() Log.i(TAG, "Seeded ${file.length()} bytes of history into ${file.path}") } From 27ad04b43e6714464d5c23a83b3572b003eac8c1 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 23 Sep 2026 08:17:45 +0000 Subject: [PATCH 5/5] chore(ci): re-trigger E2E after emulator flake on syncToggleReceivesRealTap Git-Session-Id: 702c