core: hle: service: acc: Fix ListOpenContextStoredUsers/StoreOpenContext.

- These APIs are used to capture the opened users and allow that state to be persisted across processes.
- They are not intended to just return the system opened users, that is what ListOpenUsers is for.
- Fixes the launch hang with Bayonetta 3.
This commit is contained in:
bunnei 2022-10-30 16:37:28 -07:00
parent 83f649240e
commit 75ab52f05b
5 changed files with 42 additions and 23 deletions

View file

@ -512,10 +512,11 @@ protected:
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public: public:
explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_) explicit IManagerForApplication(Core::System& system_,
const std::shared_ptr<ProfileManager>& profile_manager_)
: ServiceFramework{system_, "IManagerForApplication"}, : ServiceFramework{system_, "IManagerForApplication"},
ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)}, ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
user_id{user_id_} { profile_manager{profile_manager_} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
@ -545,7 +546,7 @@ private:
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<u64>(user_id.Hash()); rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
} }
void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) { void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
@ -575,17 +576,20 @@ private:
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<u64>(user_id.Hash()); rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
} }
void StoreOpenContext(Kernel::HLERequestContext& ctx) { void StoreOpenContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); LOG_DEBUG(Service_ACC, "called");
profile_manager->StoreOpenedUsers();
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{}; std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
Common::UUID user_id{}; std::shared_ptr<ProfileManager> profile_manager;
}; };
// 6.0.0+ // 6.0.0+
@ -790,7 +794,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
LOG_DEBUG(Service_ACC, "called"); LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser()); rb.PushIpcInterface<IManagerForApplication>(system, profile_manager);
} }
void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) {
@ -849,22 +853,10 @@ void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void Module::Interface::LoadOpenContext(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
// This is similar to GetBaasAccountManagerForApplication
// This command is used concurrently with ListOpenContextStoredUsers
// TODO: Find the differences between this and GetBaasAccountManagerForApplication
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser());
}
void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) { void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called"); LOG_DEBUG(Service_ACC, "called");
// TODO(ogniK): Handle open contexts ctx.WriteBuffer(profile_manager->GetStoredOpenedUsers());
ctx.WriteBuffer(profile_manager->GetOpenUsers());
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }

View file

@ -35,7 +35,6 @@ public:
void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx); void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx);
void GetProfileEditor(Kernel::HLERequestContext& ctx); void GetProfileEditor(Kernel::HLERequestContext& ctx);
void ListQualifiedUsers(Kernel::HLERequestContext& ctx); void ListQualifiedUsers(Kernel::HLERequestContext& ctx);
void LoadOpenContext(Kernel::HLERequestContext& ctx);
void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx); void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx);
void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx); void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx);
void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx); void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx);

View file

@ -28,7 +28,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
{110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"}, {110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
{111, nullptr, "ClearSaveDataThumbnail"}, {111, nullptr, "ClearSaveDataThumbnail"},
{120, nullptr, "CreateGuestLoginRequest"}, {120, nullptr, "CreateGuestLoginRequest"},
{130, &ACC_U0::LoadOpenContext, "LoadOpenContext"}, // 5.0.0+ {130, nullptr, "LoadOpenContext"}, // 5.0.0+
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+ {131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+ {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+

View file

@ -261,6 +261,31 @@ UUID ProfileManager::GetLastOpenedUser() const {
return last_opened_user; return last_opened_user;
} }
/// Gets the list of stored opened users.
UserIDArray ProfileManager::GetStoredOpenedUsers() const {
UserIDArray output{};
std::ranges::transform(stored_opened_profiles, output.begin(), [](const ProfileInfo& p) {
if (p.is_open)
return p.user_uuid;
return Common::InvalidUUID;
});
std::stable_partition(output.begin(), output.end(),
[](const UUID& uuid) { return uuid.IsValid(); });
return output;
}
/// Captures the opened users, which can be queried across process launches with
/// ListOpenContextStoredUsers.
void ProfileManager::StoreOpenedUsers() {
size_t profile_index{};
stored_opened_profiles = {};
std::for_each(profiles.begin(), profiles.end(), [&](const auto& profile) {
if (profile.is_open) {
stored_opened_profiles[profile_index++] = profile;
}
});
}
/// Return the users profile base and the unknown arbitary data. /// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile, bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
UserData& data) const { UserData& data) const {

View file

@ -86,6 +86,8 @@ public:
UserIDArray GetOpenUsers() const; UserIDArray GetOpenUsers() const;
UserIDArray GetAllUsers() const; UserIDArray GetAllUsers() const;
Common::UUID GetLastOpenedUser() const; Common::UUID GetLastOpenedUser() const;
UserIDArray GetStoredOpenedUsers() const;
void StoreOpenedUsers();
bool CanSystemRegisterUser() const; bool CanSystemRegisterUser() const;
@ -101,6 +103,7 @@ private:
bool RemoveProfileAtIndex(std::size_t index); bool RemoveProfileAtIndex(std::size_t index);
std::array<ProfileInfo, MAX_USERS> profiles{}; std::array<ProfileInfo, MAX_USERS> profiles{};
std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{};
std::size_t user_count{}; std::size_t user_count{};
Common::UUID last_opened_user{}; Common::UUID last_opened_user{};
}; };