[driver framework][power] Add support for mapping system states to device states

Change-Id: I3adc3c656b2f18bdaf0fb303d0b93793b23a2a0d
diff --git a/zircon/system/core/devmgr/devhost/api.cc b/zircon/system/core/devmgr/devhost/api.cc
index 4606ada..4026961 100644
--- a/zircon/system/core/devmgr/devhost/api.cc
+++ b/zircon/system/core/devmgr/devhost/api.cc
@@ -92,6 +92,19 @@
       return r;
     }
 
+    //Set Default system power state mapping. This can be later
+    //be updated by the system power manager.
+    std::array<fuchsia_device_SystemPowerStateInfo,
+        fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> states_mapping{};
+    for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+      states_mapping[i].dev_state = fuchsia_device_DevicePowerState_DEVICE_POWER_STATE_D3COLD;
+      states_mapping[i].wakeup_enable = false;
+    }                                                                                                      
+    r = dev->SetSystemPowerStateMapping(states_mapping);
+    if (r != ZX_OK) {
+      return r;
+    }
+
     // out must be set before calling devhost_device_add().
     // devhost_device_add() may result in child devices being created before it returns,
     // and those children may call ops on the device before device_add() returns.
diff --git a/zircon/system/core/devmgr/devhost/rpc-server.cc b/zircon/system/core/devmgr/devhost/rpc-server.cc
index c19313e..f9eecb1 100644
--- a/zircon/system/core/devmgr/devhost/rpc-server.cc
+++ b/zircon/system/core/devmgr/devhost/rpc-server.cc
@@ -25,6 +25,8 @@
 #include <zircon/syscalls.h>
 #include <zircon/types.h>
 
+#include <array>
+#include <iterator>
 #include <new>
 #include <utility>
 
@@ -36,7 +38,6 @@
 
 #include "devhost.h"
 #include "zx-device.h"
-#include <array>
 
 namespace devmgr {
 
@@ -631,6 +632,39 @@
   return fuchsia_device_ControllerResume_reply(txn, &result);
 }
 
+static zx_status_t fidl_DeviceControllerUpdatePowerStateMapping(void* ctx,
+                    const fuchsia_device_SystemPowerStateInfo mapping[6], fidl_txn_t* txn) {
+  auto conn = static_cast<DevfsConnection*>(ctx);
+  fuchsia_device_Controller_UpdatePowerStateMapping_Result result{};
+  std::array<fuchsia_device_SystemPowerStateInfo,
+      fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> states_mapping;
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    states_mapping[i] = mapping[i];
+  }
+  zx_status_t status = conn->dev->SetSystemPowerStateMapping(states_mapping);
+  if (status == ZX_OK) {
+    result.tag = fuchsia_device_Controller_UpdatePowerStateMapping_ResultTag_response;
+  } else {
+    result.tag = fuchsia_device_Controller_UpdatePowerStateMapping_ResultTag_err;
+    result.err = status;
+  }
+  return fuchsia_device_ControllerUpdatePowerStateMapping_reply(txn, &result);
+}
+
+static zx_status_t fidl_DeviceControllerGetPowerStateMapping(void* ctx, fidl_txn_t* txn) {
+  auto conn = static_cast<DevfsConnection*>(ctx);
+  fuchsia_device_Controller_GetPowerStateMapping_Result result{};
+
+  auto& mapping = conn->dev->GetSystemPowerStateMapping();
+  ZX_DEBUG_ASSERT(mapping.size() == fuchsia_device_manager_MAX_SYSTEM_POWER_STATES); 
+
+  result.tag = fuchsia_device_Controller_GetPowerStateMapping_ResultTag_response;
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    result.response.mapping[i] = mapping[i];
+  }
+  return fuchsia_device_ControllerGetPowerStateMapping_reply(txn, &result);
+}
+
 static zx_status_t fidl_DeviceControllerGetEventHandle(void* ctx, fidl_txn_t* txn) {
   auto conn = static_cast<DevfsConnection*>(ctx);
   zx::eventpair event;
@@ -688,6 +722,8 @@
     .DebugResume = fidl_DeviceControllerDebugResume,
     .RunCompatibilityTests = fidl_DeviceControllerRunCompatibilityTests,
     .GetDevicePowerCaps = fidl_DeviceControllerGetDevicePowerCaps,
+    .UpdatePowerStateMapping = fidl_DeviceControllerUpdatePowerStateMapping,
+    .GetPowerStateMapping = fidl_DeviceControllerGetPowerStateMapping,
     .Suspend = fidl_DeviceControllerSuspend,
     .Resume = fidl_DeviceControllerResume,
 };
diff --git a/zircon/system/core/devmgr/devhost/zx-device.cc b/zircon/system/core/devmgr/devhost/zx-device.cc
index 23b4ebf..796b393 100644
--- a/zircon/system/core/devmgr/devhost/zx-device.cc
+++ b/zircon/system/core/devmgr/devhost/zx-device.cc
@@ -53,6 +53,11 @@
   return power_states_;
 }
 
+const std::array<fuchsia_device_SystemPowerStateInfo,
+    fuchsia_device_manager_MAX_SYSTEM_POWER_STATES>& zx_device::GetSystemPowerStateMapping() const {
+  return system_power_states_mapping_;
+}
+
 zx_status_t zx_device::SetPowerStates(const device_power_state_info_t* power_states,
                                uint8_t count) {
   if (count < fuchsia_device_MIN_DEVICE_POWER_STATES ||
@@ -83,6 +88,23 @@
   return ZX_OK;
 }
 
+zx_status_t zx_device::SetSystemPowerStateMapping(std::array<fuchsia_device_SystemPowerStateInfo,
+             fuchsia_device_manager_MAX_SYSTEM_POWER_STATES>& mapping) {
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    fuchsia_device_SystemPowerStateInfo* info = &mapping[i];
+    if (!(power_states_[info->dev_state].is_supported)) {
+      return ZX_ERR_INVALID_ARGS;
+    }
+    if (info->wakeup_enable && !power_states_[info->dev_state].wakeup_capable) {
+      return ZX_ERR_INVALID_ARGS;
+    }
+    //TODO(ravoorir): Check whether the system can wake up from that state,
+    //When power states make more sense. Currently we cannot compare the sleep
+    //states in system power states.
+    system_power_states_mapping_[i] = mapping[i];
+  }
+  return ZX_OK;
+}
 
 // We must disable thread-safety analysis due to not being able to statically
 // guarantee the lock holding invariant.  Instead, we acquire the lock if
diff --git a/zircon/system/core/devmgr/devhost/zx-device.h b/zircon/system/core/devmgr/devhost/zx-device.h
index 179cb33..26c7e59 100644
--- a/zircon/system/core/devmgr/devhost/zx-device.h
+++ b/zircon/system/core/devmgr/devhost/zx-device.h
@@ -20,6 +20,7 @@
 #include <lib/zx/eventpair.h>
 #include <zircon/compiler.h>
 #include <lib/zircon-internal/thread_annotations.h>
+#include <fuchsia/device/manager/c/fidl.h>
 
 #include <atomic>
 #include <array>
@@ -169,6 +170,11 @@
              fuchsia_device_MAX_DEVICE_POWER_STATES>& GetPowerStates() const;
   zx_status_t SetPowerStates(const device_power_state_info_t* power_states,
                              uint8_t count);
+  zx_status_t SetSystemPowerStateMapping(std::array<fuchsia_device_SystemPowerStateInfo,
+             fuchsia_device_manager_MAX_SYSTEM_POWER_STATES>& mapping);
+  const std::array<fuchsia_device_SystemPowerStateInfo,
+             fuchsia_device_manager_MAX_SYSTEM_POWER_STATES>& GetSystemPowerStateMapping() const;
+  fuchsia_device_DevicePowerState GetCurrentDevicePowerState() { return current_power_state_; }
  private:
   zx_device() = default;
 
@@ -210,6 +216,9 @@
 
   std::array<fuchsia_device_DevicePowerStateInfo, fuchsia_device_MAX_DEVICE_POWER_STATES>
                                                                         power_states_;
+  std::array<fuchsia_device_SystemPowerStateInfo,
+      fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> system_power_states_mapping_;
+  fuchsia_device_DevicePowerState current_power_state_;
 };
 
 // zx_device_t objects must be created or initialized by the driver manager's
diff --git a/zircon/system/dev/test/ddk-power/test.cc b/zircon/system/dev/test/ddk-power/test.cc
index df8b067..005b679 100644
--- a/zircon/system/dev/test/ddk-power/test.cc
+++ b/zircon/system/dev/test/ddk-power/test.cc
@@ -17,6 +17,7 @@
 using llcpp::fuchsia::device::Controller;
 using llcpp::fuchsia::device::DevicePowerState;
 using llcpp::fuchsia::device::DevicePowerStateInfo;
+using llcpp::fuchsia::device::SystemPowerStateInfo;
 using llcpp::fuchsia::device::MAX_DEVICE_POWER_STATES;
 using llcpp::fuchsia::device::power::test::TestDevice;
 
@@ -49,7 +50,28 @@
         fdio_get_service_handle(child_fd.release(), child_device_handle.reset_and_get_address()));
     ASSERT_NE(child_device_handle.get(), ZX_HANDLE_INVALID);
   }
+  void AddChildWithPowerArgs(DevicePowerStateInfo* states, uint8_t count) {
+    auto power_states =
+        ::fidl::VectorView<DevicePowerStateInfo>(count, reinterpret_cast<DevicePowerStateInfo *>(states));
+    auto response = TestDevice::Call::AddDeviceWithPowerArgs(zx::unowned(child_device_handle),
+                                                             power_states);
+    ASSERT_OK(response.status());
+    zx_status_t call_status = ZX_OK;
+    if (response->result.is_err()) {
+      call_status = response->result.err();
+    }
+    ASSERT_OK(call_status);
+
+    fbl::unique_fd child2_fd;
+    ASSERT_OK(devmgr_integration_test::RecursiveWaitForFile(
+        devmgr.devfs_root(), "sys/platform/11:0b:0/power-test/power-test-child-2", &child2_fd));
+    ASSERT_GT(child2_fd.get(), 0);
+    ASSERT_OK(
+        fdio_get_service_handle(child2_fd.release(), child2_device_handle.reset_and_get_address()));
+    ASSERT_NE(child2_device_handle.get(), ZX_HANDLE_INVALID);
+  }
   zx::channel child_device_handle;
