am: implement basic WindowSystem behavior

This commit is contained in:
Liam 2024-02-12 10:09:40 -05:00
parent 26cb7c922a
commit c623e7a86d
16 changed files with 469 additions and 51 deletions

View File

@ -492,6 +492,8 @@ add_library(core STATIC
hle/service/am/service/system_applet_proxy.h
hle/service/am/service/window_controller.cpp
hle/service/am/service/window_controller.h
hle/service/am/window_system.cpp
hle/service/am/window_system.h
hle/service/aoc/addon_content_manager.cpp
hle/service/aoc/addon_content_manager.h
hle/service/aoc/purchase_event_manager.cpp

View File

@ -6,13 +6,15 @@
#include "core/hle/service/am/event_observer.h"
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
#include "core/hle/service/am/service/application_proxy_service.h"
#include "core/hle/service/am/window_system.h"
#include "core/hle/service/server_manager.h"
namespace Service::AM {
void LoopProcess(Core::System& system) {
ButtonPoller button_poller(system);
EventObserver event_observer(system);
WindowSystem window_system(system);
ButtonPoller button_poller(system, window_system);
EventObserver event_observer(system, window_system);
auto server_manager = std::make_unique<ServerManager>(system);

View File

@ -233,7 +233,6 @@ struct ApplicationPlayStatistics {
static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
"ApplicationPlayStatistics has incorrect size.");
using AppletResourceUserId = u64;
using ProgramId = u64;
struct Applet;

View File

@ -16,7 +16,7 @@ Applet::Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_
library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context),
sleep_lock_event(context), state_changed_event(context) {
aruid = process->GetProcessId();
aruid.pid = process->GetProcessId();
program_id = process->GetProgramId();
}
@ -27,18 +27,19 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) {
lifecycle_manager.RemoveForceResumeIfPossible();
// Check if we're runnable.
const bool is_runnable = lifecycle_manager.IsRunnable();
const bool was_running = running;
const bool curr_activity_runnable = lifecycle_manager.IsRunnable();
const bool prev_activity_runnable = is_activity_runnable;
const bool was_changed = curr_activity_runnable != prev_activity_runnable;
if (is_runnable != was_running) {
if (is_runnable) {
if (was_changed) {
if (curr_activity_runnable) {
process->Suspend(false);
} else {
process->Suspend(true);
lifecycle_manager.RequestResumeNotification();
}
running = is_runnable;
is_activity_runnable = curr_activity_runnable;
}
if (lifecycle_manager.GetForcedSuspend()) {
@ -47,8 +48,7 @@ void Applet::UpdateSuspensionStateLocked(bool force_message) {
}
// Signal if the focus state was changed or the process state was changed.
if (lifecycle_manager.UpdateRequestedFocusState() || is_runnable != was_running ||
force_message) {
if (lifecycle_manager.UpdateRequestedFocusState() || was_changed || force_message) {
lifecycle_manager.SignalSystemEventIfNeeded();
}
}
@ -60,10 +60,7 @@ void Applet::SetInteractibleLocked(bool interactible) {
is_interactible = interactible;
const bool new_state =
window_visible && is_interactible && !lifecycle_manager.GetExitRequested();
display_layer_manager.SetWindowVisibility(new_state);
hid_registration.EnableAppletToGetInput(new_state);
hid_registration.EnableAppletToGetInput(interactible && !lifecycle_manager.GetExitRequested());
}
void Applet::OnProcessTerminatedLocked() {

View File

@ -9,6 +9,7 @@
#include "common/math_util.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/os/event.h"
#include "core/hle/service/os/process.h"
@ -38,6 +39,7 @@ struct Applet {
// Process
std::unique_ptr<Process> process;
std::optional<ProcessHolder> process_holder;
bool is_process_running{};
// Creation state
AppletId applet_id{};
@ -78,7 +80,6 @@ struct Applet {
bool game_play_recording_supported{};
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
bool jit_service_launched{};
bool is_running{};
bool application_crash_report_enabled{};
// Common state
@ -95,6 +96,7 @@ struct Applet {
// Caller applet
std::weak_ptr<Applet> caller_applet{};
std::shared_ptr<AppletDataBroker> caller_applet_broker{};
std::list<std::shared_ptr<Applet>> child_applets{};
bool is_completed{};
// Self state
@ -108,7 +110,7 @@ struct Applet {
u64 suspended_ticks{};
bool album_image_taken_notification_enabled{};
bool record_volume_muted{};
bool running{};
bool is_activity_runnable{};
bool is_interactible{true};
bool window_visible{true};

View File

@ -232,10 +232,10 @@ AppletManager::~AppletManager() {
void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) {
std::scoped_lock lk{m_lock};
m_applets.emplace(applet->aruid, std::move(applet));
m_applets.emplace(applet->aruid.pid, std::move(applet));
}
void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
void AppletManager::TerminateAndRemoveApplet(u64 aruid) {
std::shared_ptr<Applet> applet;
bool should_stop = false;
{
@ -267,13 +267,13 @@ void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
}
void AppletManager::CreateAndInsertByFrontendAppletParameters(
AppletResourceUserId aruid, const FrontendAppletParameters& params) {
u64 aruid, const FrontendAppletParameters& params) {
// TODO: this should be run inside AM so that the events will have a parent process
// TODO: have am create the guest process
auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system),
params.applet_id == AppletId::Application);
applet->aruid = aruid;
applet->aruid.pid = aruid;
applet->program_id = params.program_id;
applet->applet_id = params.applet_id;
applet->type = params.applet_type;
@ -333,7 +333,7 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
this->InsertApplet(std::move(applet));
}
std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const {
std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(u64 aruid) const {
std::scoped_lock lk{m_lock};
if (const auto it = m_applets.find(aruid); it != m_applets.end()) {

View File

@ -34,11 +34,11 @@ public:
~AppletManager();
void InsertApplet(std::shared_ptr<Applet> applet);
void TerminateAndRemoveApplet(AppletResourceUserId aruid);
void TerminateAndRemoveApplet(u64 aruid);
void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid,
void CreateAndInsertByFrontendAppletParameters(u64 aruid,
const FrontendAppletParameters& params);
std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const;
std::shared_ptr<Applet> GetByAppletResourceUserId(u64 aruid) const;
void Reset();
@ -50,7 +50,7 @@ private:
Core::System& m_system;
mutable std::mutex m_lock{};
std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{};
std::map<u64, std::shared_ptr<Applet>> m_applets{};
// AudioController state goes here
};

View File

@ -3,6 +3,7 @@
#include "core/core.h"
#include "core/hle/service/am/button_poller.h"
#include "core/hle/service/am/window_system.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
@ -11,14 +12,7 @@ namespace Service::AM {
namespace {
enum class ButtonPressDuration {
ShortPressing,
MiddlePressing,
LongPressing,
};
[[maybe_unused]] ButtonPressDuration ClassifyPressDuration(
std::chrono::steady_clock::time_point start) {
ButtonPressDuration ClassifyPressDuration(std::chrono::steady_clock::time_point start) {
using namespace std::chrono_literals;
const auto dur = std::chrono::steady_clock::now() - start;
@ -36,7 +30,8 @@ enum class ButtonPressDuration {
} // namespace
ButtonPoller::ButtonPoller(Core::System& system) {
ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system)
: m_window_system(window_system) {
// TODO: am reads this from the home button state in hid, which is controller-agnostic.
Core::HID::ControllerUpdateCallback engine_callback{
.on_change =
@ -78,7 +73,7 @@ void ButtonPoller::OnButtonStateChanged() {
// Buttons released which were previously held
if (!home_button && m_home_button_press_start) {
// TODO
m_window_system.OnHomeButtonPressed(ClassifyPressDuration(*m_home_button_press_start));
m_home_button_press_start = std::nullopt;
}
if (!capture_button && m_capture_button_press_start) {

View File

@ -17,15 +17,19 @@ class System;
namespace Service::AM {
class WindowSystem;
class ButtonPoller {
public:
explicit ButtonPoller(Core::System& system);
explicit ButtonPoller(Core::System& system, WindowSystem& window_system);
~ButtonPoller();
private:
void OnButtonStateChanged();
private:
WindowSystem& m_window_system;
Core::HID::EmulatedController* m_handheld{};
int m_handheld_key{};
Core::HID::EmulatedController* m_player1{};

View File

@ -5,6 +5,7 @@
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/event_observer.h"
#include "core/hle/service/am/window_system.h"
namespace Service::AM {
@ -13,9 +14,10 @@ enum class UserDataTag : u32 {
AppletProcess,
};
EventObserver::EventObserver(Core::System& system)
: m_system(system), m_context(system, "am:EventObserver"), m_wakeup_event(m_context),
m_wakeup_holder(m_wakeup_event.GetHandle()) {
EventObserver::EventObserver(Core::System& system, WindowSystem& window_system)
: m_system(system), m_context(system, "am:EventObserver"), m_window_system(window_system),
m_wakeup_event(m_context), m_wakeup_holder(m_wakeup_event.GetHandle()) {
m_window_system.SetEventObserver(this);
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait));
m_thread = std::thread([&] { this->ThreadFunc(); });
@ -107,15 +109,16 @@ void EventObserver::OnWakeupEvent(MultiWaitHolder* holder) {
m_wakeup_event.Clear();
// Perform recalculation.
// TODO
m_window_system.Update();
}
void EventObserver::OnProcessEvent(ProcessHolder* holder) {
// Check process state.
auto& applet = holder->GetApplet();
auto& process = holder->GetProcess();
{
std::scoped_lock lk{m_lock};
std::scoped_lock lk{m_lock, applet.lock};
if (process.IsTerminated()) {
// Destroy the holder.
this->DestroyAppletProcessHolderLocked(holder);
@ -126,10 +129,13 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) {
// Relink wakeup event.
holder->LinkToMultiWait(std::addressof(m_deferred_wait_list));
}
// Set running.
applet.is_process_running = process.IsRunning();
}
// Perform recalculation.
// TODO
m_window_system.Update();
}
void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) {

View File

@ -17,10 +17,11 @@ namespace Service::AM {
struct Applet;
class ProcessHolder;
class WindowSystem;
class EventObserver {
public:
explicit EventObserver(Core::System& system);
explicit EventObserver(Core::System& system, WindowSystem& window_system);
~EventObserver();
void TrackAppletProcess(Applet& applet);
@ -48,6 +49,9 @@ private:
Core::System& m_system;
KernelHelpers::ServiceContext m_context;
// Window manager.
WindowSystem& m_window_system;
// Guest event handle to wake up the event loop processor.
Event m_wakeup_event;
MultiWaitHolder m_wakeup_holder;

View File

@ -176,7 +176,7 @@ Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId
Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
LOG_INFO(Service_AM, "called");
system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid.pid);
R_SUCCEED();
}

View File

@ -0,0 +1,305 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/event_observer.h"
#include "core/hle/service/am/window_system.h"
namespace Service::AM {
WindowSystem::WindowSystem(Core::System& system) : m_system(system) {}
WindowSystem::~WindowSystem() {}
void WindowSystem::Update() {
std::scoped_lock lk{m_lock};
// Loop through all applets and remove terminated applets.
this->PruneTerminatedAppletsLocked();
// If the home menu is being locked into the foreground, handle that.
if (this->LockHomeMenuIntoForegroundLocked()) {
return;
}
// Recursively update each applet root.
this->UpdateAppletStateLocked(m_home_menu, m_foreground_requested_applet == m_home_menu);
this->UpdateAppletStateLocked(m_application, m_foreground_requested_applet == m_application);
}
void WindowSystem::TrackApplet(std::shared_ptr<Applet> applet, bool is_application) {
std::scoped_lock lk{m_lock};
if (applet->applet_id == AppletId::QLaunch) {
ASSERT(m_home_menu == nullptr);
m_home_menu = applet.get();
} else if (is_application) {
ASSERT(m_application == nullptr);
m_application = applet.get();
}
m_event_observer->TrackAppletProcess(*applet);
m_applets.emplace(applet->aruid.pid, std::move(applet));
}
std::shared_ptr<Applet> WindowSystem::GetByAppletResourceUserId(u64 aruid) {
std::scoped_lock lk{m_lock};
const auto it = m_applets.find(aruid);
if (it == m_applets.end()) {
return nullptr;
}
return it->second;
}
std::shared_ptr<Applet> WindowSystem::GetMainApplet() {
std::scoped_lock lk{m_lock};
if (m_application) {
return m_applets.at(m_application->aruid.pid);
}
return nullptr;
}
void WindowSystem::RequestHomeMenuToGetForeground() {
{
std::scoped_lock lk{m_lock};
m_foreground_requested_applet = m_home_menu;
}
m_event_observer->RequestUpdate();
}
void WindowSystem::RequestApplicationToGetForeground() {
{
std::scoped_lock lk{m_lock};
m_foreground_requested_applet = m_application;
}
m_event_observer->RequestUpdate();
}
void WindowSystem::RequestLockHomeMenuIntoForeground() {
{
std::scoped_lock lk{m_lock};
m_home_menu_foreground_locked = true;
}
m_event_observer->RequestUpdate();
}
void WindowSystem::RequestUnlockHomeMenuIntoForeground() {
{
std::scoped_lock lk{m_lock};
m_home_menu_foreground_locked = false;
}
m_event_observer->RequestUpdate();
}
void WindowSystem::RequestAppletVisibilityState(Applet& applet, bool visible) {
{
std::scoped_lock lk{applet.lock};
applet.window_visible = visible;
}
m_event_observer->RequestUpdate();
}
void WindowSystem::OnOperationModeChanged() {
std::scoped_lock lk{m_lock};
for (const auto& [aruid, applet] : m_applets) {
std::scoped_lock lk2{applet->lock};
applet->lifecycle_manager.OnOperationAndPerformanceModeChanged();
}
}
void WindowSystem::OnExitRequested() {
std::scoped_lock lk{m_lock};
for (const auto& [aruid, applet] : m_applets) {
std::scoped_lock lk2{applet->lock};
applet->lifecycle_manager.RequestExit();
}
}
void WindowSystem::OnHomeButtonPressed(ButtonPressDuration type) {
std::scoped_lock lk{m_lock};
// If we don't have a home menu, nothing to do.
if (!m_home_menu) {
return;
}
// Lock.
std::scoped_lock lk2{m_home_menu->lock};
// Send home button press event to home menu.
if (type == ButtonPressDuration::ShortPressing) {
m_home_menu->lifecycle_manager.PushUnorderedMessage(
AppletMessage::DetectShortPressingHomeButton);
}
}
void WindowSystem::PruneTerminatedAppletsLocked() {
for (auto it = m_applets.begin(); it != m_applets.end(); /* ... */) {
const auto& [aruid, applet] = *it;
std::scoped_lock lk{applet->lock};
if (!applet->process->IsTerminated()) {
// Not terminated.
it = std::next(it);
continue;
}
// Terminated, so ensure all child applets are terminated.
if (!applet->child_applets.empty()) {
this->TerminateChildAppletsLocked(applet.get());
// Not ready to unlink until all child applets are terminated.
it = std::next(it);
continue;
}
// Erase from caller applet's list of children.
if (auto caller_applet = applet->caller_applet.lock(); caller_applet) {
std::scoped_lock lk2{caller_applet->lock};
std::erase(caller_applet->child_applets, applet);
applet->caller_applet.reset();
// We don't need to update the activity state of the caller applet yet.
// It will be recalculated once we fall out of the termination handling path.
}
// If this applet was foreground, it no longer is.
if (applet.get() == m_foreground_requested_applet) {
m_foreground_requested_applet = nullptr;
}
// If this was the home menu, we should clean up.
if (applet.get() == m_home_menu) {
m_home_menu = nullptr;
m_foreground_requested_applet = m_application;
}
// If this was the application, we should try to switch to the home menu.
if (applet.get() == m_application) {
m_application = nullptr;
m_foreground_requested_applet = m_home_menu;
// If we have a home menu, send it the application exited message.
if (m_home_menu) {
m_home_menu->lifecycle_manager.PushUnorderedMessage(
AppletMessage::ApplicationExited);
}
}
// Finalize applet.
applet->OnProcessTerminatedLocked();
// Request update to ensure quiescence.
m_event_observer->RequestUpdate();
// Unlink and advance.
it = m_applets.erase(it);
}
// If the last applet has exited, exit the system.
if (m_applets.empty()) {
m_system.Exit();
}
}
bool WindowSystem::LockHomeMenuIntoForegroundLocked() {
// If the home menu is not locked into foreground, then there's nothing to do.
if (m_home_menu == nullptr || !m_home_menu_foreground_locked) {
m_home_menu_foreground_locked = false;
return false;
}
// Terminate any direct child applets of the home menu.
std::scoped_lock lk{m_home_menu->lock};
this->TerminateChildAppletsLocked(m_home_menu);
// When there are zero child applets left, we can proceed with the update.
if (m_home_menu->child_applets.empty()) {
m_home_menu->window_visible = true;
m_foreground_requested_applet = m_home_menu;
return false;
}
return true;
}
void WindowSystem::TerminateChildAppletsLocked(Applet* applet) {
auto child_applets = applet->child_applets;
applet->lock.unlock();
for (const auto& child_applet : child_applets) {
child_applet->process->Terminate();
}
applet->lock.lock();
}
void WindowSystem::UpdateAppletStateLocked(Applet* applet, bool is_foreground) {
// With no applet, we don't have anything to do.
if (!applet) {
return;
}
std::scoped_lock lk{applet->lock};
const bool inherited_foreground = applet->is_process_running && is_foreground;
const auto visible_state =
inherited_foreground ? ActivityState::ForegroundVisible : ActivityState::BackgroundVisible;
const auto obscured_state = inherited_foreground ? ActivityState::ForegroundObscured
: ActivityState::BackgroundObscured;
const bool has_obscuring_child_applets = [&] {
for (const auto& child_applet : applet->child_applets) {
std::scoped_lock lk2{child_applet->lock};
const auto mode = child_applet->library_applet_mode;
if (child_applet->is_process_running && child_applet->window_visible &&
(mode == LibraryAppletMode::AllForeground ||
mode == LibraryAppletMode::AllForegroundInitiallyHidden)) {
return true;
}
}
return false;
}();
// Update visibility state.
applet->display_layer_manager.SetWindowVisibility(is_foreground && applet->window_visible);
// Update interactibility state.
applet->SetInteractibleLocked(is_foreground && applet->window_visible);
// Update focus state and suspension.
const bool is_obscured = has_obscuring_child_applets || !applet->window_visible;
const auto state = applet->lifecycle_manager.GetActivityState();
if (is_obscured && state != obscured_state) {
// Set obscured state.
applet->lifecycle_manager.SetActivityState(obscured_state);
applet->UpdateSuspensionStateLocked(true);
} else if (!is_obscured && state != visible_state) {
// Set visible state.
applet->lifecycle_manager.SetActivityState(visible_state);
applet->UpdateSuspensionStateLocked(true);
}
// Recurse into child applets.
for (const auto& child_applet : applet->child_applets) {
this->UpdateAppletStateLocked(child_applet.get(), is_foreground);
}
}
} // namespace Service::AM

View File

@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <map>
#include <memory>
#include <mutex>
#include "common/common_types.h"
namespace Core {
class System;
}
namespace Service::AM {
struct Applet;
class EventObserver;
enum class ButtonPressDuration {
ShortPressing,
MiddlePressing,
LongPressing,
};
class WindowSystem {
public:
explicit WindowSystem(Core::System& system);
~WindowSystem();
public:
void SetEventObserver(EventObserver* event_observer) {
m_event_observer = event_observer;
}
void Update();
public:
void TrackApplet(std::shared_ptr<Applet> applet, bool is_application);
std::shared_ptr<Applet> GetByAppletResourceUserId(u64 aruid);
std::shared_ptr<Applet> GetMainApplet();
public:
void RequestHomeMenuToGetForeground();
void RequestApplicationToGetForeground();
void RequestLockHomeMenuIntoForeground();
void RequestUnlockHomeMenuIntoForeground();
void RequestAppletVisibilityState(Applet& applet, bool visible);
public:
void OnOperationModeChanged();
void OnExitRequested();
void OnHomeButtonPressed(ButtonPressDuration type);
void OnCaptureButtonPressed(ButtonPressDuration type) {}
void OnPowerButtonPressed(ButtonPressDuration type) {}
private:
void PruneTerminatedAppletsLocked();
bool LockHomeMenuIntoForegroundLocked();
void TerminateChildAppletsLocked(Applet* applet);
void UpdateAppletStateLocked(Applet* applet, bool is_foreground);
private:
// System reference.
Core::System& m_system;
// Event observer.
EventObserver* m_event_observer{};
// Lock.
std::mutex m_lock{};
// Home menu state.
bool m_home_menu_foreground_locked{};
Applet* m_foreground_requested_applet{};
// Foreground roots.
Applet* m_home_menu{};
Applet* m_application{};
// Applet map by aruid.
std::map<u64, std::shared_ptr<Applet>> m_applets{};
};
} // namespace Service::AM

View File

@ -12,7 +12,7 @@ namespace Service {
Process::Process(Core::System& system)
: m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(),
m_program_id(), m_process_started() {}
m_process_started() {}
Process::~Process() {
this->Finalize();
@ -73,7 +73,6 @@ void Process::Finalize() {
m_process = nullptr;
m_main_thread_priority = 0;
m_main_thread_stack_size = 0;
m_program_id = 0;
m_process_started = false;
}
@ -107,6 +106,17 @@ void Process::ResetSignal() {
}
}
bool Process::IsRunning() const {
if (m_process) {
const auto state = m_process->GetState();
return state == Kernel::KProcess::State::Running ||
state == Kernel::KProcess::State::RunningAttached ||
state == Kernel::KProcess::State::DebugBreak;
}
return false;
}
bool Process::IsTerminated() const {
if (m_process) {
return m_process->IsTerminated();
@ -123,6 +133,14 @@ u64 Process::GetProcessId() const {
return 0;
}
u64 Process::GetProgramId() const {
if (m_process) {
return m_process->GetProgramId();
}
return 0;
}
void Process::Suspend(bool suspended) {
if (m_process) {
m_process->SetActivity(suspended ? Kernel::Svc::ProcessActivity::Paused

View File

@ -36,12 +36,11 @@ public:
return m_process != nullptr;
}
bool IsRunning() const;
bool IsTerminated() const;
u64 GetProcessId() const;
u64 GetProgramId() const {
return m_program_id;
}
u64 GetProgramId() const;
Kernel::KProcess* GetHandle() const {
return m_process;
@ -52,7 +51,6 @@ private:
Kernel::KProcess* m_process{};
s32 m_main_thread_priority{};
u64 m_main_thread_stack_size{};
u64 m_program_id{};
bool m_process_started{};
};