클라이언트팀(특히 UI)에서는 이미 잘 알고 사용하고 있겠지만 테크아트 부서에서는 잘 다룰 일이 없는 클래스입니다.
그럼에도 최근 AOS 빌드 관련 업무를 주도적으로 처리 하고 있기 때문이기도 하고 구글에서 제공하는 안드로이드 적응형 퍼포먼스 제어 플러그인으로 알려진 ADPF 내부 구조를 분석하고 커스터마이징을 하는 과정에 들어가야 했었기 때문에 AndroidMisc 클래스에서는 어떤 것들을 제공하는지 알고 싶었습니다. ADPF 의 핵심은 사실 열 공간에 대한 런타임 모니터링이 가장 핵심이고 열 공간 빈드에 따라 간단한 분기문을 통해 언리얼 모바일 렌더피처를 동적으로 수정해 주는 것이 전체 메커니즘의 전부라고 볼 수 있어요. ADPF 에 대해서도 따로 살펴 볼 기회가 있겠지만 먼저 몇 가지 언리얼엔진 내부에서 제공하는 안드로이드 관련 클래스들도 살펴볼께요.
Engine\Source\Runtime\Core\Public\Android\AndroidPlatformMisc.h
FAndroidMisc 클래스 개요
FAndroidMisc 클래스는 Unreal Engine에서 안드로이드 디바이스의 Miscellaneous 정보를 제공하는 정적 클래스입니다. 여기에는 다음 기능들이 포함됩니다:
이 클래스는 Android 플랫폼에 특화된 기능을 다루는 정적 함수와 데이터 구조를 포함하며, 다른 플랫폼에 대한 기본 기능 구현을 제공하는 FGenericPlatformMisc를 상속받습니다.
FAndroidMisc는 Unreal Engine의 모바일(Android) 플랫폼에서 장치 및 시스템 리소스 관리와 플랫폼별 기능을 수행하기 위한 유틸리티 클래스입니다. 이 클래스는 주로 Android 운영 체제와의 상호작용을 처리하며, 다양한 디바이스 정보 및 상태를 얻고, 기능을 제어하거나 조작하는 인터페이스로 사용됩니다.
플랫폼(Android) 특화 작업을 수행합니다.
- 애플리케이션과 장치 상태 관리:
- RequestExit(bool Force, const TCHAR* CallSite)
- 애플리케이션을 강제 종료하거나 정상 종료하도록 요청합니다.
- RestartApplication()
- 애플리케이션을 재시작합니다.
- PlatformInit() / PlatformPreInit() / PlatformTearDown()
- Android 플랫폼에서 초기화, 사전 초기화, 종료 작업을 담당합니다.
- RequestExit(bool Force, const TCHAR* CallSite)
- 디바이스 제어 및 정보:
- GetDeviceOrientation()
- 디바이스의 현재 화면 방향(Orientation)을 가져옵니다.
- SetAllowedDeviceOrientation()
- 허용되는 디바이스 방향을 설정합니다.
- SetCellularPreference() 및 GetCellularPreference()
- 셀룰러 데이터 사용에 대한 우선순위를 설정하거나 가져옵니다.
- GetDeviceVolume()
- 디바이스 볼륨 상태를 가져옵니다.
- IsRunningOnBattery()
- 현재 배터리 사용 중인지 확인합니다.
- GetDeviceOrientation()
- CPU 및 하드웨어 정보:
- FCPUStatTime 구조체
- CPU의 시간 데이터(사용률, Idle 상태 등)를 나타냅니다.
- FCPUState 구조체
- CPU의 여러 코어, 이름, 현재 사용량 등을 포함하여 CPU 상태를 나타냅니다.
- GetCPUState()
- CPU 상태를 반환하는 함수입니다.
- NumberOfCores()
- 디바이스의 활성 CPU 코어 수를 반환합니다.
- FCPUStatTime 구조체
- 메시지 및 환경 관리:
- LocalPrint(const TCHAR* Message)
- 로컬 디버깅/테스트용 메시지를 출력합니다.
- GetEnvironmentVariable()
- 환경 변수를 가져옵니다.
- MessageBoxExt()
- 플랫폼의 기본 메시지 상자를 표시합니다.
- LocalPrint(const TCHAR* Message)
- 리소스 저장소(command, configuration 등):
- SetStoredValue() 및 GetStoredValue()
- 스토리지에 특정 키-값 데이터를 저장하거나 검색합니다.
- DeleteStoredValue()
- 특정 키/섹션 데이터를 삭제합니다.
- SetStoredValue() 및 GetStoredValue()
- 배터리 관련 기능:
- FBatteryState 구조체
- 배터리 상태, 레벨, 온도 등의 정보를 나타냅니다.
- GetBatteryState()
- 배터리 상태를 가져옵니다.
- FBatteryState 구조체
- JNI(Java Native Interface):
- GetDeviceId() 및 GetUniqueAdvertisingId() (Android JNI 사용 시만 가능)
- Android 디바이스의 고유 식별 정보를 얻습니다.
- HasActiveWiFiConnection()
- Wi-Fi 상태 확인(JNI가 활성화된 경우만 사용 가능).
- GetDeviceId() 및 GetUniqueAdvertisingId() (Android JNI 사용 시만 가능)
- 운영 체제 및 버전 정보:
- GetOSVersions(out_OSVersionLabel, out_OSSubVersionLabel)
- Android 운영 체제의 버전 정보를 가져옵니다.
- GetAndroidVersion() / GetAndroidMajorVersion()
- Android OS 버전을 반환합니다.
- GetDeviceMake() / GetDeviceModel()
- 디바이스 제조사와 모델 정보를 반환합니다.
- GetOSVersions(out_OSVersionLabel, out_OSSubVersionLabel)
- 네트워크 및 볼륨:
- GetNetworkConnectionType()
- 네트워크 연결 유형(Wi-Fi, 셀룰러 등)을 반환합니다.
- GetVolumeButtonsHandledBySystem() 및 SetVolumeButtonsHandledBySystem(bool)
- 볼륨 버튼 이벤트를 시스템에서 처리할지 여부를 설정합니다.
- GetNetworkConnectionType()
- GPU 및 Vulkan 지원 여부:
- GetPrimaryGPUBrand()
- 주요 GPU 브랜드를 반환합니다.
- HasVulkanDriverSupport()
- Vulkan 드라이버를 지원하는지 여부 확인.
- IsVulkanAvailable()
- Vulkan 사용 가능 여부를 확인합니다.
- GetPrimaryGPUBrand()
구조체 필드 설명:
FCPUStatTime 구조체:
- CPU 시간을 나타냄.
- TotalTime - 총 사용 시간.
- IdleTime - 유휴 시간.
FBatteryState 구조체:
- 배터리의 상태.
- State - 배터리 상태(충전 중, 방전 중 등).
- Level - 배터리 잔량(0-100%).
- Temperature - 디바이스 온도(Celsius).
주요 Enum:
- EDeviceScreenOrientation
- 디바이스가 가로/세로 등의 방향을 정의합니다.
- EBatteryState
- 배터리 상태(충전, 방전, 완충 등)를 표시:
- BATTERY_STATE_CHARGING - 충전 중.
- BATTERY_STATE_DISCHARGING - 방전 중.
- 배터리 상태(충전, 방전, 완충 등)를 표시:
- ENetworkConnectionType
- 네트워크 연결 유형(Enum).
기타 주요 함수:
- GetSystemFontBytes()
- 시스템의 기본 글꼴(폰트)을 바이트 배열로 반환.
- ShareURL()
- URL을 공유하는 인터페이스 제공(Android 용).
struct FAndroidMisc : public FGenericPlatformMisc
{
static CORE_API void RequestExit( bool Force, const TCHAR* CallSite = nullptr);
static CORE_API bool RestartApplication();
static CORE_API void LocalPrint(const TCHAR *Message);
static bool IsLocalPrintThreadSafe() { return true; }
static CORE_API void PlatformPreInit();
static CORE_API void PlatformInit();
static CORE_API void PlatformTearDown();
static CORE_API void PlatformHandleSplashScreen(bool ShowSplashScreen);
static EDeviceScreenOrientation GetDeviceOrientation() { return DeviceOrientation; }
UE_DEPRECATED(5.1, "SetDeviceOrientation is deprecated. Use SetAllowedDeviceOrientation instead.")
static CORE_API void SetDeviceOrientation(EDeviceScreenOrientation NewDeviceOrentation);
static CORE_API void SetAllowedDeviceOrientation(EDeviceScreenOrientation NewAllowedDeviceOrientation);
// Change this to an Enum with Always allow, allow and deny
static CORE_API void SetCellularPreference(int32 Value);
static CORE_API int32 GetCellularPreference();
FORCEINLINE static int32 GetMaxPathLength()
{
return ANDROID_MAX_PATH;
}
UE_DEPRECATED(4.21, "void FPlatformMisc::GetEnvironmentVariable(Name, Result, Length) is deprecated. Use FString FPlatformMisc::GetEnvironmentVariable(Name) instead.")
static CORE_API void GetEnvironmentVariable(const TCHAR* VariableName, TCHAR* Result, int32 ResultLength);
static CORE_API FString GetEnvironmentVariable(const TCHAR* VariableName);
static CORE_API const TCHAR* GetSystemErrorMessage(TCHAR* OutBuffer, int32 BufferCount, int32 Error);
static CORE_API EAppReturnType::Type MessageBoxExt( EAppMsgType::Type MsgType, const TCHAR* Text, const TCHAR* Caption );
static CORE_API bool UseRenderThread();
static CORE_API bool HasPlatformFeature(const TCHAR* FeatureName);
static CORE_API bool SupportsES30();
static CORE_API bool SetStoredValue(const FString& InStoreId, const FString& InSectionName, const FString& InKeyName, const FString& InValue);
static CORE_API bool GetStoredValue(const FString& InStoreId, const FString& InSectionName, const FString& InKeyName, FString& OutValue);
static CORE_API bool DeleteStoredValue(const FString& InStoreId, const FString& InSectionName, const FString& InKeyName);
static CORE_API bool DeleteStoredSection(const FString& InStoreId, const FString& InSectionName);
public:
static CORE_API bool AllowThreadHeartBeat();
struct FCPUStatTime{
uint64_t TotalTime;
uint64_t UserTime;
uint64_t NiceTime;
uint64_t SystemTime;
uint64_t SoftIRQTime;
uint64_t IRQTime;
uint64_t IdleTime;
uint64_t IOWaitTime;
};
struct FCPUState
{
const static int32 MaxSupportedCores = 16; //Core count 16 is maximum for now
int32 CoreCount;
int32 ActivatedCoreCount;
ANSICHAR Name[6];
FAndroidMisc::FCPUStatTime CurrentUsage[MaxSupportedCores];
FAndroidMisc::FCPUStatTime PreviousUsage[MaxSupportedCores];
int32 Status[MaxSupportedCores];
double Utilization[MaxSupportedCores];
double AverageUtilization;
};
static CORE_API FCPUState& GetCPUState();
static CORE_API int32 NumberOfCores();
static CORE_API int32 NumberOfCoresIncludingHyperthreads();
static CORE_API bool SupportsLocalCaching();
static CORE_API void CreateGuid(struct FGuid& Result);
static CORE_API void SetCrashHandler(void (* CrashHandler)(const FGenericCrashContext& Context));
// NOTE: THIS FUNCTION IS DEFINED IN ANDROIDOPENGL.CPP
static CORE_API void GetValidTargetPlatforms(class TArray<class FString>& TargetPlatformNames);
static CORE_API bool GetUseVirtualJoysticks();
static CORE_API bool SupportsTouchInput();
static const TCHAR* GetDefaultDeviceProfileName() { return TEXT("Android_Default"); }
static CORE_API bool GetVolumeButtonsHandledBySystem();
static CORE_API void SetVolumeButtonsHandledBySystem(bool enabled);
// Returns current volume, 0-15
static CORE_API int GetVolumeState(double* OutTimeOfChangeInSec = nullptr);
static CORE_API int32 GetDeviceVolume();
#if USE_ANDROID_FILE
static CORE_API const TCHAR* GamePersistentDownloadDir();
static CORE_API FString GetLoginId();
#endif
#if USE_ANDROID_JNI
static CORE_API FString GetDeviceId();
static CORE_API FString GetUniqueAdvertisingId();
#endif
static CORE_API FString GetCPUVendor();
static CORE_API FString GetCPUBrand();
static CORE_API FString GetCPUChipset();
static CORE_API FString GetPrimaryGPUBrand();
static CORE_API void GetOSVersions(FString& out_OSVersionLabel, FString& out_OSSubVersionLabel);
static CORE_API bool GetDiskTotalAndFreeSpace(const FString& InPath, uint64& TotalNumberOfBytes, uint64& NumberOfFreeBytes);
enum EBatteryState
{
BATTERY_STATE_UNKNOWN = 1,
BATTERY_STATE_CHARGING,
BATTERY_STATE_DISCHARGING,
BATTERY_STATE_NOT_CHARGING,
BATTERY_STATE_FULL
};
struct FBatteryState
{
FAndroidMisc::EBatteryState State;
int Level; // in range [0,100]
float Temperature; // in degrees of Celsius
};
static CORE_API FBatteryState GetBatteryState();
static CORE_API int GetBatteryLevel();
static CORE_API bool IsRunningOnBattery();
static CORE_API bool IsInLowPowerMode();
static CORE_API float GetDeviceTemperatureLevel();
static CORE_API bool AreHeadPhonesPluggedIn();
static CORE_API ENetworkConnectionType GetNetworkConnectionType();
#if USE_ANDROID_JNI
static CORE_API bool HasActiveWiFiConnection();
#endif
static CORE_API void RegisterForRemoteNotifications();
static CORE_API void UnregisterForRemoteNotifications();
static CORE_API bool IsAllowedRemoteNotifications();
/** @return Memory representing a true type or open type font provided by the platform as a default font for unreal to consume; empty array if the default font failed to load. */
static CORE_API TArray<uint8> GetSystemFontBytes();
static CORE_API IPlatformChunkInstall* GetPlatformChunkInstall();
static CORE_API void PrepareMobileHaptics(EMobileHapticsType Type);
static CORE_API void TriggerMobileHaptics();
static CORE_API void ReleaseMobileHaptics();
static CORE_API void ShareURL(const FString& URL, const FText& Description, int32 LocationHintX, int32 LocationHintY);
static CORE_API FString LoadTextFileFromPlatformPackage(const FString& RelativePath);
static CORE_API bool FileExistsInPlatformPackage(const FString& RelativePath);
// ANDROID ONLY:
static CORE_API void SetVersionInfo(FString AndroidVersion, int32 InTargetSDKVersion, FString DeviceMake, FString DeviceModel, FString DeviceBuildNumber, FString OSLanguage, FString ProductName);
static CORE_API const FString GetAndroidVersion();
static CORE_API int32 GetAndroidMajorVersion();
static CORE_API int32 GetTargetSDKVersion();
static CORE_API const FString GetDeviceMake();
static CORE_API const FString GetDeviceModel();
static CORE_API const FString GetOSLanguage();
static CORE_API const FString GetProductName(); // returns the product name, if available. e.g. 'Galaxy Tab S8' or empty string.
static CORE_API const FString GetDeviceBuildNumber();
static CORE_API const FString GetProjectVersion();
static CORE_API FString GetDefaultLocale();
static CORE_API FString GetGPUFamily();
static CORE_API FString GetGLVersion();
static CORE_API bool SupportsFloatingPointRenderTargets();
static CORE_API bool SupportsShaderFramebufferFetch();
static CORE_API bool SupportsShaderIOBlocks();
#if USE_ANDROID_JNI
static CORE_API int GetAndroidBuildVersion();
#endif
static CORE_API bool IsSupportedAndroidDevice();
static CORE_API void SetForceUnsupported(bool bInOverride);
static CORE_API const TMap<FString, FString>& GetConfigRulesTMap();
static CORE_API FString* GetConfigRulesVariable(const FString& Key);
/* HasVulkanDriverSupport
* @return true if this Android device supports a Vulkan API Unreal could use
*/
static CORE_API bool HasVulkanDriverSupport();
/* IsVulkanAvailable
* @return true if there is driver support, we have an RHI, we are packaged with Vulkan support,
* and not we are not forcing GLES with a command line switch
*/
static CORE_API bool IsVulkanAvailable();
static CORE_API bool IsDesktopVulkanAvailable();
/* ShouldUseVulkan
* @return true if Vulkan is available, and not disabled by device profile cvar
*/
static CORE_API bool ShouldUseVulkan();
static CORE_API bool ShouldUseDesktopVulkan();
static CORE_API FString GetVulkanVersion();
typedef TFunction<void(void* NewNativeHandle)> ReInitWindowCallbackType;
static CORE_API ReInitWindowCallbackType GetOnReInitWindowCallback();
static CORE_API void SetOnReInitWindowCallback(ReInitWindowCallbackType InOnReInitWindowCallback);
typedef TFunction<void()> ReleaseWindowCallbackType;
static CORE_API ReleaseWindowCallbackType GetOnReleaseWindowCallback();
static CORE_API void SetOnReleaseWindowCallback(ReleaseWindowCallbackType InOnReleaseWindowCallback);
static CORE_API FString GetOSVersion();
static bool GetOverrideResolution(int32 &ResX, int32& ResY) { return false; }
typedef TFunction<void()> OnPauseCallBackType;
static CORE_API OnPauseCallBackType GetOnPauseCallback();
static CORE_API void SetOnPauseCallback(OnPauseCallBackType InOnPauseCallback);
static CORE_API void TriggerCrashHandler(ECrashContextType InType, const TCHAR* InErrorMessage, const TCHAR* OverrideCallstack = nullptr);
// To help track down issues with failing crash handler.
static CORE_API FString GetFatalSignalMessage(int Signal, siginfo* Info);
static CORE_API void OverrideFatalSignalHandler(void (*FatalSignalHandlerOverrideFunc)(int Signal, struct siginfo* Info, void* Context, uint32 CrashingThreadId));
// To help track down issues with failing crash handler.
static CORE_API bool IsInSignalHandler();
#if !UE_BUILD_SHIPPING
static CORE_API bool IsDebuggerPresent();
#endif
FORCEINLINE static void MemoryBarrier()
{
__sync_synchronize();
}
#if STATS || ENABLE_STATNAMEDEVENTS
static CORE_API void BeginNamedEventFrame();
static CORE_API void BeginNamedEvent(const struct FColor& Color, const TCHAR* Text);
static CORE_API void BeginNamedEvent(const struct FColor& Color, const ANSICHAR* Text);
static CORE_API void EndNamedEvent();
static CORE_API void CustomNamedStat(const TCHAR* Text, float Value, const TCHAR* Graph, const TCHAR* Unit);
static CORE_API void CustomNamedStat(const ANSICHAR* Text, float Value, const ANSICHAR* Graph, const ANSICHAR* Unit);
#endif
#if (STATS || ENABLE_STATNAMEDEVENTS)
static CORE_API int32 TraceMarkerFileDescriptor;
#endif
// run time compatibility information
static CORE_API FString AndroidVersion; // version of android we are running eg "4.0.4"
static CORE_API int32 AndroidMajorVersion; // integer major version of Android we are running, eg 10
static CORE_API int32 TargetSDKVersion; // Target SDK version, eg 29.
static CORE_API FString DeviceMake; // make of the device we are running on eg. "samsung"
static CORE_API FString DeviceModel; // model of the device we are running on eg "SAMSUNG-SGH-I437"
static CORE_API FString DeviceBuildNumber; // platform image build number of device "R16NW.G960NKSU1ARD6"
static CORE_API FString OSLanguage; // language code the device is set to
static CORE_API FString ProductName; // Product name, if available. e.g. 'Galaxy Tab S8' or empty string.
// Build version of Android, i.e. API level.
static CORE_API int32 AndroidBuildVersion;
// Key/Value pair variables from the optional configuration.txt
static CORE_API TMap<FString, FString> ConfigRulesVariables;
static CORE_API bool VolumeButtonsHandledBySystem;
static CORE_API bool bNeedsRestartAfterPSOPrecompile;
enum class ECoreFrequencyProperty
{
CurrentFrequency,
MaxFrequency,
MinFrequency,
};
static CORE_API uint32 GetCoreFrequency(int32 CoreIndex, ECoreFrequencyProperty CoreFrequencyProperty);
// Returns CPU temperature read from one of the configurable CPU sensors via android.CPUThermalSensorFilePath CVar or AndroidEngine.ini, [ThermalSensors] section.
// Doesn't guarantee to work on all devices. Some devices require root access rights to read sensors information, in that case 0.0 will be returned
static CORE_API float GetCPUTemperature();
static CORE_API void UpdateDeviceOrientation();
static void SaveDeviceOrientation(EDeviceScreenOrientation NewDeviceOrentation) { DeviceOrientation = NewDeviceOrentation; }
// Window access is locked by the game thread before preinit and unlocked here after RHIInit
static CORE_API void UnlockAndroidWindow();
static CORE_API TArray<int32> GetSupportedNativeDisplayRefreshRates();
static CORE_API bool SetNativeDisplayRefreshRate(int32 RefreshRate);
static CORE_API int32 GetNativeDisplayRefreshRate();
/**
* Returns whether or not a 16 bit index buffer should be promoted to 32 bit on load, needed for some Android devices
*/
static CORE_API bool Expand16BitIndicesTo32BitOnLoad();
/**
* Will return true if we wish to propagate the alpha to the backbuffer
*/
static CORE_API int GetMobilePropagateAlphaSetting();
static CORE_API bool SupportsBackbufferSampling();
static CORE_API void SetMemoryWarningHandler(void (*Handler)(const FGenericMemoryWarningContext& Context));
static CORE_API bool HasMemoryWarningHandler();
// Android specific requesting of exit, *ONLY* use this function in signal handling code. Otherwise normal RequestExit functions
static CORE_API void NonReentrantRequestExit();
// Register/Get thread names for Android specific threads
static CORE_API void RegisterThreadName(const char* Name, uint32 ThreadId);
static CORE_API const char* GetThreadName(uint32 ThreadId);
static CORE_API void ShowConsoleWindow();
static CORE_API FDelegateHandle AddNetworkListener(FOnNetworkConnectionChangedDelegate&& InNewDelegate);
static CORE_API bool RemoveNetworkListener(FDelegateHandle Handle);
private:
static CORE_API const ANSICHAR* CodeToString(int Signal, int si_code);
static CORE_API EDeviceScreenOrientation DeviceOrientation;
#if USE_ANDROID_JNI
enum class EAndroidScreenOrientation
{
SCREEN_ORIENTATION_UNSPECIFIED = -1,
SCREEN_ORIENTATION_LANDSCAPE = 0,
SCREEN_ORIENTATION_PORTRAIT = 1,
SCREEN_ORIENTATION_USER = 2,
SCREEN_ORIENTATION_BEHIND = 3,
SCREEN_ORIENTATION_SENSOR = 4,
SCREEN_ORIENTATION_NOSENSOR = 5,
SCREEN_ORIENTATION_SENSOR_LANDSCAPE = 6,
SCREEN_ORIENTATION_SENSOR_PORTRAIT = 7,
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8,
SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9,
SCREEN_ORIENTATION_FULL_SENSOR = 10,
SCREEN_ORIENTATION_USER_LANDSCAPE = 11,
SCREEN_ORIENTATION_USER_PORTRAIT = 12,
};
static CORE_API int32 GetAndroidScreenOrientation(EDeviceScreenOrientation ScreenOrientation);
#endif // USE_ANDROID_JNI
};
'UNREAL ENGINE' 카테고리의 다른 글
[1편] PipelineStateCache 문제점 해결을 위한 코드 트래킹. (0) | 2025.03.19 |
---|---|
Plugin 개발만 git 으로 관리 할 때 플러그인 경로 (0) | 2025.03.14 |
Enhanced Input 변경사항 적용법.[CL 39908272 by ben hoffman in ue5-main branch] (0) | 2025.03.12 |
5.5.3 또 다른 버그. 스켈레탈 애니메이션 업데이트 (0) | 2025.03.12 |
Fix shading model permutation for Mobile Deferred #12953 (0) | 2025.03.04 |