[sl4f] Add Scenic screencap

Wiring through a Scenic screencap request, encoding the screenshot as a base64
string.

It remains to be seen whether this is what we want, but in lieu of any other
formal HTI transfer mechanism (other than, say, SSH), this is something.

Test: fx set x64 --board x64 --packages topaz/packages/buildbot
      fx shell present_view fuchsia-pkg://fuchsia.com/system_dashboard#meta/system_dashboard.cmx
      [ctrl + C]
      fx shell run -d fuchsia-pkg://fuchsia.com/sl4f#meta/sl4f.cmx
      curl -X GET `dev_finder list` -d '{"id": "", "method": "scenic_facade.TakeScreenshot", "params": null}'

Script including PPM conversion: go/paste/6546725749653504

Change-Id: Iab4c80e6f289c84258e09ce0029bef0fbaba1534
diff --git a/garnet/bin/sl4f/BUILD.gn b/garnet/bin/sl4f/BUILD.gn
index f3be7ce..ea3d3f5 100644
--- a/garnet/bin/sl4f/BUILD.gn
+++ b/garnet/bin/sl4f/BUILD.gn
@@ -27,6 +27,9 @@
     "//sdk/fidl/fuchsia.bluetooth:fuchsia.bluetooth-rustc",
     "//sdk/fidl/fuchsia.bluetooth.gatt:fuchsia.bluetooth.gatt-rustc",
     "//sdk/fidl/fuchsia.bluetooth.le:fuchsia.bluetooth.le-rustc",
+    "//sdk/fidl/fuchsia.images:fuchsia.images-rustc",
+    "//sdk/fidl/fuchsia.ui.scenic:fuchsia.ui.scenic-rustc",
+    "//third_party/rust-crates/rustc_deps:base64",
     "//third_party/rust-crates/rustc_deps:failure",
     "//third_party/rust-crates/rustc_deps:futures-preview",
     "//third_party/rust-crates/rustc_deps:parking_lot",
@@ -37,6 +40,7 @@
     "//third_party/rust-crates/rustc_deps:serde_derive",
     "//third_party/rust-crates/rustc_deps:serde_json",
     "//third_party/rust-crates/rustc_deps:slab",
+    "//zircon/public/fidl/fuchsia-mem:fuchsia-mem-rustc",
     "//zircon/public/fidl/fuchsia-net-stack:fuchsia-net-stack-rustc",
   ]
 }
diff --git a/garnet/bin/sl4f/meta/sl4f.cmx b/garnet/bin/sl4f/meta/sl4f.cmx
index 98697ee..efb26ab 100644
--- a/garnet/bin/sl4f/meta/sl4f.cmx
+++ b/garnet/bin/sl4f/meta/sl4f.cmx
@@ -14,6 +14,7 @@
             "fuchsia.net.SocketProvider",
             "fuchsia.net.stack.Stack",
             "fuchsia.tracelink.Registry",
+            "fuchsia.ui.scenic.Scenic",
             "fuchsia.wlan.device.service.DeviceService"
         ]
     }
diff --git a/garnet/bin/sl4f/src/main.rs b/garnet/bin/sl4f/src/main.rs
index 7f63f78..6be4772 100644
--- a/garnet/bin/sl4f/src/main.rs
+++ b/garnet/bin/sl4f/src/main.rs
@@ -17,6 +17,7 @@
 
 mod bluetooth;
 mod netstack;
+mod scenic;
 mod server;
 mod wlan;
 
