From 7de6b410305fcfcd34078e62fbe0ceedb43663f9 Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 30 Dec 2023 20:51:23 -0500 Subject: service: split am into components --- src/core/hle/service/am/self_controller.cpp | 438 ++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 src/core/hle/service/am/self_controller.cpp (limited to 'src/core/hle/service/am/self_controller.cpp') diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp new file mode 100644 index 000000000..0f495c871 --- /dev/null +++ b/src/core/hle/service/am/self_controller.cpp @@ -0,0 +1,438 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/self_controller.h" +#include "core/hle/service/caps/caps_su.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" +#include "core/hle/service/nvnflinger/nvnflinger.h" +#include "core/hle/service/sm/sm.h" +#include "core/hle/service/vi/vi_results.h" + +namespace Service::AM { + +ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, + service_context{system, "ISelfController"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ISelfController::Exit, "Exit"}, + {1, &ISelfController::LockExit, "LockExit"}, + {2, &ISelfController::UnlockExit, "UnlockExit"}, + {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, + {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, + {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, + {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, + {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, + {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, + {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, + {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, + {15, nullptr, "SetScreenShotAppletIdentityInfo"}, + {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, + {17, nullptr, "SetControllerFirmwareUpdateSection"}, + {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, + {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, + {20, nullptr, "SetDesirableKeyboardLayout"}, + {21, nullptr, "GetScreenShotProgramId"}, + {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, + {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"}, + {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"}, + {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"}, + {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, + {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, + {46, nullptr, "SetRecordingLayerCompositionEnabled"}, + {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, + {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"}, + {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, + {61, nullptr, "SetMediaPlaybackState"}, + {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, + {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, + {64, nullptr, "SetInputDetectionSourceSet"}, + {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"}, + {66, nullptr, "GetCurrentIlluminance"}, + {67, nullptr, "IsIlluminanceAvailable"}, + {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, + {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, + {70, nullptr, "ReportMultimediaError"}, + {71, nullptr, "GetCurrentIlluminanceEx"}, + {72, nullptr, "SetInputDetectionPolicy"}, + {80, nullptr, "SetWirelessPriorityMode"}, + {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"}, + {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, + {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, + {110, nullptr, "SetApplicationAlbumUserData"}, + {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, + {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"}, + {1000, nullptr, "GetDebugStorageChannel"}, + }; + // clang-format on + + RegisterHandlers(functions); + + launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); + + // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is + // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple + // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not + // suspended if the event has previously been created by a call to + // GetAccumulatedSuspendedTickChangedEvent. + + accumulated_suspended_tick_changed_event = + service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); + accumulated_suspended_tick_changed_event->Signal(); +} + +ISelfController::~ISelfController() { + service_context.CloseEvent(launchable_event); + service_context.CloseEvent(accumulated_suspended_tick_changed_event); +} + +void ISelfController::Exit(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + + system.Exit(); +} + +void ISelfController::LockExit(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + system.SetExitLocked(true); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::UnlockExit(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + system.SetExitLocked(false); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + + if (system.GetExitRequested()) { + system.Exit(); + } +} + +void ISelfController::EnterFatalSection(HLERequestContext& ctx) { + ++num_fatal_sections_entered; + LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called."); + + // Entry and exit of fatal sections must be balanced. + if (num_fatal_sections_entered == 0) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(Result{ErrorModule::AM, 512}); + return; + } + + --num_fatal_sections_entered; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + launchable_event->Signal(); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(launchable_event->GetReadableEvent()); +} + +void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto permission = rp.PopEnum(); + LOG_DEBUG(Service_AM, "called, permission={}", permission); + + screenshot_permission = permission; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + bool flag = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + bool flag = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { + // Takes 3 input u8s with each field located immediately after the previous + // u8, these are bool flags. No output. + IPC::RequestParser rp{ctx}; + + struct FocusHandlingModeParams { + u8 unknown0; + u8 unknown1; + u8 unknown2; + }; + const auto flags = rp.PopRaw(); + + LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", + flags.unknown0, flags.unknown1, flags.unknown2); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { + // Takes 3 input u8s with each field located immediately after the previous + // u8, these are bool flags. No output. + IPC::RequestParser rp{ctx}; + + bool enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO(Subv): Find out how AM determines the display to use, for now just + // create the layer in the Default display. + const auto display_id = nvnflinger.OpenDisplay("Default"); + const auto layer_id = nvnflinger.CreateLayer(*display_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(*layer_id); +} + +void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); +} + +void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); + rb.Push(system_shared_buffer_id); + rb.Push(system_shared_layer_id); +} + +void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); + rb.Push(system_shared_buffer_id); +} + +Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { + if (buffer_sharing_enabled) { + return ResultSuccess; + } + + if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { + return VI::ResultOperationFailed; + } + + const auto display_id = nvnflinger.OpenDisplay("Default"); + const auto result = nvnflinger.GetSystemBufferManager().Initialize( + &system_shared_buffer_id, &system_shared_layer_id, *display_id); + + if (result.IsSuccess()) { + buffer_sharing_enabled = true; + } + + return result; +} + +void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + // TODO(Subv): Find out how AM determines the display to use, for now just + // create the layer in the Default display. + // This calls nn::vi::CreateRecordingLayer() which creates another layer. + // Currently we do not support more than 1 layer per display, output 1 layer id for now. + // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse + // side effects. + // TODO: Support multiple layers + const auto display_id = nvnflinger.OpenDisplay("Default"); + const auto layer_id = nvnflinger.CreateLayer(*display_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(*layer_id); +} + +void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + idle_time_detection_extension = rp.Pop(); + LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", + idle_time_detection_extension); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(idle_time_detection_extension); +} + +void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + is_auto_sleep_disabled = rp.Pop(); + + // On the system itself, if the previous state of is_auto_sleep_disabled + // differed from the current value passed in, it'd signify the internal + // window manager to update (and also increment some statistics like update counts) + // + // It'd also indicate this change to an idle handling context. + // + // However, given we're emulating this behavior, most of this can be ignored + // and it's sufficient to simply set the member variable for querying via + // IsAutoSleepDisabled(). + + LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called."); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(is_auto_sleep_disabled); +} + +void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called."); + + // This command returns the total number of system ticks since ISelfController creation + // where the game was suspended. Since Yuzu doesn't implement game suspension, this command + // can just always return 0 ticks. + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(ResultSuccess); + rb.Push(0); +} + +void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called."); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); +} + +void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + // This service call sets an internal flag whether a notification is shown when an image is + // captured. Currently we do not support capturing images via the capture button, so this can be + // stubbed for now. + const bool album_image_taken_notification_enabled = rp.Pop(); + + LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", + album_image_taken_notification_enabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto report_option = rp.PopEnum(); + + LOG_INFO(Service_AM, "called, report_option={}", report_option); + + const auto screenshot_service = + system.ServiceManager().GetService( + "caps:su"); + + if (screenshot_service) { + screenshot_service->CaptureAndSaveScreenshot(report_option); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + const auto is_record_volume_muted = rp.Pop(); + + LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +} // namespace Service::AM -- cgit v1.2.3 From dfb9fa0144ca79e596f6f2b1bc960b1a44745aa6 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 31 Dec 2023 09:40:32 -0500 Subject: am: re-namespace frontend applets to frontend directory --- src/core/hle/service/am/self_controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/am/self_controller.cpp') diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index 0f495c871..d5de1bb2f 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/am/self_controller.h" #include "core/hle/service/caps/caps_su.h" #include "core/hle/service/ipc_helpers.h" @@ -271,7 +271,7 @@ Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { return ResultSuccess; } - if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) { + if (system.GetFrontendAppletHolder().GetCurrentAppletId() <= AppletId::Application) { return VI::ResultOperationFailed; } -- cgit v1.2.3 From 182137a9a4b09c8188d2cbffa312550c5dc83641 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 2 Jan 2024 18:29:03 -0500 Subject: am: migrate global state to per-applet state structure --- src/core/hle/service/am/self_controller.cpp | 187 +++++++++++++++------------- 1 file changed, 97 insertions(+), 90 deletions(-) (limited to 'src/core/hle/service/am/self_controller.cpp') diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index d5de1bb2f..3ac967b4d 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/service/am/am_results.h" #include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/am/self_controller.h" #include "core/hle/service/caps/caps_su.h" @@ -12,9 +13,10 @@ namespace Service::AM { -ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) - : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, - service_context{system, "ISelfController"} { +ISelfController::ISelfController(Core::System& system_, std::shared_ptr applet_, + Nvnflinger::Nvnflinger& nvnflinger_) + : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move( + applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ISelfController::Exit, "Exit"}, @@ -69,24 +71,9 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& // clang-format on RegisterHandlers(functions); - - launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent"); - - // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is - // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple - // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not - // suspended if the event has previously been created by a call to - // GetAccumulatedSuspendedTickChangedEvent. - - accumulated_suspended_tick_changed_event = - service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent"); - accumulated_suspended_tick_changed_event->Signal(); } -ISelfController::~ISelfController() { - service_context.CloseEvent(launchable_event); - service_context.CloseEvent(accumulated_suspended_tick_changed_event); -} +ISelfController::~ISelfController() = default; void ISelfController::Exit(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); @@ -94,6 +81,7 @@ void ISelfController::Exit(HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); + // TODO system.Exit(); } @@ -120,8 +108,10 @@ void ISelfController::UnlockExit(HLERequestContext& ctx) { } void ISelfController::EnterFatalSection(HLERequestContext& ctx) { - ++num_fatal_sections_entered; - LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); + + std::scoped_lock lk{applet->lock}; + applet->fatal_section_count++; + LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -131,13 +121,14 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); // Entry and exit of fatal sections must be balanced. - if (num_fatal_sections_entered == 0) { + std::scoped_lock lk{applet->lock}; + if (applet->fatal_section_count == 0) { IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(Result{ErrorModule::AM, 512}); + rb.Push(AM::ResultFatalSectionCountImbalance); return; } - --num_fatal_sections_entered; + applet->fatal_section_count--; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -146,11 +137,11 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) { void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - launchable_event->Signal(); + applet->library_applet_launchable_event.Signal(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(launchable_event->GetReadableEvent()); + rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle()); } void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { @@ -158,7 +149,8 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { const auto permission = rp.PopEnum(); LOG_DEBUG(Service_AM, "called, permission={}", permission); - screenshot_permission = permission; + std::scoped_lock lk{applet->lock}; + applet->screenshot_permission = permission; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -167,8 +159,11 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) { void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - bool flag = rp.Pop(); - LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + const bool notification_enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); + + std::scoped_lock lk{applet->lock}; + applet->operation_mode_changed_notification_enabled = notification_enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -177,28 +172,27 @@ void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - bool flag = rp.Pop(); - LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); + const bool notification_enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled); + + std::scoped_lock lk{applet->lock}; + applet->performance_mode_changed_notification_enabled = notification_enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous - // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; - struct FocusHandlingModeParams { - u8 unknown0; - u8 unknown1; - u8 unknown2; - }; - const auto flags = rp.PopRaw(); + const auto flags = rp.PopRaw(); LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}", flags.unknown0, flags.unknown1, flags.unknown2); + std::scoped_lock lk{applet->lock}; + applet->focus_handling_mode = flags; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -206,24 +200,35 @@ void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) { void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + applet->restart_message_enabled = true; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous - // u8, these are bool flags. No output. IPC::RequestParser rp{ctx}; - bool enabled = rp.Pop(); + const bool enabled = rp.Pop(); LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); + std::scoped_lock lk{applet->lock}; + ASSERT(applet->type == AppletType::Application); + applet->out_of_focus_suspension_enabled = enabled; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + const auto orientation = rp.PopRaw(); + LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast(orientation)); + + std::scoped_lock lk{applet->lock}; + applet->album_image_orientation = orientation; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -232,14 +237,13 @@ void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) { void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto layer_id = nvnflinger.CreateLayer(*display_id); + u64 layer_id{}; + applet->managed_layer_holder.Initialize(&nvnflinger); + applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(*layer_id); + rb.Push(layer_id); } void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { @@ -252,56 +256,46 @@ void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) { void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + u64 buffer_id, layer_id; + applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push(system_shared_buffer_id); - rb.Push(system_shared_layer_id); + rb.Push(buffer_id); + rb.Push(layer_id); } void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + u64 buffer_id, layer_id; + applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess())); - rb.Push(system_shared_buffer_id); + rb.Push(buffer_id); } Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) { - if (buffer_sharing_enabled) { + if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) { return ResultSuccess; } - if (system.GetFrontendAppletHolder().GetCurrentAppletId() <= AppletId::Application) { - return VI::ResultOperationFailed; - } - - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto result = nvnflinger.GetSystemBufferManager().Initialize( - &system_shared_buffer_id, &system_shared_layer_id, *display_id); - - if (result.IsSuccess()) { - buffer_sharing_enabled = true; - } - - return result; + return VI::ResultOperationFailed; } void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); - // TODO(Subv): Find out how AM determines the display to use, for now just - // create the layer in the Default display. - // This calls nn::vi::CreateRecordingLayer() which creates another layer. - // Currently we do not support more than 1 layer per display, output 1 layer id for now. - // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse - // side effects. - // TODO: Support multiple layers - const auto display_id = nvnflinger.OpenDisplay("Default"); - const auto layer_id = nvnflinger.CreateLayer(*display_id); + u64 layer_id{}; + u64 recording_layer_id{}; + applet->managed_layer_holder.Initialize(&nvnflinger); + applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id); - IPC::ResponseBuilder rb{ctx, 4}; + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(ResultSuccess); - rb.Push(*layer_id); + rb.Push(layer_id); + rb.Push(recording_layer_id); } void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { @@ -320,9 +314,12 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) { void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - idle_time_detection_extension = rp.Pop(); - LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", - idle_time_detection_extension); + + const auto extension = rp.PopRaw(); + LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension); + + std::scoped_lock lk{applet->lock}; + applet->idle_time_detection_extension = extension; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -331,9 +328,11 @@ void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(idle_time_detection_extension); + rb.PushRaw(applet->idle_time_detection_extension); } void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { @@ -345,7 +344,9 @@ void ISelfController::ReportUserIsActive(HLERequestContext& ctx) { void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - is_auto_sleep_disabled = rp.Pop(); + + std::scoped_lock lk{applet->lock}; + applet->auto_sleep_disabled = rp.Pop(); // On the system itself, if the previous state of is_auto_sleep_disabled // differed from the current value passed in, it'd signify the internal @@ -357,7 +358,7 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { // and it's sufficient to simply set the member variable for querying via // IsAutoSleepDisabled(). - LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); + LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -366,20 +367,23 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) { void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); + std::scoped_lock lk{applet->lock}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(is_auto_sleep_disabled); + rb.Push(applet->auto_sleep_disabled); } void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); + std::scoped_lock lk{applet->lock}; // This command returns the total number of system ticks since ISelfController creation // where the game was suspended. Since Yuzu doesn't implement game suspension, this command // can just always return 0 ticks. IPC::ResponseBuilder rb{ctx, 4}; rb.Push(ResultSuccess); - rb.Push(0); + rb.Push(applet->suspended_ticks); } void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) { @@ -387,7 +391,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(ResultSuccess); - rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent()); + rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle()); } void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) { @@ -396,10 +400,11 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c // This service call sets an internal flag whether a notification is shown when an image is // captured. Currently we do not support capturing images via the capture button, so this can be // stubbed for now. - const bool album_image_taken_notification_enabled = rp.Pop(); + const bool enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}", - album_image_taken_notification_enabled); + std::scoped_lock lk{applet->lock}; + applet->album_image_taken_notification_enabled = enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); @@ -427,9 +432,11 @@ void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto is_record_volume_muted = rp.Pop(); + const auto enabled = rp.Pop(); + LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled); - LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted); + std::scoped_lock lk{applet->lock}; + applet->record_volume_muted = enabled; IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); -- cgit v1.2.3 From 68303ed6016da0926df8b62e5a0c55c9b914f927 Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 6 Jan 2024 21:21:01 -0500 Subject: core: support offline web applet --- src/core/hle/service/am/self_controller.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service/am/self_controller.cpp') diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp index 3ac967b4d..0289f5cf1 100644 --- a/src/core/hle/service/am/self_controller.cpp +++ b/src/core/hle/service/am/self_controller.cpp @@ -30,7 +30,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"}, {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, - {15, nullptr, "SetScreenShotAppletIdentityInfo"}, + {15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"}, {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, {17, nullptr, "SetControllerFirmwareUpdateSection"}, {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, @@ -207,6 +207,17 @@ void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + std::scoped_lock lk{applet->lock}; + applet->screen_shot_identity = rp.PopRaw(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; -- cgit v1.2.3