Skip to content

Unattended remote access and remote control - #45

Open
Rambomst wants to merge 11 commits into
Ylianst:mainfrom
Rambomst:feature/unattended-remote-access
Open

Rambomst wants to merge 11 commits into
Ylianst:mainfrom
Rambomst:feature/unattended-remote-access

Conversation

@Rambomst

@Rambomst Rambomst commented May 30, 2026

Copy link
Copy Markdown

Turns the Android agent into a full unattended remote-control agent: background screen sharing and remote input, running as a persistent foreground service.

Unattended operation

  • specialUse foreground service + boot receiver, so it runs and reconnects without the app open.
  • Shared AgentController runtime for lifecycle; unattended setup prompts and settings.
  • Consent follows the server's consent flags and the app's Automatic Consent setting, for desktop and files sessions alike. Prompts show in-app or as a notification with Approve/Deny, expire after the server's consent timeout (30 s default), and file requests are held until approved.

Remote control (previously view-only)

  • Accessibility service provides background capture (takeScreenshot) and remote input.
  • Pointer input is streamed as live gestures: click = tap, hold = long press, drag = live drag (scrolling, selection handles, moving icons), wheel = swipe, right-click = Back, middle-click = Home.
  • Keyboard input into the focused field, password fields included, with Enter as the field's keyboard action.
  • Android global actions from the web panel (Add on-screen input panel for Android devices in remote desktop views MeshCentral#8123): Back, Home, Recents, app drawer (Android 14+ action with a Home + swipe fallback for older launchers), notifications, quick settings, lock, power.
  • Lock screen: the display is woken for a session, and a PIN or password can be typed blind since Android blanks the PIN pad from capture. Pattern locks are not supported.
  • Clipboard: upload from the browser works in the background; download only works while the agent app is in the foreground (Android 10+ restriction).

Files and software

  • Uploads work under scoped storage: MediaStore for the media folders and for Android 10, raw paths where Android allows them, clear errors on the Files tab otherwise, plus uploadhash/append/cancel support.
  • Media folders are listed from the MediaStore index (several times faster on large camera rolls), downloads fall back to MediaStore rows, and the web file editor's block download protocol is implemented.
  • Optional All files access (MANAGE_EXTERNAL_STORAGE) behind -PmeshAllFilesAccess=true, off by default because Google Play requires a use-case declaration for it.
  • Software tab lists launchable apps without QUERY_ALL_PACKAGES.

Platform & tooling

  • Merged latest upstream (Android SDK 37), file-download fix, edge-to-edge/system-bar handling.
  • GitHub Actions PR build workflow; developer docs under docs/; German translations complete, lint clean.

Known limitations

  • Sideloads are flagged by Play Protect (accessibility/remote-control category); install via adb install or enterprise deployment. On Android 13+ the accessibility toggle is a Restricted Setting unless installed via ADB/EMM.
  • Unattended capture is ~2-3 fps (Android throttles AccessibilityService.takeScreenshot).
  • Secure surfaces and the lock screen PIN pad are blanked by Android; multi-touch gestures such as pinch are not available.
  • Without All files access, other apps' non-media files on Android 13+ can be listed but not transferred.

Disclaimer: developed with an AI coding assistant.

Rambomst added 3 commits May 30, 2026 21:57
- Add foreground service, boot receiver, and accessibility remote control
- Route agent lifecycle through shared runtime controller
- Add unattended setup prompts and settings status entries
- Improve remote desktop refresh and session notifications
- Update Gradle and scanner dependency versions
…tter battery usage

- Add retry backoff logic with delay for agent reconnection attempts
- Introduce `shouldKeepForegroundServiceRunning` for better service control
- Optimise frame encoding with idle frame delay adjustments
- Enhance user disconnect handling via shared preferences
- Adjust remote desktop frame capturing to dynamically handle delays
- MeshAgent: stop starting projection immediately after the agent control
  connection authenticates.
- AgentRuntime: require an active desktop tunnel before starting screen
  projection.
@Rambomst

Copy link
Copy Markdown
Author

Ive had this running on two devices without any issues for the past week or so. My initial commit introduce some battery issues but that was resolved and now its back to basically using nothing.

…s disabled

- Implement user consent prompt via dialogs and notifications for remote desktop access.
- Add new notification channel for "Approve/Deny" screen sharing actions.
- Ensure thread-safe handling and lifecycle management for capture processes.
- Remove redundant battery optimization request logic.
- Optimize screenshot capture flow with throttling and backoff mechanisms.
@Rambomst

Rambomst commented Jun 14, 2026

Copy link
Copy Markdown
Author

A few fixes to the unattended consent flow, with Play Store approval in mind.

  • Consent is properly enforced now. With Automatic Consent off, every session has to be approved (in-app dialog, or Approve/Deny on the notification), so there's no silent screen capture, which is the main thing Google flags for apps like this.
  • Removed the battery optimization popup that auto-fired on launch, since auto-firing that intent is a known rejection trigger. It's only reachable from Settings now.
  • Capture only runs during an active session and shows a persistent notification plus a per-session one, so it stays transparent rather than looking like spyware.

To hopefully get this through review we need to do this in Play Console:

  • Complete the Accessibility API declaration and add a prominent in-app disclosure, framed as person-driven remote support as Google restricts accessibility use for automation as of the Jan 2026 policy change.
  • Fill in the foreground service types declaration for the specialUse service which needs a short justification and a demo video. Something like this:

MeshCentral Agent is a remote management/support tool. The foreground service keeps a persistent connection to the management server open so an administrator can reach the device on demand for remote desktop, file transfer, and commands. It has to run continuously and indefinitely; it isn't a finite data sync, media playback, location job, or any other predefined types, so specialUse applies.

  • There might also be a need to justify the battery optimization exemption, but that should be fine since this agent wouldn't work properly without it. If they did have an issue with it we can change it pretty easily but no harm in trying if this was already going through review.

How to sideload this with the accessibility changes:

Play Store > profile icon > Play Protect > gear/settings icon > toggle off "Scan apps with Play Protect" > install the APK > turn it back on after.

Then it blocks the accessibility access until we do this:
Settings > Apps > Mesh Central > App info⋮(top-right) > Allow restricted settings (authenticate), then the toggle works.

@GlitchedCod

Copy link
Copy Markdown

I hope that this get official one day, it's really a useful feature. The app itself without that is basically useless, it's not ok to ask a user how to go to the home menu, find all the apps, start the agent and then allow the screen sharing. Plus you can't see when a device is online on the MeshCentral dashboard since the app is not running in the background if it wasn't started at the launch of the device.

It would also be cool to add the "device administrator" rights to the app so that it can be set as the device owner, disable FRP on the device and so that the user can't uninstall it unless the device is wiped.

…ility handling

- Add `.github/workflows/android-pr-build.yml` to automate pull request builds, including debug APK upload.
- Refactor `MeshAccessibilityService` screenshot handling with callback extraction.
- Prevent unintended `NullPointerException` by introducing safe access and cleanup methods.
- Harden navigation logic in fragments with exception handling.
- Improve encoded bitmap memory handling during desktop frame capture.
- Update remote desktop input documentation to reflect accessibility feature improvements.
- Enhance WebSocket handling with safe null checks and connection closures.
- Add enhanced test coverage for edge cases and validation logic.
@Rambomst

Copy link
Copy Markdown
Author

@GlitchedCod Yeah I hope this gets merged as well, I brought it up at the community meeting last night so hopefully it will get some traction.

As for your request around device administrator functionality, that would be out of scope for this PR. One thing of note around that, I don't think that sort of functionality would ever make it to the play store build, so if it was to be development it would be something that needs to get manually deployed to each device you want to manage via ADB.

@marclaporte

Copy link
Copy Markdown

I know @kambereBr is testing this PR. yay!

I look forward to this as I have an Android device which I need to manage from time to time :-)