+  zx::channel child2_device_handle;
   IsolatedDevmgr devmgr;
 };
 
@@ -160,29 +182,12 @@
   states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
   states[2].is_supported = true;
   states[2].restore_latency = 1000;
-  auto power_states =
-      ::fidl::VectorView<DevicePowerStateInfo>(3, reinterpret_cast<DevicePowerStateInfo *>(states));
-  auto response = TestDevice::Call::AddDeviceWithPowerArgs(zx::unowned(child_device_handle),
-                                                           power_states);
-  ASSERT_OK(response.status());
-  zx_status_t call_status = ZX_OK;
-  if (response->result.is_err()) {
-    call_status = response->result.err();
-  }
-  ASSERT_OK(call_status);
-
-  fbl::unique_fd child2_fd;
-  ASSERT_OK(devmgr_integration_test::RecursiveWaitForFile(
-      devmgr.devfs_root(), "sys/platform/11:0b:0/power-test/power-test-child-2", &child2_fd));
-  ASSERT_GT(child2_fd.get(), 0);
-  zx::channel child2_device_handle;
-  ASSERT_OK(
-      fdio_get_service_handle(child2_fd.release(), child2_device_handle.reset_and_get_address()));
-  ASSERT_NE(child2_device_handle.get(), ZX_HANDLE_INVALID);
+  AddChildWithPowerArgs(states, 3);
 
   const DevicePowerStateInfo *out_dpstates;
   auto response2 = Controller::Call::GetDevicePowerCaps(zx::unowned(child2_device_handle));
   ASSERT_OK(response2.status());
+  zx_status_t call_status;
   if (response2->result.is_err()) {
     call_status = response2->result.err();
   }
@@ -215,25 +220,8 @@
   states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
   states[2].is_supported = true;
   states[2].restore_latency = 1000;
-  auto power_states =
-      ::fidl::VectorView<DevicePowerStateInfo>(3, reinterpret_cast<DevicePowerStateInfo *>(states));
-  auto response = TestDevice::Call::AddDeviceWithPowerArgs(zx::unowned(child_device_handle),
-                                                           power_states);
-  ASSERT_OK(response.status());
-  zx_status_t call_status = ZX_OK;
-  if (response->result.is_err()) {
-    call_status = response->result.err();
-  }
-  ASSERT_OK(call_status);
-
-  fbl::unique_fd child2_fd;
-  ASSERT_OK(devmgr_integration_test::RecursiveWaitForFile(
-      devmgr.devfs_root(), "sys/platform/11:0b:0/power-test/power-test-child-2", &child2_fd));
-  ASSERT_GT(child2_fd.get(), 0);
-  zx::channel child2_device_handle;
-  ASSERT_OK(
-      fdio_get_service_handle(child2_fd.release(), child2_device_handle.reset_and_get_address()));
-  ASSERT_NE(child2_device_handle.get(), ZX_HANDLE_INVALID);
+  AddChildWithPowerArgs(states, 3);
+  zx_status_t call_status;
 
   auto suspend_result = Controller::Call::Suspend(zx::unowned(child2_device_handle),
                                                   DevicePowerState::DEVICE_POWER_STATE_D3COLD);
@@ -265,25 +253,8 @@
   states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
   states[2].is_supported = true;
   states[2].restore_latency = 1000;
-  auto power_states =
-      ::fidl::VectorView<DevicePowerStateInfo>(3, reinterpret_cast<DevicePowerStateInfo *>(states));
-  auto response = TestDevice::Call::AddDeviceWithPowerArgs(zx::unowned(child_device_handle),
-                                                           power_states);
-  ASSERT_OK(response.status());
-  zx_status_t call_status = ZX_OK;
-  if (response->result.is_err()) {
-    call_status = response->result.err();
-  }
-  ASSERT_OK(call_status);
-
-  fbl::unique_fd child2_fd;
-  ASSERT_OK(devmgr_integration_test::RecursiveWaitForFile(
-      devmgr.devfs_root(), "sys/platform/11:0b:0/power-test/power-test-child-2", &child2_fd));
-  ASSERT_GT(child2_fd.get(), 0);
-  zx::channel child2_device_handle;
-  ASSERT_OK(
-      fdio_get_service_handle(child2_fd.release(), child2_device_handle.reset_and_get_address()));
-  ASSERT_NE(child2_device_handle.get(), ZX_HANDLE_INVALID);
+  AddChildWithPowerArgs(states, 3);
+  zx_status_t call_status;
 
   auto suspend_result = Controller::Call::Suspend(zx::unowned(child2_device_handle),
                                                   DevicePowerState::DEVICE_POWER_STATE_D3COLD);
@@ -323,3 +294,169 @@
   ASSERT_OK(call_status);
   ASSERT_EQ(response3->result.response().cur_state, DevicePowerState::DEVICE_POWER_STATE_D0);
 }
+
+TEST_F(PowerTestCase, DefaultSystemPowerStatesMapping) {
+  // Add Capabilities
+  DevicePowerStateInfo states[3];
+  states[0].state_id = DevicePowerState::DEVICE_POWER_STATE_D0;
+  states[0].is_supported = true;
+  states[0].restore_latency = 0;
+  states[1].state_id = DevicePowerState::DEVICE_POWER_STATE_D1;
+  states[1].is_supported = true;
+  states[1].restore_latency = 100;
+  states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
+  states[2].is_supported = true;
+  states[2].restore_latency = 1000;
+  AddChildWithPowerArgs(states, 3);
+
+  const SystemPowerStateInfo *states_mapping;
+  auto response2 = Controller::Call::GetPowerStateMapping(zx::unowned(child2_device_handle));
+  ASSERT_OK(response2.status());
+  zx_status_t call_status = ZX_OK;
+  if (response2->result.is_err()) {
+    call_status = response2->result.err();
+  }
+  ASSERT_STATUS(call_status, ZX_OK);
+  states_mapping = &response2->result.response().mapping[0];
+
+  // Test Default mapping
+  ASSERT_EQ(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].dev_state,
+      DevicePowerState::DEVICE_POWER_STATE_D3COLD);
+  ASSERT_FALSE(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].wakeup_enable);
+}
+
+TEST_F(PowerTestCase, UpdatePowerStatesMapping_UnsupportedDevicestate) {
+  // Add Capabilities
+  DevicePowerStateInfo states[3];
+  states[0].state_id = DevicePowerState::DEVICE_POWER_STATE_D0;
+  states[0].is_supported = true;
+  states[0].restore_latency = 0;
+  states[1].state_id = DevicePowerState::DEVICE_POWER_STATE_D1;
+  states[1].is_supported = true;
+  states[1].restore_latency = 100;
+  states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
+  states[2].is_supported = true;
+  states[2].restore_latency = 1000;
+  AddChildWithPowerArgs(states, 3);
+
+  ::fidl::Array<SystemPowerStateInfo, fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> mapping{};
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    mapping[i].dev_state = DevicePowerState::DEVICE_POWER_STATE_D2;
+    mapping[i].wakeup_enable = false;
+  }
+
+  auto update_result = 
+    Controller::Call::UpdatePowerStateMapping(zx::unowned(child2_device_handle),
+                                              mapping);
+  ASSERT_OK(update_result.status());
+  zx_status_t call_status = ZX_OK;
+  if (update_result->result.is_err()) {
+    call_status = update_result->result.err();
+  }
+  ASSERT_EQ(call_status, ZX_ERR_INVALID_ARGS);
+
+  const SystemPowerStateInfo *states_mapping;
+  auto response2 = Controller::Call::GetPowerStateMapping(zx::unowned(child2_device_handle));
+  ASSERT_OK(response2.status());
+  call_status = ZX_OK;
+  if (response2->result.is_err()) {
+    call_status = response2->result.err();
+  }
+  ASSERT_STATUS(call_status, ZX_OK);
+  states_mapping = &response2->result.response().mapping[0];
+
+  ASSERT_EQ(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].dev_state,
+      DevicePowerState::DEVICE_POWER_STATE_D3COLD);
+  ASSERT_FALSE(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].wakeup_enable);
+}
+
+TEST_F(PowerTestCase, UpdatePowerStatesMapping_UnsupportedWakeConfig) {
+  // Add Capabilities
+  DevicePowerStateInfo states[3];
+  states[0].state_id = DevicePowerState::DEVICE_POWER_STATE_D0;
+  states[0].is_supported = true;
+  states[0].restore_latency = 0;
+  states[1].state_id = DevicePowerState::DEVICE_POWER_STATE_D1;
+  states[1].is_supported = true;
+  states[1].restore_latency = 100;
+  states[1].wakeup_capable = false;
+  states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
+  states[2].is_supported = true;
+  states[2].restore_latency = 1000;
+  AddChildWithPowerArgs(states, 3);
+
+  ::fidl::Array<SystemPowerStateInfo, fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> mapping{};
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    mapping[i].dev_state = DevicePowerState::DEVICE_POWER_STATE_D1;
+    mapping[i].wakeup_enable = true;
+  }
+
+  auto update_result = 
+    Controller::Call::UpdatePowerStateMapping(zx::unowned(child2_device_handle),
+                                              mapping);
+  ASSERT_OK(update_result.status());
+  zx_status_t call_status = ZX_OK;
+  if (update_result->result.is_err()) {
+    call_status = update_result->result.err();
+  }
+  ASSERT_EQ(call_status, ZX_ERR_INVALID_ARGS);
+
+  const SystemPowerStateInfo *states_mapping;
+  auto response2 = Controller::Call::GetPowerStateMapping(zx::unowned(child2_device_handle));
+  ASSERT_OK(response2.status());
+  call_status = ZX_OK;
+  if (response2->result.is_err()) {
+    call_status = response2->result.err();
+  }
+  ASSERT_STATUS(call_status, ZX_OK);
+  states_mapping = &response2->result.response().mapping[0];
+
+  ASSERT_EQ(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].dev_state,
+      DevicePowerState::DEVICE_POWER_STATE_D3COLD);
+  ASSERT_FALSE(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].wakeup_enable);
+}
+
+TEST_F(PowerTestCase, UpdatePowerStatesMapping_success) {
+  // Add Capabilities
+  DevicePowerStateInfo states[3];
+  states[0].state_id = DevicePowerState::DEVICE_POWER_STATE_D0;
+  states[0].is_supported = true;
+  states[0].restore_latency = 0;
+  states[1].state_id = DevicePowerState::DEVICE_POWER_STATE_D1;
+  states[1].is_supported = true;
+  states[1].restore_latency = 100;
+  states[2].state_id = DevicePowerState::DEVICE_POWER_STATE_D3COLD;
+  states[2].is_supported = true;
+  states[2].restore_latency = 1000;
+  AddChildWithPowerArgs(states, 3);
+
+  ::fidl::Array<SystemPowerStateInfo, fuchsia_device_manager_MAX_SYSTEM_POWER_STATES> mapping{};
+  for (size_t i = 0; i < fuchsia_device_manager_MAX_SYSTEM_POWER_STATES; i++) {
+    mapping[i].dev_state = DevicePowerState::DEVICE_POWER_STATE_D1;
+    mapping[i].wakeup_enable = false;
+  }
+
+  auto update_result = 
+    Controller::Call::UpdatePowerStateMapping(zx::unowned(child2_device_handle),
+                                              mapping);
+  ASSERT_OK(update_result.status());
+  zx_status_t call_status = ZX_OK;
+  if (update_result->result.is_err()) {
+    call_status = update_result->result.err();
+  }
+  ASSERT_OK(call_status);
+
+  const SystemPowerStateInfo *states_mapping;
+  auto response2 = Controller::Call::GetPowerStateMapping(zx::unowned(child2_device_handle));
+  ASSERT_OK(response2.status());
+  call_status = ZX_OK;
+  if (response2->result.is_err()) {
+    call_status = response2->result.err();
+  }
+  ASSERT_STATUS(call_status, ZX_OK);
+  states_mapping = &response2->result.response().mapping[0];
+
+  ASSERT_EQ(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].dev_state,
+      DevicePowerState::DEVICE_POWER_STATE_D1);
+  ASSERT_FALSE(states_mapping[fuchsia_device_manager_SystemPowerState_SYSTEM_POWER_STATE_REBOOT].wakeup_enable);
+}
diff --git a/zircon/system/fidl/fuchsia-device-manager/administrator.fidl b/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
index d6fba16..1e276e0 100644
--- a/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
+++ b/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
@@ -6,9 +6,25 @@
 
 using zx;
 
