1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45//! Interface and impls to read/write the persistent storage for an [`OptOutPreference`].
67use async_trait::async_trait;
8use thiserror::Error;
910#[cfg(test)]
11pub mod testing;
1213mod vx_ta;
1415/// A user's preference for which updates to automatically fetch and apply.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum OptOutPreference {
18/// Allow all published updates to be automatically fetched and applied.
19AllowAllUpdates = 0,
2021/// Allow only critical security updates to be automatically fetched and applied.
22AllowOnlySecurityUpdates,
23}
2425/// An error encountered while accessing the underlying storage for the opt-out setting.
26#[derive(Debug, Error)]
27#[allow(missing_docs)]
28pub enum BridgeError {
29#[error("TEE Internal Error")]
30Internal(#[from] vx_ta::TeeError),
31#[error("TEE Busy")]
32Busy,
33}
3435/// Interface to read/write the persistent storage for an [`OptOutPreference`].
36#[async_trait(?Send)]
37pub trait Bridge {
38/// Reads the current persisted opt-out preference.
39 ///
40 /// Defaults to [`OptOutPreference::AllowAllUpdates`] if no preference is set.
41async fn get_opt_out(&self) -> Result<OptOutPreference, BridgeError>;
4243/// Sets the persisted opt-out preference to `value`, or returns the error encountered while
44 /// attempting to do so.
45async fn set_opt_out(&mut self, value: OptOutPreference) -> Result<(), BridgeError>;
46}
4748/// Implementation of [`Bridge`] that interacts with secure storage on a device.
49#[derive(Debug)]
50pub struct OptOutStorage;
5152#[async_trait(?Send)]
53impl Bridge for OptOutStorage {
54async fn get_opt_out(&self) -> Result<OptOutPreference, BridgeError> {
55let default_value = OptOutPreference::AllowAllUpdates;
56let value = match vx_ta::ota_config_get(default_value as u32).map_err(map_tee_error)? {
570 => OptOutPreference::AllowAllUpdates,
58_ => OptOutPreference::AllowOnlySecurityUpdates,
59 };
60Ok(value)
61 }
6263async fn set_opt_out(&mut self, value: OptOutPreference) -> Result<(), BridgeError> {
64 vx_ta::ota_config_set(value as u32).map_err(map_tee_error)?;
65Ok(())
66 }
67}
6869fn map_tee_error(err: vx_ta::TeeError) -> BridgeError {
70match err {
71 vx_ta::TeeError::Busy => BridgeError::Busy,
72 vx_ta::TeeError::General(_) => BridgeError::Internal(err),
73 }
74}