In order to meet common needs of applications running on CE devices, Cobalt implements a well-defined web application lifecycle, managing resources and notifying the application as appropriate.
The application lifecycle has some changes from Cobalt 22:
The new Concealed state is used for applications that are not visible but may use CPU or network resources. This state is used to both replace the Preloading state, and as an intermediate state between Blurred and Frozen.
The Frozen state most closely resembles the previous Suspended state, during which applications do not have network access.
Most platforms should only need to replace ‘Pause’ with ‘Blur’, ‘Unpause’ with ‘Focus’, ‘Suspend’ with ‘Freeze’, and ‘Resume’ with ‘Reveal’.
Since there is no longer a special Preloading state, applications should no longer use the Start event when a preloaded application is brought to the foreground. Instead, the same event(s) used for backgrounded applications (Concealed or Frozen) should be used.
To signal that the application is being ‘backgrounded’, the use of Suspend should be replaced with Freeze.
To signal that the application is being ‘foregrounded’, the use of Unpause should be replaced with Focus.
Note: If a platform is using Resume (Reveal) to signal that an application is being ‘foregrounded’, then that may result in unexpected application behavior, unless a subsequent Unpause (Focus) is also used when the application receives input focus.
More details about lifecycle states and state changes can be found in src/starboard/event.h
.
SbEventType
values.The SbEventType
enum is defined in src/starboard/event.h
.
kSbEventTypePause
value is renamed to kSbEventTypeBlur
.kSbEventTypeUnpause
value is renamed to kSbEventTypeFocus
.kSbEventTypeSuspend
value is replaced by kSbEventTypeConceal
and kSbEventTypeFreeze
.kSbEventTypeResume
value is replaced by kSbEventTypeUnfreeze
and kSbEventTypeReveal
.The corresponding helper functions in starboard::shared::starboard::Application
(implemented in starboard/shared/starboard/application.cc
) that inject events with these values have been updated correspondingly:
Pause()
method is renamed to Blur()
.Unpause()
method is renamed to Focus()
.Suspend()
method is replaced by Conceal()
and Freeze()
.Resume()
method is replaced by Unfreeze()
and Reveal()
.Platforms that inject events themselves should be updated to use renamed event type values, and platforms that use the helper functions should be updated to call the corresponding renamed helper functions.
SbSystemRequest
functions.The SbSytemRequest
functions are declared in src/starboard/system.h
SbSystemRequestPause
event is renamed to SbSystemRequestBlur
SbSystemRequestUnpause
event is renamed to SbSystemRequestFocus
SbSystemRequestSuspend
event is replaced by SbSystemRequestConceal
and SbSystemRequestFreeze
SbSystemRequestResume
event is replaced by SbSystemRequestUnfreeze
and SbSystemRequestReveal
Starboard Application State | Page Visibility State | Window Focused |
---|---|---|
Started | visible | true |
Blurred | visible | false |
Concealed | hidden | false |
Frozen | hidden | false |
When transitioning between Concealed and Frozen, the document.onfreeze and document.onresume events from the Page LifeCycle Web API will be dispatched.
The application is running, visible, and interactive. The normal foreground application state. May be the start state, or can be entered from Blurred.
May only transition to Blurred. In Linux desktop, this happens anytime the top-level Cobalt X11 window loses focus. Linux transition back to Started when the top-level Cobalt X11 window gains focus again.
The application may be fully visible, partially visible, or completely obscured, but it has lost input focus, so will receive no input events. It has been allowed to retain all its resources for a very quick return to Started, and the application is still running. May be entered from or transition to Started or Concealed at any time.
The application is not visible and will receive no input, but is running. Can be entered as the start state. May be entered from or transition to Blurred or Frozen at any time. The application may be terminated in this state without notification.
Upon entering, all graphics resources will be revoked until revealed, so the application should expect all images to be lost, and all caches to be cleared.
The application should shut down playback, releasing resources. On resume, all resources need to be reloaded, and playback should be reinitialized where it left off, or at the nearest key frame.
The application is not visible and will receive no input, and, once Frozen, will not run any code. May be entered from or transition to Concealed at any time. The application may be terminated in this state without notification.
Upon entering, all graphics and media resources will be revoked until resumed, so the application should expect all images to be lost, all caches to be cleared, and all network requests to be aborted.
Currently, Cobalt does not manually stop JavaScript execution when it goes into the Frozen state. In Linux desktop, it expects that a SIGSTOP
will be raised, causing all the threads not to get any more CPU time until resumed. This will be fixed in a future version of Cobalt.
The starboard application lifecycle, with descriptions of the states and the state changes can be found in src/starboard/event.h
.
For applications that can be preloaded, the platform should send kSbEventTypePreload
as the first Starboard event instead of kSbEventTypeStart
. Subclasses of src/starboard/shared/starboard/application.cc
can opt-in to use the already implemented support for the --preload
command-line switch.
If started with kSbEventTypePreload
, the platform can at any time send kSbEventTypeFocus
when the application brought to the foreground. In Linux desktop (linux-x64x11), this can be done by sending a SIGCONT
to the process that is in the Preloading state (see starboard/shared/signal/suspend_signals.cc
)
If the platform wants to only give applications a certain amount of time to preload, they can send SbSystemRequestFreeze
to halt preloading and move to the Frozen state. In Linux desktop, this can be done by sending SIGUSR1 to the process that is in the Preloading state.
The platform Starboard implementation must always send events in the prescribed order - meaning, for example, that it should never send a kSbEventTypeConceal
event unless in the Blurred state.
Most porters will want to subclass either starboard::shared::Application
(in src/starboard/shared/starboard/application.cc
) or starboard::shared::QueueApplication
(in src/starboard/shared/starboard/queue_application.cc
), as these are reference classes that rigorously implement the Starboard application lifecycle. They are optional, and platforms can directly dispatch events to SbEventHandle(), but it is then up to them to ensure that events are always sent in the correct state as specified in the Starboard documentation.
starboard::shared::Application
(in starboard/shared/starboard/application.cc
) guarantees the correct ordering by implementing a small state machine that ignores invalid application state transitions, and inserts any necessary transitions to make them valid. For example, you can call starboard::shared::Application::Conceal()
, and if you are in Blurred, it will just dispatch a kSbEventTypeConceal
event. But if you call Conceal()
in the Started state, it will first dispatch kSbEventTypeBlur
, followed by a kSbEventTypeConceal
event. If you call Conceal()
in the Concealed state, it just does nothing.
This behavior can be ensured by only dispatching events to SbEventHandle() using Application::DispatchAndDelete()
either directly, or indirectly such as by using Application::RunLoop()
with the default implementation of Application::DispatchNextEvent()
.
To control starting up in the Concealed state for preloading, Application
subclasses must override two functions:
class MyApplication : public shared::starboard::QueueApplication { // [ ... ] bool IsStartImmediate() override; bool IsPreloadImmediate() override; // [ ... ] }
To start up in the Concealed state, IsStartImmediate()
should return false
and IsPreloadImmediate()
should return true
.
To start up in the Starting state (which is the default), IsStartImmediate()
should return true
and IsPreloadImmediate()
will not be called.
To delay starting up until some later event, IsStartImmediate()
and IsPreloadImmediate()
should both return false
. No initial event will be automatically sent to the application, and it is then up to the porter to dispatch a kSbEventTypeStart
or kSbEventTypePreload
event as the first event. This is useful if you need to wait for an asynchronous system activity to complete before starting Cobalt.
To support the --preload
command-line argument:
bool IsStartImmediate() override { return !HasPreloadSwitch(); } bool IsPreloadImmediate() override { return HasPreloadSwitch(); }