-/// Check the DDK for all available flags.
+// TODO(ravoorir): When the system power states are properly defined,
+// replace these flags.
+/// All available flags currently treated as system power states.
 const uint32 SUSPEND_FLAG_REBOOT = 0xdcdc0100;
+const uint32 SUSPEND_FLAG_REBOOT_BOOTLOADER = 0xdcdc0101;
+const uint32 SUSPEND_FLAG_REBOOT_RECOVERY = 0xdcdc0102;
 const uint32 SUSPEND_FLAG_POWEROFF = 0xdcdc0200;
+const uint32 SUSPEND_FLAG_MEXEC    = 0xdcdc0300;
+const uint32 SUSPEND_FLAG_SUSPEND_RAM = 0xdcdc0400;
+
+enum SystemPowerState : uint8 {
+  SYSTEM_POWER_STATE_REBOOT = 0;
+  SYSTEM_POWER_STATE_REBOOT_BOOTLOADER = 1;
+  SYSTEM_POWER_STATE_REBOOT_RECOVERY = 2;
+  SYSTEM_POWER_STATE_REBOOT_POWEROFF = 3;
+  SYSTEM_POWER_STATE_REBOOT_MEXEC = 4;
+  SYSTEM_POWER_STATE_REBOOT_SUSPEND_RAM = 5;
+};
+const uint32 MAX_SYSTEM_POWER_STATES = 6;
 
 /// Provides administration services for the device manager service and the device tree it controls.
 [Discoverable, Layout = "Simple"]
diff --git a/zircon/system/fidl/fuchsia-device-manager/gen/llcpp/include/fuchsia/device/manager/llcpp/fidl.h b/zircon/system/fidl/fuchsia-device-manager/gen/llcpp/include/fuchsia/device/manager/llcpp/fidl.h
index 5f5412e..19b1809 100644
--- a/zircon/system/fidl/fuchsia-device-manager/gen/llcpp/include/fuchsia/device/manager/llcpp/fidl.h
+++ b/zircon/system/fidl/fuchsia-device-manager/gen/llcpp/include/fuchsia/device/manager/llcpp/fidl.h
@@ -22,6 +22,16 @@
 namespace device {
 namespace manager {
 
+enum class SystemPowerState : uint8_t {
+  SYSTEM_POWER_STATE_REBOOT = 0u,
+  SYSTEM_POWER_STATE_REBOOT_BOOTLOADER = 1u,
+  SYSTEM_POWER_STATE_REBOOT_RECOVERY = 2u,
+  SYSTEM_POWER_STATE_REBOOT_POWEROFF = 3u,
+  SYSTEM_POWER_STATE_REBOOT_MEXEC = 4u,
+  SYSTEM_POWER_STATE_REBOOT_SUSPEND_RAM = 5u,
+};
+
+
 class DebugDumper;
 class Administrator;
 class DevhostController;
@@ -705,17 +715,27 @@
 
 };
 
-// Check the DDK for all available flags.
+constexpr uint32_t SUSPEND_FLAG_SUSPEND_RAM = 3705406464u;
+
+constexpr uint32_t SUSPEND_FLAG_REBOOT_RECOVERY = 3705405698u;
+
+constexpr uint32_t SUSPEND_FLAG_REBOOT_BOOTLOADER = 3705405697u;
+
+// All available flags currently treated as system power states.
 constexpr uint32_t SUSPEND_FLAG_REBOOT = 3705405696u;
 
 constexpr uint32_t SUSPEND_FLAG_POWEROFF = 3705405952u;
 
+constexpr uint32_t SUSPEND_FLAG_MEXEC = 3705406208u;
+
 // Maximum number of properties that can be attached to a device
 constexpr uint32_t PROPERTIES_MAX = 256u;
 
 // Maximum number of bytes in a metadata payload
 constexpr uint32_t METADATA_MAX = 8192u;
 
+constexpr uint32_t MAX_SYSTEM_POWER_STATES = 6u;
+
 extern "C" const fidl_type_t fuchsia_device_manager_DevhostControllerCreateDeviceStubRequestTable;
 extern "C" const fidl_type_t fuchsia_device_manager_DevhostControllerCreateDeviceRequestTable;
 extern "C" const fidl_type_t fuchsia_device_manager_DevhostControllerCreateCompositeDeviceRequestTable;
diff --git a/zircon/system/fidl/fuchsia-device/BUILD.gn b/zircon/system/fidl/fuchsia-device/BUILD.gn
index eda2e2b..321de69 100644
--- a/zircon/system/fidl/fuchsia-device/BUILD.gn
+++ b/zircon/system/fidl/fuchsia-device/BUILD.gn
@@ -9,4 +9,7 @@
     "controller.fidl",
     "name-provider.fidl",
   ]
+  public_deps = [
+    "$zx/system/fidl/fuchsia-device-manager"
+  ]
 }
diff --git a/zircon/system/fidl/fuchsia-device/controller.fidl b/zircon/system/fidl/fuchsia-device/controller.fidl
index c654333..96d418e 100644
--- a/zircon/system/fidl/fuchsia-device/controller.fidl
+++ b/zircon/system/fidl/fuchsia-device/controller.fidl
@@ -5,6 +5,7 @@
 library fuchsia.device;
 
 using zx;
+using fuchsia.device.manager;
 
 /// Maxmium length for a device name
 const uint64 MAX_DEVICE_NAME_LEN = 32;
@@ -99,6 +100,15 @@
   int32 system_wake_state;
 };
 
+struct SystemPowerStateInfo {
+  uint32 suspend_flag;
+  /// Should wakeup be enabled from this system state?
+  bool wakeup_enable;
+
+  /// Device power state that the device should be in for this system power state.
+  DevicePowerState dev_state;
+};
+
 /// Interface for manipulating a device in a devhost
 [Layout = "Simple"]
 protocol Controller {
@@ -141,6 +151,14 @@
     /// to manage power for this device.
     GetDevicePowerCaps() -> (array<DevicePowerStateInfo>:MAX_DEVICE_POWER_STATES dpstates) error zx.status;
 
+    /// Updates the mapping between system power states to device power states. Used by the system
+    /// wide power manager to manage power for this device
+    UpdatePowerStateMapping(array<SystemPowerStateInfo>:fuchsia.device.manager.MAX_SYSTEM_POWER_STATES mapping) -> () error zx.status;
+
+    /// Get the mapping between system power states to device power states. Used by the system
+    /// wide power manager to manage power for this device.
+    GetPowerStateMapping()->(array<SystemPowerStateInfo>:fuchsia.device.manager.MAX_SYSTEM_POWER_STATES mapping) error zx.status;
+
     /// Transition this device from a working to a sleep state or from a sleep state to a deeper sleep
     /// state. TODO(ravoorir): At the moment, this will call the suspend hook only on this device.
     /// In a future change, this api will result in suspend hook being called on all the children and
diff --git a/zircon/system/fidl/fuchsia-device/gen/llcpp/fidl.cc b/zircon/system/fidl/fuchsia-device/gen/llcpp/fidl.cc
index ca33ded..06dfc8c 100644
--- a/zircon/system/fidl/fuchsia-device/gen/llcpp/fidl.cc
+++ b/zircon/system/fidl/fuchsia-device/gen/llcpp/fidl.cc
@@ -211,6 +211,65 @@
 }
 
 
