Skip to content

Conversation

@0xbrayo
Copy link
Member

@0xbrayo 0xbrayo commented Oct 21, 2025

Important

Integrate aw-sync into Android app with JNI support, update build configurations, and enhance sync operations and testing.

  • aw-sync Integration:
    • Add SyncInterface.kt for JNI bindings and sync operations.
    • Implement SyncScheduler.kt for periodic sync tasks.
    • Add SyncAlarmReceiver.kt for handling sync alarms.
    • Update BackgroundService.kt to start sync scheduler.
  • Build and Configuration:
    • Update build.gradle to Kotlin 1.9.0 and Gradle 8.14.
    • Set minSdkVersion to 26 and targetSdkVersion to 34 in mobile/build.gradle.
    • Update gradle-wrapper.properties to use Gradle 8.14.
    • Modify .gitmodules to remove aw-server-rust submodule.
  • AndroidManifest and Permissions:
    • Add permissions for FOREGROUND_SERVICE and FOREGROUND_SERVICE_DATA_SYNC.
    • Update AndroidManifest.xml to include new services and permissions.
  • Testing and Linting:
    • Add WebWatcherTest.kt and ScreenshotTest.kt for testing web activities and screenshots.
    • Add lint-baseline.xml for linting configuration.
  • Miscellaneous:
    • Update README.md for build instructions.
    • Update Makefile to use magick instead of convert for image processing.

This description was created by Ellipsis for 234b123. You can customize this summary. It will automatically update as commits are pushed.

0xbrayo added 13 commits August 11, 2025 19:04
- Analyzed current aw-sync architecture and Android integration patterns
- Identified key challenges: build system, JNI bindings, storage paths
- Documented feasibility: FEASIBLE following aw-server pattern
- Created detailed implementation plan with 5 phases
- Noted that aw-sync already supports AW_SYNC_DIR env var (key enabler)

Main findings:
- aw-sync needs to be built as library for Android
- CLI dependencies (clap, ctrlc) need to be optional
- JNI bindings required following RustInterface.kt pattern
- Storage directory can be set via environment variable
- Overall complexity: Medium, no fundamental blockers
…ntation guide

- Marked phases 1-3 as complete in aw-server-rust (dev/sync-jni branch)
- Added detailed implementation guide for phases 4-5 in aw-android
- Includes complete code examples for:
  * SyncInterface.kt with JNI bindings
  * UI integration with sync buttons
  * WorkManager background sync
  * Storage permissions
- Added testing and troubleshooting sections
- Documented library rebuild and deployment steps

All Rust-side work (phases 1-3) complete and verified.
Android app integration (phases 4-5) ready to implement.
…ranch

Updated submodule to use fork with aw-sync JNI implementation.
This branch includes:
- JNI bindings for aw-sync operations
- Android build configuration
- Library preparation for Android integration
- Removed git submodule dependency
- Created symlink to ~/repos/aw-server-rust for direct development
- Added aw-server-rust to .gitignore
- This allows immediate use of local changes without submodule complexity
- Created SyncInterface class to interact with native aw-sync library
- Implemented JNI bindings for sync operations:
  * syncPullAll - pull from all hosts
  * syncPush - push local data
  * syncBoth - full bidirectional sync
  * getSyncDir - get sync directory path
- Async wrappers with callbacks for all sync operations
- Automatic sync directory setup in external storage
- Proper error handling and logging

Phase 4 implementation: Android app integration
- Modified SyncInterface to use Downloads/ActivityWatch/ directory
  * Static path for easy access by sync apps (Syncthing, etc.)
  * Falls back gracefully if storage not available

- Created SyncScheduler for automatic periodic syncing
  * First sync runs 1 minute after app starts
  * Subsequent syncs every 15 minutes while app is open
  * Runs syncBoth (pull + push) for full bidirectional sync
  * Logs all sync operations and results

- Integrated into MainActivity lifecycle
  * Starts scheduler in onCreate after server initialization
  * Stops scheduler in onDestroy to clean up resources

No UI needed - syncs automatically in background.
Users can access sync directory at: /sdcard/Download/ActivityWatch/

Phase 4 complete: Automatic background sync implementation
Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Changes requested ❌