diff --git a/garnet/bin/sl4f/src/scenic/commands.rs b/garnet/bin/sl4f/src/scenic/commands.rs
new file mode 100644
index 0000000..17f4d8d
--- /dev/null
+++ b/garnet/bin/sl4f/src/scenic/commands.rs
@@ -0,0 +1,20 @@
+// Copyright 2019 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 crate::scenic::{facade::ScenicFacade, types::ScenicMethod};
+use failure::Error;
+use serde_json::Value;
+use std::sync::Arc;
+
+// Takes ACTS method command and executes corresponding Scenic Client
+// FIDL methods.
+pub async fn scenic_method_to_fidl(
+    method_name: String,
+    _args: Value,
+    facade: Arc<ScenicFacade>,
+) -> Result<Value, Error> {
+    match method_name.parse()? {
+        ScenicMethod::TakeScreenshot => await!(facade.take_screenshot()),
+    }
+}
diff --git a/garnet/bin/sl4f/src/scenic/facade.rs b/garnet/bin/sl4f/src/scenic/facade.rs
new file mode 100644
index 0000000..fa205fd
--- /dev/null
+++ b/garnet/bin/sl4f/src/scenic/facade.rs
@@ -0,0 +1,36 @@
+// Copyright 2019 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 crate::scenic::types::ScreenshotDataDef;
+use failure::Error;
+use fidl_fuchsia_ui_scenic::ScenicMarker;
+use fuchsia_app as app;
+use serde_json::{to_value, Value};
+
+/// Perform Scenic operations.
+///
+/// Note this object is shared among all threads created by server.
+///
+/// This facade does not hold onto a Scenic proxy as the server may be
+/// long-running while individual tests set up and tear down Scenic.
+#[derive(Debug)]
+pub struct ScenicFacade {}
+
+impl ScenicFacade {
+    pub fn new() -> ScenicFacade {
+        ScenicFacade {}
+    }
+
+    pub async fn take_screenshot(&self) -> Result<Value, Error> {
+        let scenic =
+            app::client::connect_to_service::<ScenicMarker>().expect("failed to connect to Scenic");
+
+        let (screenshot, success) = await!(scenic.take_screenshot())?;
+        if success {
+            Ok(to_value(ScreenshotDataDef::new(screenshot))?)
+        } else {
+            bail!("TakeScreenshot failed")
+        }
+    }
+}
diff --git a/garnet/bin/sl4f/src/scenic/mod.rs b/garnet/bin/sl4f/src/scenic/mod.rs
new file mode 100644
index 0000000..28121b1
--- /dev/null
+++ b/garnet/bin/sl4f/src/scenic/mod.rs
@@ -0,0 +1,7 @@
+// Copyright 2019 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.
+
+pub mod commands;
+pub mod facade;
+pub mod types;
diff --git a/garnet/bin/sl4f/src/scenic/types.rs b/garnet/bin/sl4f/src/scenic/types.rs
new file mode 100644
index 0000000..fcba4b2
--- /dev/null
+++ b/garnet/bin/sl4f/src/scenic/types.rs
@@ -0,0 +1,107 @@
+// Copyright 2019 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 base64;
+use fidl_fuchsia_images::{AlphaFormat, ColorSpace, ImageInfo, PixelFormat, Tiling, Transform};
+use fidl_fuchsia_mem::Buffer;
+use fidl_fuchsia_ui_scenic::ScreenshotData;
+use serde::Serializer;
+use serde_derive::{Deserialize, Serialize};
+
+/// Enum for supported FIDL commands.
+pub enum ScenicMethod {
+    TakeScreenshot,
+}
+
+impl std::str::FromStr for ScenicMethod {
+    type Err = failure::Error;
+
+    fn from_str(method: &str) -> Result<Self, Self::Err> {
+        match method {
+            "TakeScreenshot" => Ok(ScenicMethod::TakeScreenshot),
+            _ => bail!("invalid Scenic FIDL method: {}", method),
+        }
+    }
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "Transform")]
+pub enum TransformDef {
+    Normal = 0,
+    FlipHorizontal = 1,
+    FlipVertical = 2,
+    FlipVerticalAndHorizontal = 3,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "PixelFormat")]
+pub enum PixelFormatDef {
+    Bgra8 = 0,
+    Yuy2 = 1,
+    Nv12 = 2,
+    Yv12 = 3,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "ColorSpace")]
+pub enum ColorSpaceDef {
+    Srgb = 0,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "Tiling")]
+pub enum TilingDef {
+    Linear = 0,
+    GpuOptimal = 1,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "AlphaFormat")]
+pub enum AlphaFormatDef {
+    Opaque = 0,
+    Premultiplied = 1,
+    NonPremultiplied = 2,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+#[serde(remote = "ImageInfo")]
+pub struct ImageInfoDef {
+    #[serde(with = "TransformDef")]
+    pub transform: Transform,
+    pub width: u32,
+    pub height: u32,
+    pub stride: u32,
+    #[serde(with = "PixelFormatDef")]
+    pub pixel_format: PixelFormat,
+    #[serde(with = "ColorSpaceDef")]
+    pub color_space: ColorSpace,
+    #[serde(with = "TilingDef")]
+    pub tiling: Tiling,
+    #[serde(with = "AlphaFormatDef")]
+    pub alpha_format: AlphaFormat,
+}
+
+fn serialize_buffer<S>(buffer: &Buffer, serializer: S) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+{
+    let mut data = vec![0; buffer.size as usize];
+    use serde::ser::Error;
+    buffer.vmo.read(&mut data, 0).map_err(Error::custom)?;
+    serializer.serialize_str(&base64::encode(&data))
+}
+
+#[derive(Serialize, Debug)]
+pub struct ScreenshotDataDef {
+    #[serde(with = "ImageInfoDef")]
+    pub info: ImageInfo,
+    #[serde(serialize_with = "serialize_buffer")]
+    pub data: Buffer,
+}
+
+impl ScreenshotDataDef {
+    pub fn new(screenshot_data: ScreenshotData) -> ScreenshotDataDef {
+        ScreenshotDataDef { info: screenshot_data.info, data: screenshot_data.data }
+    }
+}
diff --git a/garnet/bin/sl4f/src/server/sl4f.rs b/garnet/bin/sl4f/src/server/sl4f.rs
index 1a55b6d..dbc505c 100644
--- a/garnet/bin/sl4f/src/server/sl4f.rs
+++ b/garnet/bin/sl4f/src/server/sl4f.rs
@@ -31,6 +31,9 @@
 // Netstack related includes
 use crate::netstack::facade::NetstackFacade;
 
+// Scenic related includes
+use crate::scenic::facade::ScenicFacade;
+
 // Wlan related includes
 use crate::wlan::facade::WlanFacade;
 
@@ -109,6 +112,9 @@
     // netstack_facade: Thread safe object for state for netstack functions.
     netstack_facade: Arc<NetstackFacade>,
 
+    // scenic_facade: thread safe object for state for Scenic functions.
+    scenic_facade: Arc<ScenicFacade>,
+
     // wlan_facade: Thread safe object for state for wlan connectivity tests
     wlan_facade: Arc<WlanFacade>,
 
@@ -124,6 +130,7 @@
         let gatt_client_facade = Arc::new(GattClientFacade::new());
         let gatt_server_facade = Arc::new(GattServerFacade::new());
         let netstack_facade = Arc::new(NetstackFacade::new());
+        let scenic_facade = Arc::new(ScenicFacade::new());
         let wlan_facade = Arc::new(WlanFacade::new()?);
         Ok(Arc::new(RwLock::new(Sl4f {
             ble_advertise_facade,
@@ -131,6 +138,7 @@
             gatt_client_facade,
             gatt_server_facade,
             netstack_facade,
+            scenic_facade,
             wlan_facade,
             clients: Arc::new(Mutex::new(HashMap::new())),
         })))
@@ -156,6 +164,10 @@
         self.bt_facade.clone()
     }
 