+::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::Controller_GetPowerStateMapping_Result() {
+  tag_ = Tag::Invalid;
+}
+
+::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::~Controller_GetPowerStateMapping_Result() {
+  Destroy();
+}
+
+void ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::Destroy() {
+  switch (which()) {
+  case Tag::kResponse:
+    response_.~Controller_GetPowerStateMapping_Response();
+    break;
+  default:
+    break;
+  }
+  tag_ = Tag::Invalid;
+}
+
+void ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::MoveImpl_(Controller_GetPowerStateMapping_Result&& other) {
+  switch (other.which()) {
+  case Tag::kResponse:
+    mutable_response() = std::move(other.mutable_response());
+    break;
+  case Tag::kErr:
+    mutable_err() = std::move(other.mutable_err());
+    break;
+  default:
+    break;
+  }
+  other.Destroy();
+}
+
+void ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::SizeAndOffsetAssertionHelper() {
+  static_assert(offsetof(::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result, response_) == 4);
+  static_assert(offsetof(::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result, err_) == 4);
+  static_assert(sizeof(::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result) == ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::PrimarySize);
+}
+
+
+Controller_GetPowerStateMapping_Response& ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::mutable_response() {
+  if (which() != Tag::kResponse) {
+    Destroy();
+    new (&response_) Controller_GetPowerStateMapping_Response;
+  }
+  tag_ = Tag::kResponse;
+  return response_;
+}
+
+int32_t& ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result::mutable_err() {
+  if (which() != Tag::kErr) {
+    Destroy();
+    new (&err_) int32_t;
+  }
+  tag_ = Tag::kErr;
+  return err_;
+}
+
+
 ::llcpp::fuchsia::device::Controller_GetDevicePowerCaps_Result::Controller_GetDevicePowerCaps_Result() {
   tag_ = Tag::Invalid;
 }
@@ -328,6 +387,66 @@
   return err_;
 }
 
+const char DEFAULT_DEVICE_NAME[] = "fuchsia";
+
+::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::Controller_UpdatePowerStateMapping_Result() {
+  tag_ = Tag::Invalid;
+}
+
+::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::~Controller_UpdatePowerStateMapping_Result() {
+  Destroy();
+}
+
+void ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::Destroy() {
+  switch (which()) {
+  case Tag::kResponse:
+    response_.~Controller_UpdatePowerStateMapping_Response();
+    break;
+  default:
+    break;
+  }
+  tag_ = Tag::Invalid;
+}
+
+void ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::MoveImpl_(Controller_UpdatePowerStateMapping_Result&& other) {
+  switch (other.which()) {
+  case Tag::kResponse:
+    mutable_response() = std::move(other.mutable_response());
+    break;
+  case Tag::kErr:
+    mutable_err() = std::move(other.mutable_err());
+    break;
+  default:
+    break;
+  }
+  other.Destroy();
+}
+
+void ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::SizeAndOffsetAssertionHelper() {
+  static_assert(offsetof(::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result, response_) == 4);
+  static_assert(offsetof(::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result, err_) == 4);
+  static_assert(sizeof(::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result) == ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::PrimarySize);
+}
+
+
+Controller_UpdatePowerStateMapping_Response& ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::mutable_response() {
+  if (which() != Tag::kResponse) {
+    Destroy();
+    new (&response_) Controller_UpdatePowerStateMapping_Response;
+  }
+  tag_ = Tag::kResponse;
+  return response_;
+}
+
+int32_t& ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result::mutable_err() {
+  if (which() != Tag::kErr) {
+    Destroy();
+    new (&err_) int32_t;
+  }
+  tag_ = Tag::kErr;
+  return err_;
+}
+
 
 namespace {
 
@@ -368,6 +487,13 @@
 constexpr uint64_t kController_GetDevicePowerCaps_Ordinal = 0x70a9ecf200000000lu;
 extern "C" const fidl_type_t fuchsia_device_ControllerGetDevicePowerCapsResponseTable;
 [[maybe_unused]]
+constexpr uint64_t kController_UpdatePowerStateMapping_Ordinal = 0x5200982600000000lu;
+extern "C" const fidl_type_t fuchsia_device_ControllerUpdatePowerStateMappingRequestTable;
+extern "C" const fidl_type_t fuchsia_device_ControllerUpdatePowerStateMappingResponseTable;
+[[maybe_unused]]
+constexpr uint64_t kController_GetPowerStateMapping_Ordinal = 0x4ca6662900000000lu;
+extern "C" const fidl_type_t fuchsia_device_ControllerGetPowerStateMappingResponseTable;
+[[maybe_unused]]
 constexpr uint64_t kController_Suspend_Ordinal = 0x5897568300000000lu;
 extern "C" const fidl_type_t fuchsia_device_ControllerSuspendRequestTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerSuspendResponseTable;
@@ -1132,6 +1258,131 @@
 }
 
 template <>