Reviewed everything up to 975df0b in 2 minutes and 54 seconds. Click for details.
  • Reviewed 3377 lines of code in 25 files
  • Skipped 1 files when reviewing.
  • Skipped posting 9 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. .idea/compiler.xml:4
  • Draft comment:
    The is updated to 21. Ensure that all modules and dependencies are compatible with JDK 21.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is asking the PR author to ensure compatibility with JDK 21, which falls under the rule of not asking the author to ensure behavior is intended or tested. It does not provide a specific suggestion or point out a specific issue.
2. mobile/build.gradle:10
  • Draft comment:
    minSdkVersion has been increased to 25. Confirm that dropping support for API 24 is intentional.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment violates multiple rules. It's asking for confirmation of intention, which is explicitly forbidden. It's also about platform/dependency support changes, which we're told to ignore. The change is small (24 to 25) and likely intentional given it was committed. Perhaps dropping API support could have major implications for users that we should be concerned about? Maybe this needs discussion? The rules explicitly state not to ask for confirmations or make speculative comments. Platform support changes are intentional decisions that don't need review confirmation. Delete this comment as it violates rules against asking for confirmations and commenting on dependency/platform support changes.
3. mobile/src/main/AndroidManifest.xml:30
  • Draft comment:
    Screen orientation is locked to 'portrait'. Consider whether supporting 'unspecified' or 'fullSensor' might improve user experience on devices like Chrome OS.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. mobile/src/main/java/net/activitywatch/android/RustInterface.kt:56
  • Draft comment:
    The server startup logic checks port availability via binding a socket. Consider refining error handling for concurrency – e.g., ensuring proper reset of the serverStarted flag if startup fails unexpectedly.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
5. mobile/src/main/java/net/activitywatch/android/SyncInterface.kt:19
  • Draft comment:
    Using the public Downloads directory (via Environment.getExternalStoragePublicDirectory) for sync storage exposes data. Verify that this directory choice meets your privacy and security requirements.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The comment raises a valid security concern, but it's phrased as "verify that..." which violates our rules. The code comment indicates this was an intentional choice for user accessibility. The security implications are likely already known and accepted by the developers. This seems more like asking for confirmation rather than pointing out a definite issue that needs fixing. The security concern is legitimate and could be serious if the developers haven't considered it. Maybe this should be kept as a warning? While the security concern is valid, the comment is phrased as a verification request rather than an actionable issue. The code comment shows this was a deliberate choice for user accessibility. Delete the comment because it violates our rule about verification requests ("Verify that...") and appears to be questioning an intentional design decision rather than pointing out a definite issue requiring changes.
6. mobile/src/main/java/net/activitywatch/android/SyncScheduler.kt:19
  • Draft comment:
    The sync scheduler uses a fixed 15‐minute interval. Consider making this interval configurable for different deployment scenarios.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% While making the interval configurable could add flexibility, there's no evidence this is actually needed. The 15-minute interval seems like a reasonable default. Without knowing the requirements or use cases, suggesting configuration adds unnecessary complexity. The comment is speculative about "different deployment scenarios" that aren't demonstrated to exist. The suggestion could be valuable if there are indeed different deployment needs. Making it configurable early could prevent future refactoring. We should follow YAGNI principle - don't add configuration without clear evidence it's needed. If different intervals are needed later, it's a simple refactor. Delete the comment as it suggests adding complexity without clear evidence of need, violating the rule about speculative comments.
7. mobile/src/main/java/net/activitywatch/android/parser/SessionParser.kt:148
  • Draft comment:
    The strict RESUME→PAUSE matching loop skips sessions if an extra RESUME occurs. Make sure this strict mode meets your intended session detection requirements and consider logging additional context for debugging.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 50% <= threshold 50% The comment is asking the PR author to ensure that the strict mode meets their intended requirements, which violates the rule against asking for confirmation of intention. However, it also suggests considering logging additional context for debugging, which is a specific suggestion. The first part of the comment should be removed, but the second part is useful.
8. mobile/src/main/java/net/activitywatch/android/watcher/UsageStatsWatcher.kt:124
  • Draft comment:
    In setupAlarm(), the PendingIntent uses FLAG_IMMUTABLE which is good; ensure the chosen ELAPSED_REALTIME alarm type fits your scheduling needs even under Doze conditions.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