- Add `android:fitsSystemWindows="true"` to adjust layout for system bars.
- Set `app:statusBarForeground` in `AppBarLayout` for better visual consistency.
…le gesture execution

- Add drag gesture support with motion path tracking and duration-based gestures.
- Introduce gesture queueing mechanism to ensure sequential input handling.
- Optimise screenshot capture timing with dynamic wake handling and backoff adjustments.
- Enhance text input handling with precise cursor control and focused field management.
- Refine global action handling and keyboard interaction for seamless remote desktop experience.
@Rambomst Rambomst changed the title Add unattended remote access support Unattended remote access and remote control for the Android agent Aug 28, 2026
@Rambomst Rambomst changed the title Unattended remote access and remote control for the Android agent Unattended remote access and remote control Aug 28, 2026
@GlitchedCod

Copy link
Copy Markdown

I know @kambereBr is testing this PR. yay!

I look forward to this as I have an Android device which I need to manage from time to time :-)

That is so cool ! This is definitely gonna be a game changer. Fun fact I actually read this merge request yesterday to see if they were any update onto it.

@Rambomst

Copy link
Copy Markdown
Author

I have created a MeshCentral PR which implements some UI changes to facilitate interactions with this agent, things like buttons to go home/back/recents menu/etc.

MeshCentral #8123

@kambereBr

Copy link
Copy Markdown

Hi @Rambomst

