|  | // 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(CheckOptions options, Monitor? monitor) | 
|  | -> () 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() -> (bool rebooting); | 
|  | }; | 
|  |  | 
|  | /// Configuration options for an update check. | 
|  | table CheckOptions { | 
|  | /// 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: bool allow_attaching_to_existing_update_check; | 
|  | }; | 
|  |  | 
|  | /// Who or what initiated the update check. | 
|  | enum Initiator { | 
|  | /// 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 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(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        | | 
|  | ///                                  +---------------------------------+ | 
|  | /// ``` | 
|  | union State { | 
|  |  | 
|  | /// 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: CheckingForUpdatesData checking_for_updates; | 
|  |  | 
|  | /// The Manager encountered an error while checking for the existence of a | 
|  | /// a new update. | 
|  | /// | 
|  | /// **This is a terminal state** | 
|  | /// | 
|  | 2: ErrorCheckingForUpdateData error_checking_for_update; | 
|  |  | 
|  | /// There is not update available at this time. | 
|  | /// | 
|  | /// **This is a terminal state** | 
|  | /// | 
|  | 3: NoUpdateAvailableData no_update_available; | 
|  |  | 
|  | /// 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: InstallationDeferredData installation_deferred_by_policy; | 
|  |  | 
|  | /// The Manager is installing the available update. | 
|  | /// | 
|  | /// Next states: | 
|  | /// * `waiting_for_reboot` on success | 
|  | /// * `installation_error` on error | 
|  | 5: InstallingData installing_update; | 
|  |  | 
|  | /// 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: InstallingData waiting_for_reboot; | 
|  |  | 
|  | /// The Manager encountered an update in the installation of the update. | 
|  | /// | 
|  | /// **This is a terminal state** | 
|  | /// | 
|  | 7: InstallationErrorData installation_error; | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with `checking_for_updates`. | 
|  | /// (currently none) | 
|  | table CheckingForUpdatesData { | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with the `error_checking_for_update` | 
|  | /// state. | 
|  | /// (currently none) | 
|  | table ErrorCheckingForUpdateData { | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with the `no_update_available` state. | 
|  | /// (currently none) | 
|  | table NoUpdateAvailableData { | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with the | 
|  | /// `installation_deferred_by_policy` state. | 
|  | table InstallationDeferredData { | 
|  | 1: UpdateInfo update; | 
|  | 2: InstallationDeferralReason deferral_reason; | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with the states involved with installing | 
|  | /// an update: | 
|  | /// * `installing_update` | 
|  | /// * `waiting_for_reboot` | 
|  | table InstallingData { | 
|  | 1: UpdateInfo update; | 
|  | 2: InstallationProgress installation_progress; | 
|  | }; | 
|  |  | 
|  | /// This is the set of data associated with the `installation_error` state. | 
|  | /// (currently none) | 
|  | table InstallationErrorData { | 
|  | 1: UpdateInfo update; | 
|  | 2: InstallationProgress installation_progress; | 
|  | }; | 
|  |  | 
|  | /// This describes the update that is available to be installed. | 
|  | table UpdateInfo { | 
|  | /// 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: string:MAX_VERSION_STRING_SIZE version_available; | 
|  |  | 
|  | /// The total number of bytes that may be downloaded to apply this update. | 
|  | 2: uint64 download_size; | 
|  | }; | 
|  |  | 
|  | /// This is the maximum length of a version string that will be returned by the | 
|  | /// protocol | 
|  | const uint32 MAX_VERSION_STRING_SIZE = 128; | 
|  |  | 
|  | /// This describes the progress installing the update that has been made so far. | 
|  | table InstallationProgress { | 
|  | /// The fraction [0-1.0f] of the installation that has been completed. | 
|  | 1: float32 fraction_completed; | 
|  | }; | 
|  |  | 
|  | /// This is the set of values that are returned by an request to immediately | 
|  | /// check for an update. | 
|  | enum CheckNotStartedReason { | 
|  |  | 
|  | /// 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. | 
|  | flexible enum InstallationDeferralReason { | 
|  |  | 
|  | /// 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; | 
|  | }; |