9. mobile/src/main/java/net/activitywatch/android/RustInterface.kt:95
  • Draft comment:
    Typo suggestion: The log message in the createBucketHelper method reads "Bucket with ID '$bucket_id', already existed. Not creating." Consider rephrasing it to something like "Bucket with ID '$bucket_id' already exists. Not creating." to improve clarity.
  • Reason this comment was not posted:
    Comment was on unchanged code.

Workflow ID: wflow_TuLG6TnCI6KMpSnF

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

callback: (Boolean, String) -> Unit,
syncFn: () -> String
) {
val executor = Executors.newSingleThreadExecutor()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new single-thread executor is created for each async sync call. Consider using a shared executor to avoid thread churn if sync operations are frequent.

}
}

private inner class SendSessionEventTask : AsyncTask<Void, AppSession, Int>() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AsyncTask SendSessionEventTask is an inner class and may leak the Context. Consider refactoring it to a static inner class or using coroutines to prevent memory leaks.

DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: In the comment on collecting java command arguments (line 206), JAVA_OPTS is mentioned twice and optsEnvironmentVar appears. This seems like an error; likely it should list DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS instead.

Suggested change
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS are not allowed to contain shell fragments,

@0xbrayo 0xbrayo marked this pull request as draft October 21, 2025 15:11
@0xbrayo
Copy link
Member Author

0xbrayo commented Dec 2, 2025

@ellipsis-dev review

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to 234b123 in 2 minutes and 33 seconds. Click for details.
  • Reviewed 4368 lines of code in 34 files
  • Skipped 1 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. gradlew:206
  • Draft comment:
    Typo: The comment on line 206 repeats 'JAVA_OPTS' twice. Please remove the duplicate or clarify if two distinct options were intended.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This is the Gradle wrapper script (gradlew), which is a generated file from the Gradle project itself. The comment at line 57-58 explicitly states "This script is generated from the Groovy template https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt within the Gradle project." This means the file is auto-generated and shouldn't be manually edited. If there's truly a typo, it would need to be fixed upstream in the Gradle project itself, not in this repository. The comment is technically correct that "JAVA_OPTS" appears twice on line 206, but suggesting a fix here is not appropriate since this is generated code. The PR author is likely just updating the Gradle wrapper version, and any issues in the generated script should be reported to Gradle, not fixed locally. However, I should verify if this is actually a typo or intentional. Looking at the comment, it mentions "DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar" - the duplicate JAVA_OPTS does seem odd. But even if it's a real typo, the key issue is that this is generated code from Gradle itself, so the comment is misdirected. Even if there is a genuine typo in the generated Gradle wrapper script, the comment should be deleted because: 1) This is auto-generated code that shouldn't be manually edited, and 2) The comment violates the rule about not commenting on things that should be obvious or that are outside the scope of this PR (the PR is updating the wrapper, not fixing Gradle's upstream issues). Delete this comment. The gradlew file is an auto-generated Gradle wrapper script that shouldn't be manually edited. Any issues with the generated content should be reported to the Gradle project upstream, not fixed in this repository.
2. mobile/build.gradle:48
  • Draft comment:
    Typo: The line 'coreLibraryDesugaringEnabled true' is missing an '='. It should be written as 'coreLibraryDesugaringEnabled = true' to match the assignment syntax.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment is flagging what it perceives as a syntax inconsistency. However, in Gradle's Groovy DSL, both property = value and property value are valid syntaxes. The comment is treating this as a typo or error, but it's actually valid syntax. While consistency might be nice, this is not a bug or error that needs fixing. The comment is making a style suggestion at best, not identifying a real issue. According to the rules, I should not keep comments about code quality/style unless they are clearly actionable and important. This is a minor style inconsistency at best, and the code will work fine as-is. The build would not fail because of this. Could there be a specific reason why the equals sign is preferred in this context? Perhaps certain Gradle versions or Android Gradle Plugin versions require the equals sign for this specific property? I might be missing domain-specific knowledge about Android Gradle configuration. Even if there were version-specific requirements, the comment doesn't provide that context and simply calls it a "typo" to match "assignment syntax." If this were a real issue that would cause build failures, it would be caught by the build system. The comment is framed as a style/consistency issue, not a functional requirement. This comment should be deleted. It's flagging valid Gradle/Groovy syntax as a "typo" when both property value and property = value syntaxes are acceptable. This is at most a minor style preference, not a real issue, and doesn't meet the bar for a useful review comment.

Workflow ID: wflow_IunrW1SkDnKSlb1z

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants