skyline/app/src/main/cpp/skyline/services/am/controller/IApplicationFunctions.cpp
PixelyIon 82154f3ef6 Upgrade AGP to 7.1.0-beta01 & NDK to 24.0.7856742
We've moved to using a beta AGP as `7.0.2` is breaks `clangd` and other C++ features on Beta/Canary Android Studio. NDK was additionally updated with `mbedtls` to fix warnings caused by it alongside some other minor fixes to code for newer versions of libcxx.

The new AGP has a bug where it does not look for executables specified in `android_gradle_build.json` in `PATH` that includes `ninja` which is provided by the `ninja-build` package on the system rather than Android SDK's CMake on GitHub Actions (Ubuntu 20.04). This has been fixed by symlinking `/usr/bin/ninja` to the project root which is searched in for the `ninja` executable.
2021-10-31 15:50:15 +05:30

142 lines
6.1 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <common/uuid.h>
#include <mbedtls/sha1.h>
#include <loader/loader.h>
#include <os.h>
#include <kernel/types/KProcess.h>
#include <services/account/IAccountServiceForApplication.h>
#include <services/am/storage/IStorage.h>
#include "IApplicationFunctions.h"
namespace skyline::service::am {
IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) : gpuErrorEvent(std::make_shared<type::KEvent>(state, false)), BaseService(state, manager) {}
Result IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters
constexpr size_t LaunchParameterSize{0x88}; //!< The size of the launch parameter IStorage
enum class LaunchParameterKind : u32 {
UserChannel = 1,
PreselectedUser = 2,
Unknown = 3,
} launchParameterKind{request.Pop<LaunchParameterKind>()};
std::shared_ptr<IStorage> storageService;
switch (launchParameterKind) {
case LaunchParameterKind::UserChannel:
return result::NotAvailable;
case LaunchParameterKind::PreselectedUser: {
storageService = std::make_shared<IStorage>(state, manager, LaunchParameterSize);
storageService->Push<u32>(LaunchParameterMagic);
storageService->Push<u32>(1);
storageService->Push(constant::DefaultUserId);
break;
}
case LaunchParameterKind::Unknown:
throw exception("Popping 'Unknown' Launch Parameter: {}", static_cast<u32>(launchParameterKind));
default:
return result::InvalidInput;
}
manager.RegisterService(storageService, session, response);
return {};
}
Result IApplicationFunctions::EnsureSaveData(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<u8>(0);
return {};
}
Result IApplicationFunctions::GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto desiredLanguage{language::GetApplicationLanguage(state.os->systemLanguage)};
// In the future we might want to trigger an UI dialog if the user selected languages is not available, for now it will use the first available
if (((1 << static_cast<u32>(desiredLanguage)) & state.loader->nacp->nacpContents.supportedLanguageFlag) == 0)
desiredLanguage = state.loader->nacp->GetFirstSupportedLanguage();
response.Push(language::GetLanguageCode(language::GetSystemLanguage(desiredLanguage)));
return {};
}
Result IApplicationFunctions::NotifyRunning(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
response.Push<u8>(1);
return {};
}
Result IApplicationFunctions::GetPseudoDeviceId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto seedForPseudoDeviceId{state.loader->nacp->nacpContents.seedForPseudoDeviceId};
std::array<u8, 20> hashBuf{};
// On HOS the seed from control.ncap is hashed together with the device specific device ID seed
// for us it's enough to just hash the seed from control.nacp as it provides the same guarantees
if (int err{mbedtls_sha1_ret(seedForPseudoDeviceId.data(), seedForPseudoDeviceId.size(), hashBuf.data())}; err < 0)
throw exception("Failed to hash device ID, err: {}", err);
response.Push<UUID>(UUID::GenerateUuidV5(hashBuf));
return {};
}
Result IApplicationFunctions::InitializeGamePlayRecording(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
return {};
}
Result IApplicationFunctions::SetGamePlayRecordingState(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
return {};
}
Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
i32 width{request.Pop<i32>()};
i32 height{request.Pop<i32>()};
u64 transferMemorySize{request.Pop<u64>()};
constexpr i32 MaximumFbWidth{1280};
constexpr i32 MaximumFbHeight{720};
constexpr u64 RequiredFbAlignment{0x40000};
if (width > MaximumFbWidth || height > MaximumFbHeight || !util::IsAligned(transferMemorySize, RequiredFbAlignment))
return result::InvalidParameters;
state.logger->Debug("Dimensions: ({}, {}) Transfer Memory Size: {}", width, height, transferMemorySize);
return {};
}
Result IApplicationFunctions::SetApplicationCopyrightImage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
i32 x{request.Pop<i32>()};
i32 y{request.Pop<i32>()};
i32 width{request.Pop<i32>()};
i32 height{request.Pop<i32>()};
enum class WindowOriginMode : i32 {
LowerLeft,
UpperLeft
} originMode = request.Pop<WindowOriginMode>();
if (y < 0 || x < 0 || width < 1 || height < 1)
return result::InvalidParameters;
state.logger->Debug("Position: ({}, {}) Dimensions: ({}, {}) Origin mode: {}", x, y, width, height, static_cast<i32>(originMode));
return {};
}
Result IApplicationFunctions::SetApplicationCopyrightVisibility(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
u8 visiblity{request.Pop<u8>()};
state.logger->Debug("Visiblity: {}", visiblity);
return {};
}
Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
auto handle{state.process->InsertItem(gpuErrorEvent)};
state.logger->Debug("GPU Error Event Handle: 0x{:X}", handle);
response.copyHandles.push_back(handle);
return {};
}
}