Add profile service to support custom usernames

This commit is contained in:
Willi Ye 2020-07-19 22:35:50 +02:00 committed by ◱ PixelyIon
parent b86aac26d7
commit ffb9e743dd
11 changed files with 152 additions and 1 deletions

View File

@ -118,6 +118,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/services/lm/ILogger.cpp
${source_DIR}/skyline/services/account/IAccountServiceForApplication.cpp
${source_DIR}/skyline/services/account/IManagerForApplication.cpp
${source_DIR}/skyline/services/account/IProfile.cpp
${source_DIR}/skyline/services/friends/IServiceCreator.cpp
${source_DIR}/skyline/services/friends/IFriendService.cpp
${source_DIR}/skyline/services/nfp/IUserManager.cpp

View File

@ -54,6 +54,7 @@ namespace skyline {
constexpr u32 MaxHandles = 0xEE01; //!< "Too many handles"
constexpr u32 NotFound = 0xF201; //!< "Not found"
constexpr u32 Unimpl = 0x177202; //!< "Unimplemented behaviour"
constexpr u32 InvArg = 0x2c7c; //!< "Argument is invalid"
}
};

View File

@ -3,11 +3,13 @@
#include "IManagerForApplication.h"
#include "IAccountServiceForApplication.h"
#include "IProfile.h"
namespace skyline::service::account {
IAccountServiceForApplication::IAccountServiceForApplication(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::account_IAccountServiceForApplication, "account:IAccountServiceForApplication", {
{0x1, SFUNC(IAccountServiceForApplication::GetUserExistence)},
{0x4, SFUNC(IAccountServiceForApplication::GetLastOpenedUser)},
{0x5, SFUNC(IAccountServiceForApplication::GetProfile)},
{0x64, SFUNC(IAccountServiceForApplication::InitializeApplicationInfoV0)},
{0x65, SFUNC(IAccountServiceForApplication::GetBaasAccountManagerForApplication)}
}) {}
@ -24,6 +26,16 @@ namespace skyline::service::account {
void IAccountServiceForApplication::InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void IAccountServiceForApplication::GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto id = request.Pop<UserId>();
if (id != constant::DefaultUserId) {
response.errorCode = constant::status::InvArg;
return;
}
manager.RegisterService(std::make_shared<IProfile>(state, manager, id), session, response);
}
void IAccountServiceForApplication::GetBaasAccountManagerForApplication(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(SRVREG(IManagerForApplication), session, response);
}

View File

@ -19,9 +19,13 @@ namespace skyline {
* @param userId The user ID to compare with
* @return Whether this user ID matches the one given as a parameter
*/
inline constexpr bool operator==(const UserId& userId) {
inline constexpr bool operator==(const UserId &userId) {
return upper == userId.upper && lower == userId.lower;
}
inline constexpr bool operator!=(const UserId &userId) {
return !(*this == userId);
}
};
/**
* @brief IAccountServiceForApplication or acc:u0 provides functions for reading user information (https://switchbrew.org/wiki/Account_services#acc:u0)
@ -45,6 +49,11 @@ namespace skyline {
*/
void InitializeApplicationInfoV0(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a handle to an IProfile which can be used for reading user information
*/
void GetProfile(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
/**
* @brief This returns a handle to an IManagerForApplication which can be used for reading Nintendo Online info
*/

View File

@ -0,0 +1,24 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <kernel/types/KProcess.h>
#include "IProfile.h"
namespace skyline::service::account {
IProfile::IProfile(const DeviceState &state, ServiceManager &manager, const UserId &userId) : BaseService(state, manager, Service::account_IProfile, "account:IProfile", {
{0x0, SFUNC(IProfile::Get)}
}) {}
void IProfile::Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
AccountUserData userData{};
AccountProfileBase profileBase{};
std::string username = state.settings->GetString("username_value");
size_t usernameSize = std::min(sizeof(profileBase), username.size());
std::memcpy(profileBase.nickname, username.c_str(), usernameSize);
profileBase.nickname[usernameSize] = '\0';
state.process->WriteMemory(userData, request.outputBuf.at(0).address);
response.Push(profileBase);
}
}

View File

@ -0,0 +1,41 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include "IAccountServiceForApplication.h"
#include <services/base_service.h>
namespace skyline::service::account {
/// UserData
typedef struct {
u32 unk_x0; ///< Unknown.
u32 iconID; ///< Icon ID. 0 = Mii, the rest are character icon IDs.
u8 iconBackgroundColorID; ///< Profile icon background color ID
u8 unk_x9[0x7]; ///< Unknown.
u8 miiID[0x10]; ///< Some ID related to the Mii? All zeros when a character icon is used.
u8 unk_x20[0x60]; ///< Usually zeros?
} AccountUserData;
/// ProfileBase
typedef struct {
UserId uid; ///< \ref AccountUid
u64 lastEditTimestamp; ///< POSIX UTC timestamp, for the last account edit.
char nickname[0x20]; ///< UTF-8 Nickname.
} AccountProfileBase;
/**
* @brief IProfile provides functions for reading user profile (https://switchbrew.org/wiki/Account_services#IProfile)
*/
class IProfile : public BaseService {
public:
IProfile(const DeviceState &state, ServiceManager &manager, const UserId &userId);
private:
/**
* @brief This returns AccountUserData (optional) and AccountProfileBase
*/
void Get(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
};
}

View File

@ -73,6 +73,7 @@ namespace skyline::service {
lm_ILogger,
account_IAccountServiceForApplication,
account_IManagerForApplication,
account_IProfile,
friends_IServiceCreator,
friends_IFriendService,
nfp_IUserManager,

View File

@ -0,0 +1,49 @@
/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.preference
import android.content.Context
import android.text.InputFilter
import android.text.InputFilter.LengthFilter
import android.util.AttributeSet
import androidx.preference.EditTextPreference
import emu.skyline.R
/**
* [EditTextPreference] lacks the feature to set the automatically value as summary.
* This class adds this missing thing. Also added useful attributes.
*/
class CustomEditTextPreference : EditTextPreference {
constructor(context : Context, attrs : AttributeSet?, defStyleAttr : Int, defStyleRes : Int) : super(context, attrs, defStyleAttr, defStyleRes) {
attrs?.let {
val a = context.obtainStyledAttributes(it, R.styleable.CustomEditTextPreference, defStyleAttr, 0)
val limit = a.getInt(R.styleable.CustomEditTextPreference_limit, -1)
a.recycle()
if (limit >= 0) {
setOnBindEditTextListener { editText -> editText.filters = arrayOf<InputFilter>(LengthFilter(limit)) }
}
}
setOnPreferenceChangeListener { _, newValue ->
summary = newValue.toString()
true
}
}
constructor(context : Context, attrs : AttributeSet?, defStyleAttr : Int) : this(context, attrs, defStyleAttr, 0)
constructor(context : Context, attrs : AttributeSet?) : this(context, attrs, androidx.preference.R.attr.editTextPreferenceStyle)
constructor(context : Context) : this(context, null)
override fun onAttached() {
super.onAttached()
summary = text
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomEditTextPreference">
<attr name="limit" format="integer"/>
</declare-styleable>
</resources>

View File

@ -38,6 +38,8 @@
<string name="handheld_enabled">The system will emulate being in handheld mode</string>
<string name="docked_enabled">The system will emulate being in docked mode</string>
<string name="theme">Theme</string>
<string name="username">Username</string>
<string name="username_default">@string/app_name</string>
<!-- Licenses -->
<string name="licenses">Licenses</string>
<string name="skyline_license_description">The license of Skyline (MPL 2.0)</string>

View File

@ -62,6 +62,11 @@
android:summaryOn="@string/log_compact_desc_on"
app:key="log_compact"
app:title="@string/log_compact" />
<emu.skyline.preference.CustomEditTextPreference
android:defaultValue="@string/username_default"
app:key="username_value"
app:limit="32"
app:title="@string/username" />
</PreferenceCategory>
<PreferenceCategory
android:key="category_system"