display_utils/error.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
// Copyright 2022 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.
use fidl_fuchsia_hardware_display::ClientCompositionOp;
use fidl_fuchsia_hardware_display_types::{ClientCompositionOpcode, ConfigResult};
use futures::channel::mpsc;
use thiserror::Error;
use crate::controller::VsyncEvent;
use crate::types::{DisplayId, LayerId};
/// Library error type.
#[derive(Error, Debug)]
pub enum Error {
/// Error encountered while connecting to a display-coordinator device via devfs.
#[error("could not find a display-coordinator device")]
DeviceNotFound,
/// No displays were reported by the display driver when expected.
#[error("device did not enumerate initial displays")]
NoDisplays,
/// A request handling task (such as one that owns a FIDL event stream that can only be
/// started once) was already been initiated before.
#[error("a singleton task was already initiated")]
AlreadyRequested,
/// Error while allocating shared sysmem buffers.
#[error("sysmem buffer collection allocation failed, or invalid response from sysmem")]
BuffersNotAllocated,
/// Error while establishing a connection to sysmem.
#[error("error while setting up a sysmem connection")]
SysmemConnection,
/// Ran out of free client-assigned identifiers.
#[error("ran out of identifiers")]
IdsExhausted,
/// Path to the device is invalid (e.g. containing invalid
/// characters).
#[error("invalid device path")]
DevicePathInvalid,
/// Wrapper for errors from FIDL bindings.
#[error("FIDL error: {0}")]
FidlError(#[from] fidl::Error),
/// Wrapper for system file I/O errors.
#[error("OS I/O error: {0}")]
IoError(#[from] std::io::Error),
/// Wrapper for errors from zircon syscalls.
#[error("zircon error: {0}")]
ZxError(#[from] zx::Status),
/// Wrapper for errors from FIDL device connections.
#[error("Device connection error: {0}")]
DeviceConnectionError(anyhow::Error),
/// Wrapper for errors from fuchsia-fs.
#[error("filesystem error: {0}")]
FsError(#[from] fuchsia_fs::node::OpenError),
/// Wrapper for errors from fuchsia-fs watcher creation.
#[error("failed to create directory watcher: {0}")]
WatcherCreateError(#[from] fuchsia_fs::directory::WatcherCreateError),
/// Wrapper for errors from the fuchsia-fs watcher stream.
#[error("directory watcher stream produced error: {0}")]
WatcherStreamError(#[from] fuchsia_fs::directory::WatcherStreamError),
/// Error that occurred while notifying vsync event listeners over an in-process async channel.
#[error("failed to notify vsync: {0}")]
CouldNotSendVsyncEvent(#[from] mpsc::TrySendError<VsyncEvent>),
/// UTF-8 validation error.
#[error("invalid UTF-8 string")]
InvalidUtf8(#[from] std::str::Utf8Error),
}
/// Library Result type alias.
pub type Result<T> = std::result::Result<T, Error>;
/// An error generated by `fuchsia.hardware.display.Controller.CheckConfig`.
#[derive(Debug, Error)]
pub enum ConfigError {
/// Failure due to an invalid configuration.
#[error("invalid configuration - error_code: {error_code:#?}, actions: {actions:#?}")]
Invalid {
/// The reason for the failure.
error_code: ConfigResult,
/// Suggested actions that the client can take to resolve the failure.
actions: Vec<ClientCompositionAction>,
},
/// Failure due to a FIDL transport error.
#[error("FIDL channel error")]
Fidl(#[from] fidl::Error),
}
/// Represents a suggested client composition action generated by the driver.
#[derive(Debug, Clone)]
pub struct ClientCompositionAction {
/// The ID of the display that concerns the action.
pub display_id: DisplayId,
/// The ID of the layer that the action should be taken on.
pub layer_id: LayerId,
/// Description of the action.
pub opcode: ClientCompositionOpcode,
}
impl ConfigError {
/// Create an `Invalid` configuration error variant from FIDL output.
pub fn invalid(error_code: ConfigResult, actions: Vec<ClientCompositionOp>) -> ConfigError {
ConfigError::Invalid {
error_code,
actions: actions.into_iter().map(ClientCompositionAction::from).collect(),
}
}
}
impl From<ClientCompositionOp> for ClientCompositionAction {
fn from(src: ClientCompositionOp) -> Self {
Self {
display_id: src.display_id.into(),
layer_id: src.layer_id.into(),
opcode: src.opcode,
}
}
}