summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/am/self_controller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/am/self_controller.cpp')
-rw-r--r--src/core/hle/service/am/self_controller.cpp187
1 files changed, 97 insertions, 90 deletions
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> 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<ScreenshotPermission>();
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<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
+ const bool notification_enabled = rp.Pop<bool>();
+ 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<bool>();
- LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
+ const bool notification_enabled = rp.Pop<bool>();
+ 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<FocusHandlingModeParams>();
+ const auto flags = rp.PopRaw<FocusHandlingMode>();
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<bool>();
+ const bool enabled = rp.Pop<bool>();
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<Capture::AlbumImageOrientation>();
+ LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(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<s64>(system_shared_buffer_id);
- rb.Push<s64>(system_shared_layer_id);
+ rb.Push<s64>(buffer_id);
+ rb.Push<s64>(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<s64>(system_shared_buffer_id);
+ rb.Push<s64>(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<u32>();
- LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
- idle_time_detection_extension);
+
+ const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
+ 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<u32>(idle_time_detection_extension);
+ rb.PushRaw<IdleTimeDetectionExtension>(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<bool>();
+
+ std::scoped_lock lk{applet->lock};
+ applet->auto_sleep_disabled = rp.Pop<bool>();
// 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<u64>(0);
+ rb.Push<u64>(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<bool>();
+ const bool enabled = rp.Pop<bool>();
+ 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<bool>();
+ const auto enabled = rp.Pop<bool>();
+ 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);