Tested this PR with the on-screen input panel PR (Ylianst/MeshCentral#8123) on a Pixel 3a, Android 12 (Snapdragon 670), installed via ADB from Android Studio.

Works well:

  • App swiped away: stays online. Reboot: auto-starts and reconnects on its own.
  • First-run setup handled the accessibility flow, and the settings status updated once granted.
  • Background capture works with the app/AndroidAgent closed.
  • Back, Home, Recent, Notifications, Quick, Lock and Power buttons work fine.

Issues:

  • The "Waiting for user to grant access..." message stays on screen even after access is granted and I'm already controlling the device.
  • The "Apps" button does nothing. The other actions work, so it seems specific to this one.
  • Text selection has a small issue: the selection only expands if I release the mouse button inside the phone's screen. If the cursor is already outside the screen when I release it, nothing happens. Nothing unusual showed in logcat.
  • File upload does not work (download works fine). Nothing unusual showed in logcat here either.

I recorded a short screencast showing the text selection and file upload issues, attached below.

Maybe out of scope of this PR, please let me know if that is the case:

  • Long-press, right-click and drag-and-drop: couldn't find how to do these from the panel.
  • Clipboard both ways (copy on web, paste on phone and vice versa) is not available.
  • Opening/connecting to Files doesn't ask for consent on the device even when I choose "Ask Consent" on the web UI, I can access them silently. Should asking for consent be mandatory here?

I'll also test on an Android 16 device and send feedback if anything comes up.

Thank you for this PR, remote control is working really well.

MeshCentralAndroidAgent.mp4

@GlitchedCod

Copy link
Copy Markdown

Woah ! So cool already !

Good luck for the little patches needed.

- Introduce `DesktopInput` for refined mouse input handling, including button presses, releases, movement, and double-click decoding.
- Add `MeshHttp` for centralised HTTP client configuration with connection pool reuse.
- Implement `UploadStorage` for file upload and shared storage management, with support for raw public file access and MediaStore integration.
- Update `README.md` to document remote desktop capabilities and extended user consent handling.
- Enhance accessibility service (`MeshAccessibilityService`) to support expanded input gestures, including taps, drags, and double-taps, with queued gesture processing for improved input fidelity.
@Rambomst

Copy link
Copy Markdown
Author

@kambereBr Thanks again for the detailed test, all four should now be fixed.

  • Banner: the agent never cleared "Waiting for user to grant access" once capture started. Both capture paths clear it now.
  • Apps: the accessibility all-apps action is only wired to the launcher from Android 14, so on 12 and 13 it did nothing. The agent uses it on 14+ and checks the launcher came up, otherwise it goes Home and swipes up.
  • Selection drag: input was replayed as one gesture on button release, and the browser never delivers a release outside the canvas. Input is now streamed live: drags move as you go, holding the button is a long press, right-click is Back, middle-click is Home. The viewer side in Add on-screen input panel for Android devices in remote desktop views MeshCentral#8123 now releases the button at the canvas edge.
  • Upload: your target was Sdcard/Photos, a non-standard folder scoped storage refuses, and the agent said nothing. Uploads fall back to MediaStore where Android allows it, the Files tab now shows why a folder is refused, and re-uploading a same-named file no longer hangs.

Also in the same push: files sessions ask for consent per the server's flags and the app setting, clipboard upload to the device (download only works while the app is in front, an Android restriction), a Software tab inventory, and blind PIN unlock, since Android blanks the PIN pad from capture.

…ility service text handling, and optimise screen capture flow

- Add drag-to-select functionality for text fields, including character bounds calculation and shift-based extension.
- Improve text field handling with shadow state management to prevent input inconsistencies.
- Refactor legacy key handling for modifiers, shortcuts, and focused actions, including robust Ctrl-based operations.
- Optimise screenshot capture with sequence validation and fallback handling to address dropped requests.
- Replace adler32 checks with FNV-1a hashing for improved tile hash accuracy.
- Expand unit test coverage (`TileHashTest`) to validate hash and change detection logic.
@Rambomst

Copy link
Copy Markdown
Author

Update since the above comment:

  • Keyboard: on Android 13+ typing now goes through the system input method, so fast typing stays in order and Ctrl+A/C/X/V, Shift+arrows, Delete and Tab work. Older releases keep the field-rewrite path with a guard against dropped characters.
  • Dragging on the focused text field selects text like a mouse; a click still places the caret and a hold still long-presses.
  • Capture: proper tile hashing and a watchdog for unanswered screenshot requests, which fixed a ghosting problem where a stale frame stayed on screen. The viewer in Add on-screen input panel for Android devices in remote desktop views MeshCentral#8123 also no longer stalls on a tile it can't decode.

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.

4 participants