+Controller::ResultOf::UpdatePowerStateMapping_Impl<Controller::UpdatePowerStateMappingResponse>::UpdatePowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::Array<SystemPowerStateInfo, 6> mapping) {
+  constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<UpdatePowerStateMappingRequest, ::fidl::MessageDirection::kSending>();
+  ::fidl::internal::AlignedBuffer<_kWriteAllocSize> _write_bytes_inlined;
+  auto& _write_bytes_array = _write_bytes_inlined;
+  uint8_t* _write_bytes = _write_bytes_array.view().data();
+  memset(_write_bytes, 0, UpdatePowerStateMappingRequest::PrimarySize);
+  auto& _request = *reinterpret_cast<UpdatePowerStateMappingRequest*>(_write_bytes);
+  _request.mapping = std::move(mapping);
+  ::fidl::BytePart _request_bytes(_write_bytes, _kWriteAllocSize, sizeof(UpdatePowerStateMappingRequest));
+  ::fidl::DecodedMessage<UpdatePowerStateMappingRequest> _decoded_request(std::move(_request_bytes));
+  Super::SetResult(
+      Controller::InPlace::UpdatePowerStateMapping(std::move(_client_end), std::move(_decoded_request), Super::response_buffer()));
+}
+
+Controller::ResultOf::UpdatePowerStateMapping Controller::SyncClient::UpdatePowerStateMapping(::fidl::Array<SystemPowerStateInfo, 6> mapping) {
+  return ResultOf::UpdatePowerStateMapping(zx::unowned_channel(this->channel_), std::move(mapping));
+}
+
+Controller::ResultOf::UpdatePowerStateMapping Controller::Call::UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::Array<SystemPowerStateInfo, 6> mapping) {
+  return ResultOf::UpdatePowerStateMapping(std::move(_client_end), std::move(mapping));
+}
+
+template <>
+Controller::UnownedResultOf::UpdatePowerStateMapping_Impl<Controller::UpdatePowerStateMappingResponse>::UpdatePowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer) {
+  if (_request_buffer.capacity() < UpdatePowerStateMappingRequest::PrimarySize) {
+    Super::SetFailure(::fidl::DecodeResult<UpdatePowerStateMappingResponse>(ZX_ERR_BUFFER_TOO_SMALL, ::fidl::internal::kErrorRequestBufferTooSmall));
+    return;
+  }
+  memset(_request_buffer.data(), 0, UpdatePowerStateMappingRequest::PrimarySize);
+  auto& _request = *reinterpret_cast<UpdatePowerStateMappingRequest*>(_request_buffer.data());
+  _request.mapping = std::move(mapping);
+  _request_buffer.set_actual(sizeof(UpdatePowerStateMappingRequest));
+  ::fidl::DecodedMessage<UpdatePowerStateMappingRequest> _decoded_request(std::move(_request_buffer));
+  Super::SetResult(
+      Controller::InPlace::UpdatePowerStateMapping(std::move(_client_end), std::move(_decoded_request), std::move(_response_buffer)));
+}
+
+Controller::UnownedResultOf::UpdatePowerStateMapping Controller::SyncClient::UpdatePowerStateMapping(::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer) {
+  return UnownedResultOf::UpdatePowerStateMapping(zx::unowned_channel(this->channel_), std::move(_request_buffer), std::move(mapping), std::move(_response_buffer));
+}
+
+Controller::UnownedResultOf::UpdatePowerStateMapping Controller::Call::UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer) {
+  return UnownedResultOf::UpdatePowerStateMapping(std::move(_client_end), std::move(_request_buffer), std::move(mapping), std::move(_response_buffer));
+}
+
+::fidl::DecodeResult<Controller::UpdatePowerStateMappingResponse> Controller::InPlace::UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::DecodedMessage<UpdatePowerStateMappingRequest> params, ::fidl::BytePart response_buffer) {
+  params.message()->_hdr = {};
+  params.message()->_hdr.ordinal = kController_UpdatePowerStateMapping_Ordinal;
+  auto _encode_request_result = ::fidl::Encode(std::move(params));
+  if (_encode_request_result.status != ZX_OK) {
+    return ::fidl::DecodeResult<Controller::UpdatePowerStateMappingResponse>::FromFailure(
+        std::move(_encode_request_result));
+  }
+  auto _call_result = ::fidl::Call<UpdatePowerStateMappingRequest, UpdatePowerStateMappingResponse>(
+    std::move(_client_end), std::move(_encode_request_result.message), std::move(response_buffer));
+  if (_call_result.status != ZX_OK) {
+    return ::fidl::DecodeResult<Controller::UpdatePowerStateMappingResponse>::FromFailure(
+        std::move(_call_result));
+  }
+  return ::fidl::Decode(std::move(_call_result.message));
+}
+
+template <>
+Controller::ResultOf::GetPowerStateMapping_Impl<Controller::GetPowerStateMappingResponse>::GetPowerStateMapping_Impl(zx::unowned_channel _client_end) {
+  constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<GetPowerStateMappingRequest, ::fidl::MessageDirection::kSending>();
+  ::fidl::internal::AlignedBuffer<_kWriteAllocSize> _write_bytes_inlined;
+  auto& _write_bytes_array = _write_bytes_inlined;
+  uint8_t* _write_bytes = _write_bytes_array.view().data();
+  memset(_write_bytes, 0, GetPowerStateMappingRequest::PrimarySize);
+  ::fidl::BytePart _request_bytes(_write_bytes, _kWriteAllocSize, sizeof(GetPowerStateMappingRequest));
+  ::fidl::DecodedMessage<GetPowerStateMappingRequest> _decoded_request(std::move(_request_bytes));
+  Super::SetResult(
+      Controller::InPlace::GetPowerStateMapping(std::move(_client_end), Super::response_buffer()));
+}
+
+Controller::ResultOf::GetPowerStateMapping Controller::SyncClient::GetPowerStateMapping() {
+  return ResultOf::GetPowerStateMapping(zx::unowned_channel(this->channel_));
+}
+
+Controller::ResultOf::GetPowerStateMapping Controller::Call::GetPowerStateMapping(zx::unowned_channel _client_end) {
+  return ResultOf::GetPowerStateMapping(std::move(_client_end));
+}
+
+template <>
+Controller::UnownedResultOf::GetPowerStateMapping_Impl<Controller::GetPowerStateMappingResponse>::GetPowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer) {
+  FIDL_ALIGNDECL uint8_t _write_bytes[sizeof(GetPowerStateMappingRequest)] = {};
+  ::fidl::BytePart _request_buffer(_write_bytes, sizeof(_write_bytes));
+  memset(_request_buffer.data(), 0, GetPowerStateMappingRequest::PrimarySize);
+  _request_buffer.set_actual(sizeof(GetPowerStateMappingRequest));
+  ::fidl::DecodedMessage<GetPowerStateMappingRequest> _decoded_request(std::move(_request_buffer));
+  Super::SetResult(
+      Controller::InPlace::GetPowerStateMapping(std::move(_client_end), std::move(_response_buffer)));
+}
+
+Controller::UnownedResultOf::GetPowerStateMapping Controller::SyncClient::GetPowerStateMapping(::fidl::BytePart _response_buffer) {
+  return UnownedResultOf::GetPowerStateMapping(zx::unowned_channel(this->channel_), std::move(_response_buffer));
+}
+
+Controller::UnownedResultOf::GetPowerStateMapping Controller::Call::GetPowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer) {
+  return UnownedResultOf::GetPowerStateMapping(std::move(_client_end), std::move(_response_buffer));
+}
+
+::fidl::DecodeResult<Controller::GetPowerStateMappingResponse> Controller::InPlace::GetPowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart response_buffer) {
+  constexpr uint32_t _write_num_bytes = sizeof(GetPowerStateMappingRequest);
+  ::fidl::internal::AlignedBuffer<_write_num_bytes> _write_bytes;
+  ::fidl::BytePart _request_buffer = _write_bytes.view();
+  _request_buffer.set_actual(_write_num_bytes);
+  ::fidl::DecodedMessage<GetPowerStateMappingRequest> params(std::move(_request_buffer));
+  params.message()->_hdr = {};
+  params.message()->_hdr.ordinal = kController_GetPowerStateMapping_Ordinal;
+  auto _encode_request_result = ::fidl::Encode(std::move(params));
+  if (_encode_request_result.status != ZX_OK) {
+    return ::fidl::DecodeResult<Controller::GetPowerStateMappingResponse>::FromFailure(
+        std::move(_encode_request_result));
+  }
+  auto _call_result = ::fidl::Call<GetPowerStateMappingRequest, GetPowerStateMappingResponse>(
+    std::move(_client_end), std::move(_encode_request_result.message), std::move(response_buffer));
+  if (_call_result.status != ZX_OK) {
+    return ::fidl::DecodeResult<Controller::GetPowerStateMappingResponse>::FromFailure(
+        std::move(_call_result));
+  }
+  return ::fidl::Decode(std::move(_call_result.message));
+}
+
+template <>
 Controller::ResultOf::Suspend_Impl<Controller::SuspendResponse>::Suspend_Impl(zx::unowned_channel _client_end, DevicePowerState requested_state) {
   constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<SuspendRequest, ::fidl::MessageDirection::kSending>();
   ::fidl::internal::AlignedBuffer<_kWriteAllocSize> _write_bytes_inlined;
@@ -1401,6 +1652,29 @@
         Interface::GetDevicePowerCapsCompleter::Sync(txn));
       return true;
     }
+    case kController_UpdatePowerStateMapping_Ordinal:
+    {
+      auto result = ::fidl::DecodeAs<UpdatePowerStateMappingRequest>(msg);
+      if (result.status != ZX_OK) {
+        txn->Close(ZX_ERR_INVALID_ARGS);
+        return true;
+      }
+      auto message = result.message.message();
+      impl->UpdatePowerStateMapping(std::move(message->mapping),
+        Interface::UpdatePowerStateMappingCompleter::Sync(txn));
+      return true;
+    }
+    case kController_GetPowerStateMapping_Ordinal:
+    {
+      auto result = ::fidl::DecodeAs<GetPowerStateMappingRequest>(msg);
+      if (result.status != ZX_OK) {
+        txn->Close(ZX_ERR_INVALID_ARGS);
+        return true;
+      }
+      impl->GetPowerStateMapping(
+        Interface::GetPowerStateMappingCompleter::Sync(txn));
+      return true;
+    }
     case kController_Suspend_Ordinal:
     {
       auto result = ::fidl::DecodeAs<SuspendRequest>(msg);
@@ -1825,6 +2099,64 @@
 }
 
 
+void Controller::Interface::UpdatePowerStateMappingCompleterBase::Reply(Controller_UpdatePowerStateMapping_Result result) {
+  constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<UpdatePowerStateMappingResponse, ::fidl::MessageDirection::kSending>();
+  FIDL_ALIGNDECL uint8_t _write_bytes[_kWriteAllocSize] = {};
+  auto& _response = *reinterpret_cast<UpdatePowerStateMappingResponse*>(_write_bytes);
+  _response._hdr.ordinal = kController_UpdatePowerStateMapping_Ordinal;
+  _response.result = std::move(result);
+  ::fidl::BytePart _response_bytes(_write_bytes, _kWriteAllocSize, sizeof(UpdatePowerStateMappingResponse));
+  CompleterBase::SendReply(::fidl::DecodedMessage<UpdatePowerStateMappingResponse>(std::move(_response_bytes)));
+}
+
+void Controller::Interface::UpdatePowerStateMappingCompleterBase::Reply(::fidl::BytePart _buffer, Controller_UpdatePowerStateMapping_Result result) {
+  if (_buffer.capacity() < UpdatePowerStateMappingResponse::PrimarySize) {
+    CompleterBase::Close(ZX_ERR_INTERNAL);
+    return;
+  }
+  auto& _response = *reinterpret_cast<UpdatePowerStateMappingResponse*>(_buffer.data());
+  _response._hdr.ordinal = kController_UpdatePowerStateMapping_Ordinal;
+  _response.result = std::move(result);
+  _buffer.set_actual(sizeof(UpdatePowerStateMappingResponse));
+  CompleterBase::SendReply(::fidl::DecodedMessage<UpdatePowerStateMappingResponse>(std::move(_buffer)));
+}
+
+void Controller::Interface::UpdatePowerStateMappingCompleterBase::Reply(::fidl::DecodedMessage<UpdatePowerStateMappingResponse> params) {
+  params.message()->_hdr = {};
+  params.message()->_hdr.ordinal = kController_UpdatePowerStateMapping_Ordinal;
+  CompleterBase::SendReply(std::move(params));
+}
+
+
+void Controller::Interface::GetPowerStateMappingCompleterBase::Reply(Controller_GetPowerStateMapping_Result result) {
+  constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<GetPowerStateMappingResponse, ::fidl::MessageDirection::kSending>();
+  FIDL_ALIGNDECL uint8_t _write_bytes[_kWriteAllocSize] = {};
+  auto& _response = *reinterpret_cast<GetPowerStateMappingResponse*>(_write_bytes);
+  _response._hdr.ordinal = kController_GetPowerStateMapping_Ordinal;
+  _response.result = std::move(result);
+  ::fidl::BytePart _response_bytes(_write_bytes, _kWriteAllocSize, sizeof(GetPowerStateMappingResponse));
+  CompleterBase::SendReply(::fidl::DecodedMessage<GetPowerStateMappingResponse>(std::move(_response_bytes)));
+}
+
+void Controller::Interface::GetPowerStateMappingCompleterBase::Reply(::fidl::BytePart _buffer, Controller_GetPowerStateMapping_Result result) {
+  if (_buffer.capacity() < GetPowerStateMappingResponse::PrimarySize) {
+    CompleterBase::Close(ZX_ERR_INTERNAL);
+    return;
+  }
+  auto& _response = *reinterpret_cast<GetPowerStateMappingResponse*>(_buffer.data());
+  _response._hdr.ordinal = kController_GetPowerStateMapping_Ordinal;
+  _response.result = std::move(result);
+  _buffer.set_actual(sizeof(GetPowerStateMappingResponse));
+  CompleterBase::SendReply(::fidl::DecodedMessage<GetPowerStateMappingResponse>(std::move(_buffer)));
+}
+
+void Controller::Interface::GetPowerStateMappingCompleterBase::Reply(::fidl::DecodedMessage<GetPowerStateMappingResponse> params) {
+  params.message()->_hdr = {};
+  params.message()->_hdr.ordinal = kController_GetPowerStateMapping_Ordinal;
+  CompleterBase::SendReply(std::move(params));
+}
+
+
 void Controller::Interface::SuspendCompleterBase::Reply(int32_t status, DevicePowerState out_state) {
   constexpr uint32_t _kWriteAllocSize = ::fidl::internal::ClampedMessageSize<SuspendResponse, ::fidl::MessageDirection::kSending>();
   FIDL_ALIGNDECL uint8_t _write_bytes[_kWriteAllocSize] = {};
@@ -1884,7 +2216,6 @@
   CompleterBase::SendReply(std::move(params));
 }
 
