Back process-only triggers with an owned foreground service #23

Open
opened 2026-09-16 22:16:09 +02:00 by morten-olsen · 0 comments
Owner

Some Android broadcasts cannot be delivered to a manifest receiver, only to one registered at runtime, so the trigger
only fires while the Macros process happens to be alive. AudioRouteReceiver and ScreenStateReceiver already live
with this through dynamicActionsByEvent, and RINGER_MODE_CHANGED is the same shape — which is why a ringer-mode
trigger was left out of the first device-controls increment.

Proposal

Where such a trigger exists and a workflow actually subscribes to it, run a foreground service that keeps the process
alive and holds the dynamic registrations. The service is owned exactly like the current registrations: derived from
trigger subscriptions and durable continuations by BackgroundResourceManager, started when the first owner appears and
stopped when the last one disappears. No workflow needs it, no service runs.

Points to settle

  • Which events genuinely need it. Prefer a manifest receiver wherever the broadcast is exempt from implicit-broadcast
    restrictions; this is only for the ones that are not.
  • Foreground service type and notification text. It is a persistent, user-visible cost, so the notification should name
    which automations are keeping it alive, and the Background activity screen should project it like any other resource.
  • Battery honesty. BackgroundResourceManager already reports qualitative battery behaviour per resource; a
    process-resident service is a materially different cost from an alarm and must be labelled as such.
  • Whether the user opts in per workflow or per event, rather than a service appearing silently because a trigger was
    added.
  • Interaction with the existing RUN_AS_NON_EXPEDITED_WORK_REQUEST path and with #21, since a live foreground service
    also removes the background foreground-service start problem for playback.

Why it is worth doing

Without it these triggers are close to decorative: they appear in the catalogue, compile, and then rarely fire. Either
back them properly or mark them unavailable with a reason, the way planned event sources already are — a trigger that
silently does not fire is the worst of the three options.

Some Android broadcasts cannot be delivered to a manifest receiver, only to one registered at runtime, so the trigger only fires while the Macros process happens to be alive. `AudioRouteReceiver` and `ScreenStateReceiver` already live with this through `dynamicActionsByEvent`, and `RINGER_MODE_CHANGED` is the same shape — which is why a ringer-mode trigger was left out of the first device-controls increment. ## Proposal Where such a trigger exists and a workflow actually subscribes to it, run a foreground service that keeps the process alive and holds the dynamic registrations. The service is **owned exactly like the current registrations**: derived from trigger subscriptions and durable continuations by `BackgroundResourceManager`, started when the first owner appears and stopped when the last one disappears. No workflow needs it, no service runs. ## Points to settle - Which events genuinely need it. Prefer a manifest receiver wherever the broadcast is exempt from implicit-broadcast restrictions; this is only for the ones that are not. - Foreground service type and notification text. It is a persistent, user-visible cost, so the notification should name which automations are keeping it alive, and the Background activity screen should project it like any other resource. - Battery honesty. `BackgroundResourceManager` already reports qualitative battery behaviour per resource; a process-resident service is a materially different cost from an alarm and must be labelled as such. - Whether the user opts in per workflow or per event, rather than a service appearing silently because a trigger was added. - Interaction with the existing `RUN_AS_NON_EXPEDITED_WORK_REQUEST` path and with #21, since a live foreground service also removes the background foreground-service start problem for playback. ## Why it is worth doing Without it these triggers are close to decorative: they appear in the catalogue, compile, and then rarely fire. Either back them properly or mark them unavailable with a reason, the way planned event sources already are — a trigger that silently does not fire is the worst of the three options.
Sign in to join this conversation.
No labels
bug
enhancement
feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
incubator/macros#23
No description provided.