Activity Manager

The Activity Manager service (com.palm.activitymanager) acts as a traffic cop for Activities (apps, services, tasks, network flows, etc.) running on the device, balancing Activity priorities and system resources to optimize the user's experience. The Activity Manager has the following goals:

  • The device remains responsive as possible.
  • Background tasks do not affect device responsiveness.
  • Foreground task with focus can always continue.
  • Power use is optimized.
  • Activities are prioritized and started, stopped, paused or canceled accordingly.
  • Activities are not lost due to system reboots.

In this Section:

  • Activity Manager Features
  • Activity Participants
  • Activity Lifecycle
  • Activity Checklists

See also: Activity Manager Data Types

 


Activity Manager Features

Activity Manager features include:

  • Prioritization -- Activities should be created for any non-trivial use of system resources (i.e., CPU, the network). Apps and services can assign an Activity priority level property. The Activity Manager prioritizes Activities based on this and Activities' use of system resources to optimize the user's experience. Foreground Activities are given normal priority; background Activities are given a low priority and run as resources allow. You can set an Activity's priority with the Type object, which is an Activity object sub-property.

  • Services run when needed -- To conserve system resources, services should run only when needed. Services should not remain running while subscribed to other services such as the TIL (Telephony Interface Layer) or db8 (JSON database), waiting for events or the network to begin work or to communicate outside the device. The Activity Manager does not implement this capability, but it does facilitate it -- services and their Activities can use the Activity Manager to subscribe to other services on their behalf and monitor for responses, invoking a callback when a specified event has occurred. While waiting, services can exit, returning resources to the device until the service is again needed.

  • Scheduling and alignment -- Activities can be scheduled to run at a specific time or at a particular interval. Activities can be scheduled to run as a background Activity in the future if not needed immediately. To reduce how often the device is suspended and restarted, the Activity Manager batches Activities scheduled to run at approximately the same interval. See the Schedule data type for more information.

  • Persistence -- Using db8 state storage, Activities can persist across a device reboot. They can be atomically updated and re-scheduled to avoid being lost due to version updating, device crashes, or lost service. Use the Type object's "persist" flag to set this.

  • Requirements prior to running are met -- The Activity Manager can ensure that power-state, network access, telephony, battery and other pre-conditions are met before an Activity runs. In addition, the Activity Manager can send out update notices if these pre-conditions change while the Activity is running. See the Requirements data type for more information.

  • Triggers -- Activities with triggers do not run until an event occurs on a subscribed method. The Activity Manager can subscribe on behalf of the Activity creator and invoke the specified callback when a trigger event fires. This allows the service to exit and let the Activity Manager wait on its behalf. See the Triggers data type for more information.

  • Complete-and-Restart Activities -- When a service finishes processing an Activity, it can request the Activity Manager to restart the Activity with updated schedule, triggers, requirements, and callbacks.

    See the complete API for more information.

  • Power Control -- The Activity Manager can ensure the device remains powered while an Activity is running. It can also debounce power, allowing the device to remain powered for a short time waiting for a new task to start. For example, in the case where a network sync service sent out a request and is waiting on an imminent response. In this case, it is better to wait since it takes less power than having the device suspend and restart.

    Your service can request this functionality using the Type object's "power" and "powerDebounce" properties.

  • Standardized control -- The Activity Manager provides a standardized interface for controlling (start, stop, pause, and cancel) activity lifecycle.

 


Activity Participants

A running Activity must have a parent. Initially, that would be the service or app that creates it. In addition, Activities can have subscribers, which include the Activity's parent, potential adopters and others wishing to monitor the Activity. Subscribers are services or apps that are sent Activity event notifications (start, stop, etc., see Activity Events for a complete list). Adopters are subscribers who can also take over as an Activity's parent. They register their willingness to do this with the adopt method. Apps or services can subscribe to an Activity through either the create, adopt, or monitor methods.

If an Activity loses its parent, and there are no waiting adopters, it is canceled unless marked as persistent or explicit, and all subscribers are sent cancel events. When this happens, adopters have the opportunity to take over as the parent and keep the Activity alive. However, it is canceled if no app or service adopts the Activity during that time.

An Activity with a callback can briefly run without a parent while the callback is invoked; the Activity Manager waits for a specified time to see if the app or service adopts the Activity. If not adopted after that time, the Activity is canceled. If an Activity is marked as being persistent or explicit, it is restarted.

 


Activity Lifecycle

In most cases, an Activity is created to run in either the foreground or the background. A foreground Activity runs as soon as its specified prerequisites (schedule, requirements, triggers) are met.

When its prerequisites are met, a background Activity is moved into a ready queue, and a limited number are allowed to run depending on system resources. Activities can be scheduled to run at a specific time or when certain conditions (requirements) are met or events (triggers) occur. They can also be scheduled to repeat at a particular interval. The Activity Manager attempts to batch-run Activities repeating at the same interval, allowing the device to suspend/restart less frequently, conserving battery use.