-const char DEFAULT_DEVICE_NAME[] = "fuchsia";
 
 }  // namespace device
 }  // namespace fuchsia
diff --git a/zircon/system/fidl/fuchsia-device/gen/llcpp/include/fuchsia/device/llcpp/fidl.h b/zircon/system/fidl/fuchsia-device/gen/llcpp/include/fuchsia/device/llcpp/fidl.h
index 930e7d5..9f0b943 100644
--- a/zircon/system/fidl/fuchsia-device/gen/llcpp/include/fuchsia/device/llcpp/fidl.h
+++ b/zircon/system/fidl/fuchsia-device/gen/llcpp/include/fuchsia/device/llcpp/fidl.h
@@ -15,6 +15,8 @@
 #include <lib/zx/event.h>
 #include <zircon/fidl.h>
 
+#include <fuchsia/device/manager/llcpp/fidl.h>
+
 namespace llcpp {
 
 namespace fuchsia {
@@ -32,11 +34,16 @@
 };
 
 
+struct SystemPowerStateInfo;
+struct Controller_GetPowerStateMapping_Response;
+struct Controller_GetPowerStateMapping_Result;
 struct DevicePowerStateInfo;
 struct Controller_GetDevicePowerCaps_Response;
 struct Controller_GetDevicePowerCaps_Result;
 struct Controller_Resume_Response;
 struct Controller_Resume_Result;
+struct Controller_UpdatePowerStateMapping_Response;
+struct Controller_UpdatePowerStateMapping_Result;
 class Controller;
 
 extern "C" const fidl_type_t fuchsia_device_NameProvider_GetDeviceName_ResponseTable;
@@ -320,6 +327,119 @@
 // Maxmium length for a device name
 constexpr uint64_t MAX_DEVICE_NAME_LEN = 32u;
 
+extern "C" const fidl_type_t fuchsia_device_SystemPowerStateInfoTable;
+
+struct SystemPowerStateInfo {
+  static constexpr const fidl_type_t* Type = &fuchsia_device_SystemPowerStateInfoTable;
+  static constexpr uint32_t MaxNumHandles = 0;
+  static constexpr uint32_t PrimarySize = 8;
+  [[maybe_unused]]
+  static constexpr uint32_t MaxOutOfLine = 0;
+
+  uint32_t suspend_flag = {};
+
+  // Should wakeup be enabled from this system state?
+  bool wakeup_enable = {};
+
+  // Device power state that the device should be in for this system power state.
+  DevicePowerState dev_state = {};
+};
+
+extern "C" const fidl_type_t fuchsia_device_Controller_GetPowerStateMapping_ResponseTable;
+
+struct Controller_GetPowerStateMapping_Response {
+  static constexpr const fidl_type_t* Type = &fuchsia_device_Controller_GetPowerStateMapping_ResponseTable;
+  static constexpr uint32_t MaxNumHandles = 0;
+  static constexpr uint32_t PrimarySize = 48;
+  [[maybe_unused]]
+  static constexpr uint32_t MaxOutOfLine = 0;
+
+  ::fidl::Array<SystemPowerStateInfo, 6> mapping = {};
+};
+
+extern "C" const fidl_type_t fuchsia_device_Controller_GetPowerStateMapping_ResultTable;
+
+struct Controller_GetPowerStateMapping_Result {
+  enum class Tag : fidl_union_tag_t {
+    kResponse = 0,
+    kErr = 1,
+    Invalid = ::std::numeric_limits<::fidl_union_tag_t>::max(),
+  };
+
+  Controller_GetPowerStateMapping_Result();
+  ~Controller_GetPowerStateMapping_Result();
+
+  Controller_GetPowerStateMapping_Result(Controller_GetPowerStateMapping_Result&& other) {
+    tag_ = Tag::Invalid;
+    if (this != &other) {
+      MoveImpl_(std::move(other));
+    }
+  }
+
+  Controller_GetPowerStateMapping_Result& operator=(Controller_GetPowerStateMapping_Result&& other) {
+    if (this != &other) {
+      MoveImpl_(std::move(other));
+    }
+    return *this;
+  }
+
+  bool has_invalid_tag() const { return tag_ == Tag::Invalid; }
+
+  bool is_response() const { return tag_ == Tag::kResponse; }
+
+  Controller_GetPowerStateMapping_Response& mutable_response();
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, Controller_GetPowerStateMapping_Response>::value && std::is_copy_assignable<T>::value>
+  set_response(const T& v) {
+    mutable_response() = v;
+  }
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, Controller_GetPowerStateMapping_Response>::value && std::is_move_assignable<T>::value>
+  set_response(T&& v) {
+    mutable_response() = std::move(v);
+  }
+
+  Controller_GetPowerStateMapping_Response const & response() const { return response_; }
+
+  bool is_err() const { return tag_ == Tag::kErr; }
+
+  int32_t& mutable_err();
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, int32_t>::value && std::is_copy_assignable<T>::value>
+  set_err(const T& v) {
+    mutable_err() = v;
+  }
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, int32_t>::value && std::is_move_assignable<T>::value>
+  set_err(T&& v) {
+    mutable_err() = std::move(v);
+  }
+
+  int32_t const & err() const { return err_; }
+
+  Tag which() const { return tag_; }
+
+  static constexpr const fidl_type_t* Type = &fuchsia_device_Controller_GetPowerStateMapping_ResultTable;
+  static constexpr uint32_t MaxNumHandles = 0;
+  static constexpr uint32_t PrimarySize = 52;
+  [[maybe_unused]]
+  static constexpr uint32_t MaxOutOfLine = 0;
+
+ private:
+  void Destroy();
+  void MoveImpl_(Controller_GetPowerStateMapping_Result&& other);
+  static void SizeAndOffsetAssertionHelper();
+  Tag tag_;
+  union {
+    Controller_GetPowerStateMapping_Response response_;
+    int32_t err_;
+  };
+};
+
 extern "C" const fidl_type_t fuchsia_device_DevicePowerStateInfoTable;
 
 struct DevicePowerStateInfo {
@@ -534,6 +654,124 @@
   };
 };
 
+// Signal that will be active on a device event handle if the device's write() method
+// will accept data.
+constexpr uint32_t DEVICE_SIGNAL_WRITABLE = 67108864u;
+
+// Signal that will be active on a device event handle if the device's read() method
+// will return data.
+constexpr uint32_t DEVICE_SIGNAL_READABLE = 16777216u;
+
+// Signal that will be active on a device event handle if the device has some out-of-band
+// mechanism that needs attention.
+// This is primarily used by the PTY support.
+constexpr uint32_t DEVICE_SIGNAL_OOB = 33554432u;
+
+// Signal that will be active on a device event handle if the device has been disconnected.
+// This is primarily used by the PTY support.
+constexpr uint32_t DEVICE_SIGNAL_HANGUP = 268435456u;
+
+// Signal that will be active on a device event handle if the device has encountered an error.
+// This is primarily used by the PTY support.
+constexpr uint32_t DEVICE_SIGNAL_ERROR = 134217728u;
+
+extern const char DEFAULT_DEVICE_NAME[];
+
+
+
+struct Controller_UpdatePowerStateMapping_Response {
+  static constexpr const fidl_type_t* Type = nullptr;
+  static constexpr uint32_t MaxNumHandles = 0;
+  static constexpr uint32_t PrimarySize = 1;
+  [[maybe_unused]]
+  static constexpr uint32_t MaxOutOfLine = 0;
+
+  uint8_t __reserved = {};
+};
+
+extern "C" const fidl_type_t fuchsia_device_Controller_UpdatePowerStateMapping_ResultTable;
+
+struct Controller_UpdatePowerStateMapping_Result {
+  enum class Tag : fidl_union_tag_t {
+    kResponse = 0,
+    kErr = 1,
+    Invalid = ::std::numeric_limits<::fidl_union_tag_t>::max(),
+  };
+
+  Controller_UpdatePowerStateMapping_Result();
+  ~Controller_UpdatePowerStateMapping_Result();
+
+  Controller_UpdatePowerStateMapping_Result(Controller_UpdatePowerStateMapping_Result&& other) {
+    tag_ = Tag::Invalid;
+    if (this != &other) {
+      MoveImpl_(std::move(other));
+    }
+  }
+
+  Controller_UpdatePowerStateMapping_Result& operator=(Controller_UpdatePowerStateMapping_Result&& other) {
+    if (this != &other) {
+      MoveImpl_(std::move(other));
+    }
+    return *this;
+  }
+
+  bool has_invalid_tag() const { return tag_ == Tag::Invalid; }
+
+  bool is_response() const { return tag_ == Tag::kResponse; }
+
+  Controller_UpdatePowerStateMapping_Response& mutable_response();
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, Controller_UpdatePowerStateMapping_Response>::value && std::is_copy_assignable<T>::value>
+  set_response(const T& v) {
+    mutable_response() = v;
+  }
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, Controller_UpdatePowerStateMapping_Response>::value && std::is_move_assignable<T>::value>
+  set_response(T&& v) {
+    mutable_response() = std::move(v);
+  }
+
+  Controller_UpdatePowerStateMapping_Response const & response() const { return response_; }
+
+  bool is_err() const { return tag_ == Tag::kErr; }
+
+  int32_t& mutable_err();
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, int32_t>::value && std::is_copy_assignable<T>::value>
+  set_err(const T& v) {
+    mutable_err() = v;
+  }
+
+  template <typename T>
+  std::enable_if_t<std::is_convertible<T, int32_t>::value && std::is_move_assignable<T>::value>
+  set_err(T&& v) {
+    mutable_err() = std::move(v);
+  }
+
+  int32_t const & err() const { return err_; }
+
+  Tag which() const { return tag_; }
+
+  static constexpr const fidl_type_t* Type = &fuchsia_device_Controller_UpdatePowerStateMapping_ResultTable;
+  static constexpr uint32_t MaxNumHandles = 0;
+  static constexpr uint32_t PrimarySize = 8;
+  [[maybe_unused]]
+  static constexpr uint32_t MaxOutOfLine = 0;
+
+ private:
+  void Destroy();
+  void MoveImpl_(Controller_UpdatePowerStateMapping_Result&& other);
+  static void SizeAndOffsetAssertionHelper();
+  Tag tag_;
+  union {
+    Controller_UpdatePowerStateMapping_Response response_;
+    int32_t err_;
+  };
+};
+
 extern "C" const fidl_type_t fuchsia_device_ControllerBindRequestTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerBindResponseTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerScheduleUnbindResponseTable;
