Skip to content

Support offline Gemma model, fix scrollbar, and update build script#51

Open
Android-PowerUser wants to merge 5 commits intofeat-offline-gemma-scrollbar-apikey-refactor-18218192389146845628from
apk-delivery-394299877912208302
Open

Support offline Gemma model, fix scrollbar, and update build script#51
Android-PowerUser wants to merge 5 commits intofeat-offline-gemma-scrollbar-apikey-refactor-18218192389146845628from
apk-delivery-394299877912208302

Conversation

@Android-PowerUser
Copy link
Owner

  • Added support for offline Gemma 3n E4B it int4 litertlm model with download capability.
  • Implemented optimized VerticalScrollbar in PhotoReasoningScreen.
  • Enabled screenshots for the offline model.
  • Refactored PhotoReasoningViewModel to improve context handling and implement offline inference logic (simulated in this build due to dependency constraints).
  • Updated build_and_sign.sh to prevent keystore conflicts.
  • Included app-release-signed.apk.

PR created automatically by Jules for task 394299877912208302 started by @Android-PowerUser

…ed APK

Co-authored-by: Android-PowerUser <88908510+Android-PowerUser@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copy link

@amazon-q-developer amazon-q-developer bot left a comment

Choose a reason for hiding this comment

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

Summary

This PR adds offline Gemma model support with download capability, implements an optimized scrollbar, and updates the build script. I've identified 4 critical defects that must be fixed before merge:

Critical Issues Found

  1. ModelDownloadManager.kt (Line 24-26): Missing null check for getExternalFilesDir() - will crash when external storage is unavailable
  2. ModelDownloadManager.kt (Line 47-48): Unsafe cast of DownloadManager - will crash if service unavailable
  3. PhotoReasoningViewModel.kt (Line 424): Missing null check for getApplication() - can crash during initialization/cleanup
  4. build_and_sign.sh (Line 42-45): Hardcoded debug credentials used for release APK signing - severe security vulnerability (CWE-798)

Additional Concern

The API key validation logic (GenerativeAiViewModelFactory.kt lines 61-67) may block offline model usage since the offline Gemma model doesn't require an API key. While not visible in the diff, this should be verified to ensure offline functionality works correctly.

All identified issues have blocking severity and must be resolved before merging.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Comment on lines +42 to +45
-keystore debug.keystore \
-storepass android \
-alias androiddebugkey \
-keypass android \

Choose a reason for hiding this comment

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

🛑 Security Vulnerability: Hardcoded debug credentials in production build script. The debug.keystore uses hardcoded password "android" and is used to sign release APKs. This is a severe security issue - attackers can extract the keystore password and sign malicious APKs with your key. Use a production keystore with secure credentials for release builds.1

Footnotes

  1. CWE-798: Use of Hard-coded Credentials - https://cwe.mitre.org/data/definitions/798.html


// Check for offline model (Gemma)
if (currentModel == ModelOption.GEMMA_3N_E4B_IT) {
val context = getApplication<Application>().applicationContext

Choose a reason for hiding this comment

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

🛑 Crash Risk: Missing null check causes crash. getApplication() can return null in edge cases during ViewModel initialization or cleanup, causing NullPointerException when accessing applicationContext. This can crash the app when saving chat history.

Suggested change
val context = getApplication<Application>().applicationContext
val context = getApplication<Application>().applicationContext

Comment on lines 47 to 48
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)

Choose a reason for hiding this comment

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

🛑 Crash Risk: Unsafe type cast can crash. The getSystemService call returns Any? but is force-cast to DownloadManager without null checking. If DOWNLOAD_SERVICE is unavailable (rare but possible on some devices), this causes a crash.

Suggested change
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as? DownloadManager
?: throw IllegalStateException("DownloadManager not available")
downloadId = downloadManager.enqueue(request)

Comment on lines 24 to 26
fun getModelFile(context: Context): File {
return File(context.getExternalFilesDir(null), MODEL_FILENAME)
}

Choose a reason for hiding this comment

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

🛑 Crash Risk: Missing null check causes crash. getExternalFilesDir(null) can return null when external storage is unavailable or unmounted, causing a NullPointerException when passed to the File constructor. This will crash the app during model file operations.

Suggested change
fun getModelFile(context: Context): File {
return File(context.getExternalFilesDir(null), MODEL_FILENAME)
}
fun getModelFile(context: Context): File {
val externalDir = context.getExternalFilesDir(null)
?: throw IllegalStateException("External storage not available")
return File(externalDir, MODEL_FILENAME)
}

google-labs-jules bot and others added 4 commits February 15, 2026 02:34
…ed APK

Co-authored-by: Android-PowerUser <88908510+Android-PowerUser@users.noreply.github.com>
…ed APK

Co-authored-by: Android-PowerUser <88908510+Android-PowerUser@users.noreply.github.com>
…ed APK

Co-authored-by: Android-PowerUser <88908510+Android-PowerUser@users.noreply.github.com>
…ed APK

Co-authored-by: Android-PowerUser <88908510+Android-PowerUser@users.noreply.github.com>
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.

1 participant