+    pub fn get_scenic_facade(&self) -> Arc<ScenicFacade> {
+        self.scenic_facade.clone()
+    }
+
     pub fn get_wlan_facade(&self) -> Arc<WlanFacade> {
         self.wlan_facade.clone()
     }
@@ -191,43 +203,47 @@
 
 // Handles all incoming requests to SL4F server, routes accordingly
 pub fn serve(
-    request: &Request, sl4f_session: Arc<RwLock<Sl4f>>,
+    request: &Request,
+    sl4f_session: Arc<RwLock<Sl4f>>,
     rouille_sender: mpsc::UnboundedSender<AsyncRequest>,
 ) -> Response {
     router!(request,
-            (GET) (/) => {
-                // Parse the command request
-                fx_log_info!(tag: "serve", "Received command request.");
-                client_request(sl4f_session.clone(), &request, rouille_sender.clone())
-            },
-            (GET) (/init) => {
-                // Initialize a client
-                fx_log_info!(tag: "serve", "Received init request.");
-                client_init(&request, sl4f_session.write().get_clients().clone())
-            },
-            (GET) (/print_clients) => {
-                // Print information about all clients
-                fx_log_info!(tag: "serve", "Received print client request.");
-                const PRINT_ACK: &str = "Successfully printed clients.";
-                sl4f_session.read().print_clients();
-                rouille::Response::json(&PRINT_ACK)
-            },
-            (GET) (/cleanup) => {
-                fx_log_info!(tag: "serve", "Received server cleanup request.");
-                server_cleanup(&request, sl4f_session.clone())
-            },
-            _ => {
-                fx_log_err!(tag: "serve", "Received unknown server request.");
-                const FAIL_REQUEST_ACK: &str = "Unknown GET request.";
-                let res = CommandResponse::new("".to_string(), None, serde::export::Some(FAIL_REQUEST_ACK.to_string()));
-                rouille::Response::json(&res)
-            }
-        )
+        (GET) (/) => {
+            // Parse the command request
+            fx_log_info!(tag: "serve", "Received command request.");
+            client_request(sl4f_session.clone(), &request, rouille_sender.clone())
+        },
+        (GET) (/init) => {
+            // Initialize a client
+            fx_log_info!(tag: "serve", "Received init request.");
+            client_init(&request, sl4f_session.write().get_clients().clone())
+        },
+        (GET) (/print_clients) => {
+            // Print information about all clients
+            fx_log_info!(tag: "serve", "Received print client request.");
+            const PRINT_ACK: &str = "Successfully printed clients.";
+            sl4f_session.read().print_clients();
+            rouille::Response::json(&PRINT_ACK)
+        },
+        (GET) (/cleanup) => {
+            fx_log_info!(tag: "serve", "Received server cleanup request.");
+            server_cleanup(&request, sl4f_session.clone())
+        },
+        _ => {
+            fx_log_err!(tag: "serve", "Received unknown server request.");
+            const FAIL_REQUEST_ACK: &str = "Unknown GET request.";
+            let res = CommandResponse::new("".to_string(), None, serde::export::Some(FAIL_REQUEST_ACK.to_string()));
+            rouille::Response::json(&res)
+        }
+    )
 }
 
 // Given the session id, method id, and result of FIDL call, store the result for this client
 fn store_response(
-    sl4f_session: Arc<RwLock<Sl4f>>, client_id: String, method_id: String, result: AsyncResponse,
+    sl4f_session: Arc<RwLock<Sl4f>>,
+    client_id: String,
+    method_id: String,
+    result: AsyncResponse,
 ) {
     let clients = sl4f_session.write().clients.clone();
 
@@ -235,11 +251,7 @@
     // history
     if clients.lock().contains_key(&client_id) {
         let command_response = ClientData::new(method_id.clone(), result.clone());
-        clients
-            .lock()
-            .entry(client_id.clone())
-            .or_insert(Vec::new())
-            .push(command_response);
+        clients.lock().entry(client_id.clone()).or_insert(Vec::new()).push(command_response);
     } else {
         fx_log_err!(tag: "store_response", "Client doesn't exist in server database: {:?}", client_id);
     }
@@ -250,7 +262,8 @@
 // Given the request, map the test request to a FIDL query and execute
 // asynchronously
 fn client_request(
-    sl4f_session: Arc<RwLock<Sl4f>>, request: &Request,
+    sl4f_session: Arc<RwLock<Sl4f>>,
+    request: &Request,
     rouille_sender: mpsc::UnboundedSender<AsyncRequest>,
 ) -> Response {
     const FAIL_TEST_ACK: &str = "Command failed";
@@ -267,24 +280,12 @@
     // Create channel for async thread to respond to
     // Package response and ship over JSON RPC
     let (async_sender, rouille_receiver) = std::sync::mpsc::channel();
-    let req = AsyncRequest::new(
-        async_sender,
-        method_id.clone(),
-        method_type,
-        method_name,
-        method_params,
-    );
-    rouille_sender
-        .unbounded_send(req)
-        .expect("Failed to send request to async thread.");
+    let req =
+        AsyncRequest::new(async_sender, method_id.clone(), method_type, method_name, method_params);
+    rouille_sender.unbounded_send(req).expect("Failed to send request to async thread.");
     let resp: AsyncResponse = rouille_receiver.recv().unwrap();
 
-    store_response(
-        sl4f_session,
-        session_id.clone(),
-        method_id.clone(),
-        resp.clone(),
-    );
+    store_response(sl4f_session, session_id.clone(), method_id.clone(), resp.clone());
     fx_log_info!(tag: "client_request", "Received async thread response: {:?}", resp);
 
     // If the response has a return value, package into response, otherwise use error code
@@ -303,7 +304,8 @@
 // Initializes a new client, adds to clients, a thread-safe HashMap
 // Returns a rouille::Response
 fn client_init(
-    request: &Request, clients: Arc<Mutex<HashMap<String, Vec<ClientData>>>>,
+    request: &Request,
+    clients: Arc<Mutex<HashMap<String, Vec<ClientData>>>>,
 ) -> Response {
     const INIT_ACK: &str = "Recieved init request.";
     const FAIL_INIT_ACK: &str = "Failed to init client.";
@@ -382,13 +384,7 @@
     // actual method name itself
     let (method_type, method_name) = split_string(method_name_raw.clone());
     let (session_id, method_id) = split_string(method_id_raw.clone());
-    Ok((
-        session_id,
-        method_id,
-        method_type,
-        method_name,
-        method_params,
-    ))
+    Ok((session_id, method_id, method_type, method_name, method_params))
 }
 
 fn server_cleanup(request: &Request, sl4f_session: Arc<RwLock<Sl4f>>) -> Response {
@@ -423,10 +419,7 @@
     fn split_string_test() {
         // Standard command
         let mut method_name = "bt.send".to_string();
-        assert_eq!(
-            ("bt".to_string(), "send".to_string()),
-            split_string(method_name)
-        );
+        assert_eq!(("bt".to_string(), "send".to_string()), split_string(method_name));
 
         // Invalid command (should result in empty result)
         method_name = "bluetooth_send".to_string();
diff --git a/garnet/bin/sl4f/src/server/sl4f_executor.rs b/garnet/bin/sl4f/src/server/sl4f_executor.rs
index 854cbe8..d998ddf 100644
--- a/garnet/bin/sl4f/src/server/sl4f_executor.rs
+++ b/garnet/bin/sl4f/src/server/sl4f_executor.rs
@@ -21,10 +21,12 @@
 use crate::bluetooth::commands::gatt_client_method_to_fidl;
 use crate::bluetooth::commands::gatt_server_method_to_fidl;
 use crate::netstack::commands::netstack_method_to_fidl;
+use crate::scenic::commands::scenic_method_to_fidl;
 use crate::wlan::commands::wlan_method_to_fidl;
 
 pub async fn run_fidl_loop(
-    sl4f_session: Arc<RwLock<Sl4f>>, receiver: mpsc::UnboundedReceiver<AsyncRequest>,
+    sl4f_session: Arc<RwLock<Sl4f>>,
+    receiver: mpsc::UnboundedReceiver<AsyncRequest>,
 ) {
     const CONCURRENT_REQ_LIMIT: usize = 10; // TODO(CONN-6) figure out a good parallel value for this
 
@@ -38,7 +40,10 @@
     await!(receiver_fut);
 }
 
-async fn handle_request(sl4f_session: Arc<RwLock<Sl4f>>, request: AsyncRequest) -> Result<(), Error> {
+async fn handle_request(
+    sl4f_session: Arc<RwLock<Sl4f>>,
+    request: AsyncRequest,
+) -> Result<(), Error> {
     match request {
         AsyncRequest { tx, id, method_type, name, params } => {
             let curr_sl4f_session = sl4f_session.clone();
@@ -52,7 +57,7 @@
                     // Ignore any tx sending errors since there is not a recovery path.  The
                     // connection to the test server may be broken.
                     let _ = tx.send(async_response);
-                },
+                }
                 Err(e) => {
                     println!("Error returned from calling method_to_fidl {}", e);
                     let async_response = AsyncResponse::new(Err(e));
@@ -68,23 +73,24 @@
 }
 
 async fn method_to_fidl(
-    method_type: String, method_name: String, args: Value, sl4f_session: Arc<RwLock<Sl4f>>,
+    method_type: String,
+    method_name: String,
+    args: Value,
+    sl4f_session: Arc<RwLock<Sl4f>>,
 ) -> Result<Value, Error> {
     match FacadeType::from_str(&method_type) {
         FacadeType::BleAdvertiseFacade => await!(ble_advertise_method_to_fidl(
-                method_name,
-                args,
-                sl4f_session.read().get_ble_advertise_facade(),
-        )),
-        FacadeType::Bluetooth => await!(ble_method_to_fidl(
             method_name,
             args,
-            sl4f_session.read().get_bt_facade(),
+            sl4f_session.read().get_ble_advertise_facade(),
         )),
+        FacadeType::Bluetooth => {
+            await!(ble_method_to_fidl(method_name, args, sl4f_session.read().get_bt_facade(),))
+        }
         FacadeType::GattClientFacade => await!(gatt_client_method_to_fidl(
-                method_name,
-                args,
-                sl4f_session.read().get_gatt_client_facade(),
+            method_name,
+            args,
+            sl4f_session.read().get_gatt_client_facade(),
         )),
         FacadeType::GattServerFacade => await!(gatt_server_method_to_fidl(
             method_name,
@@ -96,11 +102,14 @@
             args,
             sl4f_session.read().get_netstack_facade(),
         )),
-        FacadeType::Wlan => await!(wlan_method_to_fidl(
+        FacadeType::ScenicFacade => await!(scenic_method_to_fidl(
             method_name,
             args,
-            sl4f_session.read().get_wlan_facade()
+            sl4f_session.read().get_scenic_facade(),
         )),
+        FacadeType::Wlan => {
+            await!(wlan_method_to_fidl(method_name, args, sl4f_session.read().get_wlan_facade()))
+        }
         _ => Err(BTError::new("Invalid FIDL method type").into()),
     }
-}
\ No newline at end of file
+}
diff --git a/garnet/bin/sl4f/src/server/sl4f_types.rs b/garnet/bin/sl4f/src/server/sl4f_types.rs
index e7a3d53..1061ed7 100644
--- a/garnet/bin/sl4f/src/server/sl4f_types.rs
+++ b/garnet/bin/sl4f/src/server/sl4f_types.rs
@@ -19,10 +19,7 @@
 
 impl ClientData {
     pub fn new(id: String, result: AsyncResponse) -> ClientData {
-        ClientData {
-            command_id: id,
-            command_result: result,
-        }
+        ClientData { command_id: id, command_result: result }
     }
 }
 
@@ -79,16 +76,13 @@
 
 impl AsyncRequest {
     pub fn new(
-        tx: mpsc::Sender<AsyncResponse>, id: String, method_type: String, name: String,
+        tx: mpsc::Sender<AsyncResponse>,
+        id: String,
+        method_type: String,
+        name: String,
         params: Value,
     ) -> AsyncRequest {
-        AsyncRequest {
-            tx,
-            id,
-            method_type,
-            name,
-            params,
-        }
+        AsyncRequest { tx, id, method_type, name, params }
     }
 }
 
@@ -104,14 +98,8 @@
 impl AsyncResponse {
     pub fn new(res: Result<Value, Error>) -> AsyncResponse {
         match res {
-            Ok(v) => AsyncResponse {
-                result: Some(v),
-                error: None,
-            },
-            Err(e) => AsyncResponse {
-                result: None,
-                error: Some(e.to_string()),
-            },
+            Ok(v) => AsyncResponse { result: Some(v), error: None },
+            Err(e) => AsyncResponse { result: None, error: Some(e.to_string()) },
         }
     }
 }
@@ -124,6 +112,7 @@
     GattClientFacade,
     GattServerFacade,
     NetstackFacade,
+    ScenicFacade,
     Wlan,
     Undefined,
 }
@@ -136,6 +125,7 @@
             "gatt_client_facade" => FacadeType::GattClientFacade,
             "gatt_server_facade" => FacadeType::GattServerFacade,
             "netstack_facade" => FacadeType::NetstackFacade,
+            "scenic_facade" => FacadeType::ScenicFacade,
             "wlan" => FacadeType::Wlan,
             _ => FacadeType::Undefined,
         }