@@ -546,6 +784,9 @@
 extern "C" const fidl_type_t fuchsia_device_ControllerDebugResumeResponseTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerRunCompatibilityTestsResponseTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerGetDevicePowerCapsResponseTable;
+extern "C" const fidl_type_t fuchsia_device_ControllerUpdatePowerStateMappingRequestTable;
+extern "C" const fidl_type_t fuchsia_device_ControllerUpdatePowerStateMappingResponseTable;
+extern "C" const fidl_type_t fuchsia_device_ControllerGetPowerStateMappingResponseTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerSuspendRequestTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerSuspendResponseTable;
 extern "C" const fidl_type_t fuchsia_device_ControllerResumeRequestTable;
@@ -780,6 +1021,49 @@
   };
   using GetDevicePowerCapsRequest = ::fidl::AnyZeroArgMessage;
 
+  struct UpdatePowerStateMappingResponse final {
+    FIDL_ALIGNDECL
+    fidl_message_header_t _hdr;
+    Controller_UpdatePowerStateMapping_Result result;
+
+    static constexpr const fidl_type_t* Type = &fuchsia_device_ControllerUpdatePowerStateMappingResponseTable;
+    static constexpr uint32_t MaxNumHandles = 0;
+    static constexpr uint32_t PrimarySize = 24;
+    static constexpr uint32_t MaxOutOfLine = 0;
+    static constexpr bool HasFlexibleEnvelope = false;
+    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
+        ::fidl::internal::TransactionalMessageKind::kResponse;
+  };
+  struct UpdatePowerStateMappingRequest final {
+    FIDL_ALIGNDECL
+    fidl_message_header_t _hdr;
+    ::fidl::Array<SystemPowerStateInfo, 6> mapping;
+
+    static constexpr const fidl_type_t* Type = &fuchsia_device_ControllerUpdatePowerStateMappingRequestTable;
+    static constexpr uint32_t MaxNumHandles = 0;
+    static constexpr uint32_t PrimarySize = 64;
+    static constexpr uint32_t MaxOutOfLine = 0;
+    static constexpr bool HasFlexibleEnvelope = false;
+    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
+        ::fidl::internal::TransactionalMessageKind::kRequest;
+    using ResponseType = UpdatePowerStateMappingResponse;
+  };
+
+  struct GetPowerStateMappingResponse final {
+    FIDL_ALIGNDECL
+    fidl_message_header_t _hdr;
+    Controller_GetPowerStateMapping_Result result;
+
+    static constexpr const fidl_type_t* Type = &fuchsia_device_ControllerGetPowerStateMappingResponseTable;
+    static constexpr uint32_t MaxNumHandles = 0;
+    static constexpr uint32_t PrimarySize = 72;
+    static constexpr uint32_t MaxOutOfLine = 0;
+    static constexpr bool HasFlexibleEnvelope = false;
+    static constexpr ::fidl::internal::TransactionalMessageKind MessageKind =
+        ::fidl::internal::TransactionalMessageKind::kResponse;
+  };
+  using GetPowerStateMappingRequest = ::fidl::AnyZeroArgMessage;
+
   struct SuspendResponse final {
     FIDL_ALIGNDECL
     fidl_message_header_t _hdr;
@@ -1035,6 +1319,38 @@
       using Super::operator*;
     };
     template <typename ResponseType>
+    class UpdatePowerStateMapping_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
+      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
+     public:
+      UpdatePowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::Array<SystemPowerStateInfo, 6> mapping);
+      ~UpdatePowerStateMapping_Impl() = default;
+      UpdatePowerStateMapping_Impl(UpdatePowerStateMapping_Impl&& other) = default;
+      UpdatePowerStateMapping_Impl& operator=(UpdatePowerStateMapping_Impl&& other) = default;
+      using Super::status;
+      using Super::error;
+      using Super::ok;
+      using Super::Unwrap;
+      using Super::value;
+      using Super::operator->;
+      using Super::operator*;
+    };
+    template <typename ResponseType>
+    class GetPowerStateMapping_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
+      using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
+     public:
+      GetPowerStateMapping_Impl(zx::unowned_channel _client_end);
+      ~GetPowerStateMapping_Impl() = default;
+      GetPowerStateMapping_Impl(GetPowerStateMapping_Impl&& other) = default;
+      GetPowerStateMapping_Impl& operator=(GetPowerStateMapping_Impl&& other) = default;
+      using Super::status;
+      using Super::error;
+      using Super::ok;
+      using Super::Unwrap;
+      using Super::value;
+      using Super::operator->;
+      using Super::operator*;
+    };
+    template <typename ResponseType>
     class Suspend_Impl final : private ::fidl::internal::OwnedSyncCallBase<ResponseType> {
       using Super = ::fidl::internal::OwnedSyncCallBase<ResponseType>;
      public:
@@ -1080,6 +1396,8 @@
     using DebugResume = DebugResume_Impl<DebugResumeResponse>;
     using RunCompatibilityTests = RunCompatibilityTests_Impl<RunCompatibilityTestsResponse>;
     using GetDevicePowerCaps = GetDevicePowerCaps_Impl<GetDevicePowerCapsResponse>;
+    using UpdatePowerStateMapping = UpdatePowerStateMapping_Impl<UpdatePowerStateMappingResponse>;
+    using GetPowerStateMapping = GetPowerStateMapping_Impl<GetPowerStateMappingResponse>;
     using Suspend = Suspend_Impl<SuspendResponse>;
     using Resume = Resume_Impl<ResumeResponse>;
   };
@@ -1282,6 +1600,38 @@
       using Super::operator*;
     };
     template <typename ResponseType>
+    class UpdatePowerStateMapping_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
+      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
+     public:
+      UpdatePowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer);
+      ~UpdatePowerStateMapping_Impl() = default;
+      UpdatePowerStateMapping_Impl(UpdatePowerStateMapping_Impl&& other) = default;
+      UpdatePowerStateMapping_Impl& operator=(UpdatePowerStateMapping_Impl&& other) = default;
+      using Super::status;
+      using Super::error;
+      using Super::ok;
+      using Super::Unwrap;
+      using Super::value;
+      using Super::operator->;
+      using Super::operator*;
+    };
+    template <typename ResponseType>
+    class GetPowerStateMapping_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
+      using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
+     public:
+      GetPowerStateMapping_Impl(zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
+      ~GetPowerStateMapping_Impl() = default;
+      GetPowerStateMapping_Impl(GetPowerStateMapping_Impl&& other) = default;
+      GetPowerStateMapping_Impl& operator=(GetPowerStateMapping_Impl&& other) = default;
+      using Super::status;
+      using Super::error;
+      using Super::ok;
+      using Super::Unwrap;
+      using Super::value;
+      using Super::operator->;
+      using Super::operator*;
+    };
+    template <typename ResponseType>
     class Suspend_Impl final : private ::fidl::internal::UnownedSyncCallBase<ResponseType> {
       using Super = ::fidl::internal::UnownedSyncCallBase<ResponseType>;
      public:
@@ -1327,6 +1677,8 @@
     using DebugResume = DebugResume_Impl<DebugResumeResponse>;
     using RunCompatibilityTests = RunCompatibilityTests_Impl<RunCompatibilityTestsResponse>;
     using GetDevicePowerCaps = GetDevicePowerCaps_Impl<GetDevicePowerCapsResponse>;
+    using UpdatePowerStateMapping = UpdatePowerStateMapping_Impl<UpdatePowerStateMappingResponse>;
+    using GetPowerStateMapping = GetPowerStateMapping_Impl<GetPowerStateMappingResponse>;
     using Suspend = Suspend_Impl<SuspendResponse>;
     using Resume = Resume_Impl<ResumeResponse>;
   };
@@ -1452,6 +1804,26 @@
     // Caller provides the backing storage for FIDL message via request and response buffers.
     UnownedResultOf::GetDevicePowerCaps GetDevicePowerCaps(::fidl::BytePart _response_buffer);
 
