blob: b94f1ba1505409e503f864f34f6f0cda36549d57 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.update;
/// The Manager protocol is used by a client that wishes to either check for an
/// update, or follow the status of ongoing updates.
///
/// The Manager provides a mechanism for checking for updates via the
/// [`Manager.CheckNow`] message.
@discoverable
protocol Manager {
/// Immediately check for an update, and optionally track the state and
/// progress of that update check.
///
/// + request `options` Options for how this request should be performed.
/// E.g. What kind of entity initiated this request?
/// E.g. Is monitoring an existing update check that
/// is already in process an acceptable
/// alternative?
///
/// + request `monitor` An interface on which to receive the status events
/// for this update check. The monitor is only valid
/// for this single update check, after that it will
/// not receive any more notifications and will be
/// closed.
///
/// * error If an update check cannot be started, an error will be returned.
/// The [`Monitor`], if provided, will not receive any notifications.
CheckNow(resource struct {
options CheckOptions;
monitor client_end:<Monitor, optional>;
}) -> (struct {}) error CheckNotStartedReason;
/// Performs any pending reboot of the system into an updated OS, if an
/// update has been staged for the next system startup.
///
/// Should be used when the platform is configured to let the product drive
/// reboot scheduling. If this method is called when the platform is not
/// configured to let the product drive reboot scheduling, no reboot will
/// occur, and the system will reboot on its own after an update.
///
/// In product-driven reboot configurations, the platform still contains a
/// backstop for post-update reboots. This means that if an update
/// is installed but the system has not rebooted before the backstop
/// duration occurs, the update system will automatically reboot the
/// system as a security measure. To avoid hitting this backstop,
/// products which desire control over reboot timing should call this
/// method roughly daily.
///
/// - response `rebooting` true if the system is rebooting, false if no
/// update was pending reboot.
PerformPendingReboot() -> (struct {
rebooting bool;
});
/// Monitor all update attempts as they start, as well as an in-progress
/// attempt, if there is one.
///
/// Arguments:
/// * |attempts_monitor| A protocol on which to receive |Monitor| instances
/// as update attempts start.
MonitorAllUpdateChecks(resource struct {
attempts_monitor client_end:AttemptsMonitor;
});
};
/// Configuration options for an update check.
type CheckOptions = table {
/// Who or what initiated this update attempt. This is taken as input to
/// Policy, and may influence how the update check is performed.
///
/// **This is a required field.**
1: initiator Initiator;
/// If an update check is already in progress, it's acceptable to instead
/// attach a Monitor to that in-progress update instead of failing this
/// request to check for updates. This may convert situations that would
/// have resulted in the ALREADY_IN_PROGRESS to be treated as non-error
/// cases.
2: allow_attaching_to_existing_update_check bool;
};
/// Who or what initiated the update check.
type Initiator = strict enum {
/// The update check was initiated by an interactive user, or the user is
/// otherwise blocked and waiting for the result of this update check. This
/// SHOULD only be used when there is a UI element or flow that a user has
/// interacted with which has initiated this update check.
USER = 1;
/// The update check was initiated by a service, not a user-facing aspect
/// of the system.
SERVICE = 2;
};
/// Monitors update attempts as they start.
///
/// Clients interested in receiving progress information for an update check
/// should implement this protocol and provide the client end to
/// [`Manager.MonitorAllUpdateChecks`].
/// The Manager will close the client end of the AttemptsMonitor if there are
/// more than 2 outstanding requests.
protocol AttemptsMonitor {
/// Called when a new update attempt has started.
///
/// Arguments:
/// * |options| Options for how this request should be performed.
/// * |monitor| A protocol on which to receive progress updates.
OnStart(resource struct {
options AttemptOptions;
monitor server_end:Monitor;
}) -> ();
};
/// Details for an update attempt monitor.
type AttemptOptions = table {
/// Who or what initiated this update attempt. This may influence how the
/// update check is performed.
1: initiator Initiator;
};
/// Monitors a single update check.
///
/// Clients interested in receiving progress information for an update check
/// should implement this protocol and provide the client end to
/// [`Manager.CheckNow`].
protocol Monitor {
/// Receives a status update for this update check.
///
/// This request will be called for all state changes, skipping none.
/// However, message delivery is throttled by the rate at which the
/// implementation acknowledges the messages.
///
/// The throttled delivery doesn't impact the underlying state of the
/// [`Manager`]. It does not wait for any acknowledgements before it moves
/// on to the next state in its state machine. The [`Manager`] will simply
/// queue up the states for the [`Monitor`] implementation to receive.
///
/// During the installing_update state, the [`Manager`] may, at its
/// discretion, collapse redundant information like the fraction completed,
/// in the event that the [`Monitor`] implementation is not responding to
/// the `OnState()` requests in a timely manner.
///
/// + request `state` The new state of the update check.
/// - response The implementation is ready to receive the next
/// [`State`] from the [`Manager`].
OnState(struct {
state State;
}) -> ();
};
/// The set of states that a [`Monitor`] can receive during an update check.
///
/// An update check ends when it enters a terminal state, denoted below as the
/// states on the right-hand side of the diagram with no arrows leading out of
/// them.
///
/// # State Machine Diagram
///
/// ```
/// +----------------------+ +---------------------------------+
/// | checking_for_updates |---->| error_checking_for_update |
/// +----------------------+ +---------------------------------+
/// |
/// | +---------------------------------+
/// +---------------->| no_update_available |
/// | +---------------------------------+
/// |
/// | +---------------------------------+
/// +---------------->| installation_deferred_by_policy |
/// | +---------------------------------+
/// v
/// +----------------------+ +---------------------------------+
/// | installing_update |---->| installation_error |
/// +----------------------+ +---------------------------------+
/// |
/// | +---------------------------------+
/// +---------------->| waiting_for_reboot |
/// +---------------------------------+
/// ```
type State = strict union {
/// The Manager is currently checking for an update.
///
/// Next states:
/// * `installing_update` update is available and allowed by policy
/// * `error_checking_for_update` on error
/// * `update_deferred_by_policy` update is available but deferred by policy
1: checking_for_updates CheckingForUpdatesData;
/// The Manager encountered an error while checking for the existence of a
/// a new update.
///
/// **This is a terminal state**
///
2: error_checking_for_update ErrorCheckingForUpdateData;
/// There is not update available at this time.
///
/// **This is a terminal state**
///
3: no_update_available NoUpdateAvailableData;
/// The Manager has found an available update but is not acting on it at
/// this time due to policy restrictions.
///
/// **This is a terminal state**
///
4: installation_deferred_by_policy InstallationDeferredData;
/// The Manager is installing the available update.
///
/// Next states:
/// * `waiting_for_reboot` on success
/// * `installation_error` on error
5: installing_update InstallingData;
/// The update has been installed, and the device is waiting to be rebooted.
///
/// Next states:
/// * (none, the device reboots)
///
/// **This is a terminal state**
///
6: waiting_for_reboot InstallingData;
/// The Manager encountered an update in the installation of the update.
///
/// **This is a terminal state**
///
7: installation_error InstallationErrorData;
};
/// This is the set of data associated with `checking_for_updates`.
/// (currently none)
type CheckingForUpdatesData = table {};
/// This is the set of data associated with the `error_checking_for_update`
/// state.
/// (currently none)
type ErrorCheckingForUpdateData = table {};
/// This is the set of data associated with the `no_update_available` state.
/// (currently none)
type NoUpdateAvailableData = table {};
/// This is the set of data associated with the
/// `installation_deferred_by_policy` state.
type InstallationDeferredData = table {
1: update UpdateInfo;
2: deferral_reason InstallationDeferralReason;
};
/// This is the set of data associated with the states involved with installing
/// an update:
/// * `installing_update`
/// * `waiting_for_reboot`
type InstallingData = table {
1: update UpdateInfo;
2: installation_progress InstallationProgress;
};
/// This is the set of data associated with the `installation_error` state.
/// (currently none)
type InstallationErrorData = table {
1: update UpdateInfo;
2: installation_progress InstallationProgress;
};
/// This describes the update that is available to be installed.
type UpdateInfo = table {
/// A string that describes the version that is available. This may be
/// either a semantic version (A.B.C.D) or an opaque hash. Clients MUST
/// not attempt to inspect this value, it is for display purposes only.
1: version_available string:MAX_VERSION_STRING_SIZE;
/// The total number of bytes that may be downloaded to apply this update.
2: download_size uint64;
/// Whether the update was marked as urgent. Default is false.
3: urgent bool;
};
/// This is the maximum length of a version string that will be returned by the
/// protocol
const MAX_VERSION_STRING_SIZE uint32 = 128;
/// This describes the progress installing the update that has been made so far.
type InstallationProgress = table {
/// The fraction [0-1.0f] of the installation that has been completed.
1: fraction_completed float32;
};
/// This is the set of values that are returned by an request to immediately
/// check for an update.
type CheckNotStartedReason = strict enum {
/// There was an internal error in starting the update check. The client
/// is not expected to be able to do something meaningful about this error,
/// except to try again later (after an appropriate delay and back-off in
/// the event of multiple errors.
INTERNAL = 1;
/// If there are required arguments or options (or option values in
/// conflict), provided via the CheckOptions table to CheckNow, this error
/// will be returned.
INVALID_OPTIONS = 2;
/// There was already another update check in progress when this request was
/// made. A new update check will not be started.
ALREADY_IN_PROGRESS = 3;
/// The update check was not started, because too many requests to check for
/// updates have been made by clients in a short period of time.
///
/// **NOTE:** Clients MUST NOT attempt to cause background update checks to
/// happen at a more frequent rate than the fuchsia.update.Manager will do
/// them.
///
/// If a client attempts to abuse this, it will be throttled.
THROTTLED = 4;
};
/// This is the set of values that are provided when an update installation
/// is deferred.
type InstallationDeferralReason = flexible enum {
/// The update was not installed because the currently booted system is not
/// committed. Consumers are encouraged to use the [`CommitStatusProvider`]
/// to determine when to retry the update check such that the update will
/// be installed.
CURRENT_SYSTEM_NOT_COMMITTED = 1;
};