When an Activity finishes, the parent informs the Activity Manager with the complete method. If the Activity has other subscribers, they are sent "complete" events. An Activity is not considered finished until all of its subscribers exit.

An Activity marked explicit (via the Type object) can only be terminated by its parent with a stop, cancel, or complete call. Otherwise, after a timeout, it is restarted via a specified callback. Explicit termination is also required if the Activity is defined with the persist attribute. In this case, the Activity state is stored in db8, continues across reboots, and requires explicit termination.

Activities that need to run to completion should be marked "explicit" or "persist".

There are four methods specifically for ending an Activity:

  • cancel -- The Activity is ended immediately, with little or no time for clean-up.

  • complete -- The Activity is ended, with an option to restart with new attributes.

  • stop -- The Activity is ended, but some time is allowed for clean-up.

  • release -- The parent frees an Activity, allowing time for adopters to take over as the parent and let the Activity continue. If no adopter takes over, the Activity is ended.

 

Handling Incoming Service Requests

Any entity with bus access can generate a service request. Mostly they come from apps or the Activity Manager itself as a result of a scheduled or triggered Activity.

If the call comes from an app, the Mojo Framework should have allocated an Activity for the app (or the specific card) and passed it along with the other service call arguments. If the incoming call is the callback generated for a scheduled Activity that has been selected to run, the Activity Manager adds the "$activity" property to the other callback parameters. This property contains information about the Activity, such as its requirements, triggers, and metadata.

Before processing a request, a service should associate itself with the Activity via the adopt or monitor calls. If the request could have a life of its own (a sync, for example), then calling adopt makes sense since the service could take over as the Activity's parent if the current parent exits. Otherwise, your service should call monitor.

A service should wait until the adopt or monitor call returns successfully before beginning Activity work. If either of these calls fail, it indicates the caller has exited and the request should not be processed.

Once adopt or monitor succeeds, the service can proceed to do the work indicated in the original incoming request. If the request was to simply kick-off a long running task, then the service should do this and simply return.

A service should continue to process incoming events on an Activity subscription. If a service receives a "cancel" event and the service did not use adopt to inform the Activity Manager that it was willing to take over as the Activity parent, it should be prepared to stop Activity work and unsubscribe. If it did use adopt and it receives the "orphan" event (indicating that the original parent(s) have unsubscribed and the service is now the Activity parent), then, when it is done, the service should call complete to inform the Activity Manager before unsubscribing.

 

Activity Lifecycle Flowchart

 

Example Lifecycle Flows

Normal inbound app request

  • App calls service method.
  • Service subscribes to Activity by calling adopt (or monitor) using the app-provided Activity ID.
  • Activity Manager returns success result to service.
  • Service performs requested work.
  • Service unsubscribes from Activity.
  • Service returns result to app.

Potentially long running inbound app request

  • App calls service method.
  • Service subscribes to Activity by calling adopt (or monitor) using the app-provided Activity ID.
  • Activity Manager returns success result to service.
  • Service returns success result to app.
  • Service performs requested work.
  • Service unsubscribes from Activity.

Incoming scheduled background activity

  • Activity Manager calls service-specified callback method.
  • Service subscribes to Activity by calling adopt (or monitor) using the app-provided Activity ID.
  • Activity Manager returns success result to service.
  • Service performs requested work.
  • Service calls complete for Activity.
  • Activity Manager returns success.
  • Service unsubscribes from Activity.

 


Activity Checklists

Incoming Requests

  • Does your Service adopt (or join) the Activities on incoming requests? If not, your Service is not properly prioritized, and could be killed if the Activity Manager thinks it is running without any Activities.

  • Does your Service wait for the adopt (or join) to succeed before proceeding to perform the request?

  • For a long running request, does your service watch for "cancel" events and stop processing the Activity if one is received?

  • For background and non-immediate Activities, does your service process a bite-sized chunk of work and then re-schedule the Activity if there is more work to do rather than leave the background Activity in the running state for a long period of time?

  • Did you remember to complete your persistent or explicit Activities? If not, your callback will continue to be invoked.

Scheduled Activities

  • Does your Service exit when it has no work, and use the Activity Manager to schedule an Activity to launch it when more work becomes available?

  • Does your Service check to make sure its Trigger calls did not produce errors? For example, if bad parameters are provided for the Trigger, it will repeatedly fire, placing your Service and the Activity Manager in a infinite loop.

  • Does your Service use complete to update an Activity with new db8 watch parameters, rather than calling complete followed by create to start a new Activity? A crash between those two calls could leave you with no Activity.

Scheduled Interval Activities

  • Does your Service use a smart interval for any repeating Activities, rather than creating a new scheduled Activity after the last completes?

  • Does your Service not use a "precise" interval if it does not need one? Precise intervals are not synchronized with other interval-based Activities and consume more power.

  • Does your Service call complete with "restart":true specified to reschedule the Activity?