+    // Updates the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device
+    // Allocates 88 bytes of message buffer on the stack. No heap allocation necessary.
+    ResultOf::UpdatePowerStateMapping UpdatePowerStateMapping(::fidl::Array<SystemPowerStateInfo, 6> mapping);
+
+    // Updates the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device
+    // Caller provides the backing storage for FIDL message via request and response buffers.
+    UnownedResultOf::UpdatePowerStateMapping UpdatePowerStateMapping(::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer);
+
+    // Get the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device.
+    // Allocates 88 bytes of message buffer on the stack. No heap allocation necessary.
+    ResultOf::GetPowerStateMapping GetPowerStateMapping();
+
+    // Get the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device.
+    // Caller provides the backing storage for FIDL message via request and response buffers.
+    UnownedResultOf::GetPowerStateMapping GetPowerStateMapping(::fidl::BytePart _response_buffer);
+
     // Transition this device from a working to a sleep state or from a sleep state to a deeper sleep
     // state. TODO(ravoorir): At the moment, this will call the suspend hook only on this device.
     // In a future change, this api will result in suspend hook being called on all the children and
@@ -1613,6 +1985,26 @@
     // Caller provides the backing storage for FIDL message via request and response buffers.
     static UnownedResultOf::GetDevicePowerCaps GetDevicePowerCaps(zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
 
+    // Updates the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device
+    // Allocates 88 bytes of message buffer on the stack. No heap allocation necessary.
+    static ResultOf::UpdatePowerStateMapping UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::Array<SystemPowerStateInfo, 6> mapping);
+
+    // Updates the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device
+    // Caller provides the backing storage for FIDL message via request and response buffers.
+    static UnownedResultOf::UpdatePowerStateMapping UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart _request_buffer, ::fidl::Array<SystemPowerStateInfo, 6> mapping, ::fidl::BytePart _response_buffer);
+
+    // Get the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device.
+    // Allocates 88 bytes of message buffer on the stack. No heap allocation necessary.
+    static ResultOf::GetPowerStateMapping GetPowerStateMapping(zx::unowned_channel _client_end);
+
+    // Get the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device.
+    // Caller provides the backing storage for FIDL message via request and response buffers.
+    static UnownedResultOf::GetPowerStateMapping GetPowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart _response_buffer);
+
     // Transition this device from a working to a sleep state or from a sleep state to a deeper sleep
     // state. TODO(ravoorir): At the moment, this will call the suspend hook only on this device.
     // In a future change, this api will result in suspend hook being called on all the children and
@@ -1706,6 +2098,14 @@
     // to manage power for this device.
     static ::fidl::DecodeResult<GetDevicePowerCapsResponse> GetDevicePowerCaps(zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);
 
+    // Updates the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device
+    static ::fidl::DecodeResult<UpdatePowerStateMappingResponse> UpdatePowerStateMapping(zx::unowned_channel _client_end, ::fidl::DecodedMessage<UpdatePowerStateMappingRequest> params, ::fidl::BytePart response_buffer);
+
+    // Get the mapping between system power states to device power states. Used by the system
+    // wide power manager to manage power for this device.
+    static ::fidl::DecodeResult<GetPowerStateMappingResponse> GetPowerStateMapping(zx::unowned_channel _client_end, ::fidl::BytePart response_buffer);
+
     // Transition this device from a working to a sleep state or from a sleep state to a deeper sleep
     // state. TODO(ravoorir): At the moment, this will call the suspend hook only on this device.
     // In a future change, this api will result in suspend hook being called on all the children and
@@ -1903,6 +2303,34 @@
 
     virtual void GetDevicePowerCaps(GetDevicePowerCapsCompleter::Sync _completer) = 0;
 
+    class UpdatePowerStateMappingCompleterBase : public _Base {
+     public:
+      void Reply(Controller_UpdatePowerStateMapping_Result result);
+      void Reply(::fidl::BytePart _buffer, Controller_UpdatePowerStateMapping_Result result);
+      void Reply(::fidl::DecodedMessage<UpdatePowerStateMappingResponse> params);
+
+     protected:
+      using ::fidl::CompleterBase::CompleterBase;
+    };
+
+    using UpdatePowerStateMappingCompleter = ::fidl::Completer<UpdatePowerStateMappingCompleterBase>;
+
+    virtual void UpdatePowerStateMapping(::fidl::Array<SystemPowerStateInfo, 6> mapping, UpdatePowerStateMappingCompleter::Sync _completer) = 0;
+
+    class GetPowerStateMappingCompleterBase : public _Base {
+     public:
+      void Reply(Controller_GetPowerStateMapping_Result result);
+      void Reply(::fidl::BytePart _buffer, Controller_GetPowerStateMapping_Result result);
+      void Reply(::fidl::DecodedMessage<GetPowerStateMappingResponse> params);
+
+     protected:
+      using ::fidl::CompleterBase::CompleterBase;
+    };
+
+    using GetPowerStateMappingCompleter = ::fidl::Completer<GetPowerStateMappingCompleterBase>;
+
+    virtual void GetPowerStateMapping(GetPowerStateMappingCompleter::Sync _completer) = 0;
+
     class SuspendCompleterBase : public _Base {
      public:
       void Reply(int32_t status, DevicePowerState out_state);
@@ -1953,29 +2381,6 @@
 
 };
 
-// Signal that will be active on a device event handle if the device's write() method
-// will accept data.
-constexpr uint32_t DEVICE_SIGNAL_WRITABLE = 67108864u;
-
-// Signal that will be active on a device event handle if the device's read() method
-// will return data.
-constexpr uint32_t DEVICE_SIGNAL_READABLE = 16777216u;
-
-// Signal that will be active on a device event handle if the device has some out-of-band
-// mechanism that needs attention.
-// This is primarily used by the PTY support.
-constexpr uint32_t DEVICE_SIGNAL_OOB = 33554432u;
-
-// Signal that will be active on a device event handle if the device has been disconnected.
-// This is primarily used by the PTY support.
-constexpr uint32_t DEVICE_SIGNAL_HANGUP = 268435456u;
-
-// Signal that will be active on a device event handle if the device has encountered an error.
-// This is primarily used by the PTY support.
-constexpr uint32_t DEVICE_SIGNAL_ERROR = 134217728u;
-
-extern const char DEFAULT_DEVICE_NAME[];
-
 }  // namespace device
 }  // namespace fuchsia
 }  // namespace llcpp
@@ -2001,6 +2406,24 @@
 static_assert(offsetof(::llcpp::fuchsia::device::NameProvider::GetDeviceNameResponse, result) == 16);
 
 template <>
+struct IsFidlType<::llcpp::fuchsia::device::SystemPowerStateInfo> : public std::true_type {};
+static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::SystemPowerStateInfo>);
+static_assert(offsetof(::llcpp::fuchsia::device::SystemPowerStateInfo, suspend_flag) == 0);
+static_assert(offsetof(::llcpp::fuchsia::device::SystemPowerStateInfo, wakeup_enable) == 4);
+static_assert(offsetof(::llcpp::fuchsia::device::SystemPowerStateInfo, dev_state) == 5);
+static_assert(sizeof(::llcpp::fuchsia::device::SystemPowerStateInfo) == ::llcpp::fuchsia::device::SystemPowerStateInfo::PrimarySize);
+
+template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Response> : public std::true_type {};
+static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Response>);
+static_assert(offsetof(::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Response, mapping) == 0);
+static_assert(sizeof(::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Response) == ::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Response::PrimarySize);
+
+template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result> : public std::true_type {};
+static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::Controller_GetPowerStateMapping_Result>);
+
+template <>
 struct IsFidlType<::llcpp::fuchsia::device::DevicePowerStateInfo> : public std::true_type {};
 static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::DevicePowerStateInfo>);
 static_assert(offsetof(::llcpp::fuchsia::device::DevicePowerStateInfo, state_id) == 0);
@@ -2031,6 +2454,16 @@
 static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::Controller_Resume_Result>);
 
 template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Response> : public std::true_type {};
+static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Response>);
+static_assert(offsetof(::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Response, __reserved) == 0);
+static_assert(sizeof(::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Response) == ::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Response::PrimarySize);
+
+template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result> : public std::true_type {};
+static_assert(std::is_standard_layout_v<::llcpp::fuchsia::device::Controller_UpdatePowerStateMapping_Result>);
+
+template <>
 struct IsFidlType<::llcpp::fuchsia::device::Controller::BindRequest> : public std::true_type {};
 template <>
 struct IsFidlMessage<::llcpp::fuchsia::device::Controller::BindRequest> : public std::true_type {};
@@ -2156,6 +2589,30 @@
 static_assert(offsetof(::llcpp::fuchsia::device::Controller::GetDevicePowerCapsResponse, result) == 16);
 
 template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingRequest> : public std::true_type {};
+template <>
+struct IsFidlMessage<::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingRequest> : public std::true_type {};
+static_assert(sizeof(::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingRequest)
+    == ::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingRequest::PrimarySize);
+static_assert(offsetof(::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingRequest, mapping) == 16);
+
+template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingResponse> : public std::true_type {};
+template <>
+struct IsFidlMessage<::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingResponse> : public std::true_type {};
+static_assert(sizeof(::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingResponse)
+    == ::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingResponse::PrimarySize);
+static_assert(offsetof(::llcpp::fuchsia::device::Controller::UpdatePowerStateMappingResponse, result) == 16);
+
+template <>
+struct IsFidlType<::llcpp::fuchsia::device::Controller::GetPowerStateMappingResponse> : public std::true_type {};
+template <>
+struct IsFidlMessage<::llcpp::fuchsia::device::Controller::GetPowerStateMappingResponse> : public std::true_type {};
+static_assert(sizeof(::llcpp::fuchsia::device::Controller::GetPowerStateMappingResponse)
+    == ::llcpp::fuchsia::device::Controller::GetPowerStateMappingResponse::PrimarySize);
+static_assert(offsetof(::llcpp::fuchsia::device::Controller::GetPowerStateMappingResponse, result) == 16);
+
+template <>
 struct IsFidlType<::llcpp::fuchsia::device::Controller::SuspendRequest> : public std::true_type {};
 template <>
 struct IsFidlMessage<::llcpp::fuchsia::device::Controller::SuspendRequest> : public std::true_type {};