Files
UnrealEngineUWP/Engine/Source/Developer/IOS/IOSTargetPlatform/Private/IOSTargetDeviceOutput.inl
jack porter e4eda780ba Support for Device Output Window iOS log and console command sending using libimobiledevice
#rb Axel.Riffard
#jira UE-103878
#preflight 61d79f4c1f62d3ad4d6a0aee

#ROBOMERGE-AUTHOR: jack.porter
#ROBOMERGE-SOURCE: CL 18539330 in //UE5/Release-5.0/... via CL 18539345
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v899-18417669)

[CL 18539355 by jack porter in ue5-release-engine-test branch]
2022-01-06 21:34:01 -05:00

116 lines
3.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CoreTypes.h"
#include "CoreFwd.h"
#include "Logging/LogMacros.h"
#include "Common/TcpSocketBuilder.h"
#include "string.h"
class FIOSDeviceOutputReaderRunnable;
class FIOSTargetDevice;
class FIOSTargetDeviceOutput;
inline FIOSDeviceOutputReaderRunnable::FIOSDeviceOutputReaderRunnable(const FString& InDeviceUDID, FOutputDevice* InOutput)
: StopTaskCounter(0)
, DeviceUDID(InDeviceUDID)
, Output(InOutput)
, SyslogReadPipe(nullptr)
, SyslogWritePipe(nullptr)
{
}
inline bool FIOSDeviceOutputReaderRunnable::StartSyslogProcess(void)
{
FString Exe = GetLibImobileDeviceExe("idevicesyslog");
FString Params = FString::Printf(TEXT(" -u %s -m [UE]"), *DeviceUDID);
SyslogProcHandle = FPlatformProcess::CreateProc(*Exe, *Params, true, false, false, NULL, 0, NULL, SyslogWritePipe);
return SyslogProcHandle.IsValid();
}
inline bool FIOSDeviceOutputReaderRunnable::Init(void)
{
FPlatformProcess::CreatePipe(SyslogReadPipe, SyslogWritePipe);
return StartSyslogProcess();
}
inline void FIOSDeviceOutputReaderRunnable::Exit(void)
{
if (SyslogProcHandle.IsValid())
{
FPlatformProcess::TerminateProc(SyslogProcHandle);
}
FPlatformProcess::ClosePipe(SyslogReadPipe, SyslogWritePipe);
}
inline void FIOSDeviceOutputReaderRunnable::Stop(void)
{
StopTaskCounter.Increment();
}
inline uint32 FIOSDeviceOutputReaderRunnable::Run(void)
{
FString SyslogOutput;
while (StopTaskCounter.GetValue() == 0 && SyslogProcHandle.IsValid())
{
if (!FPlatformProcess::IsProcRunning(SyslogProcHandle))
{
// When user plugs out USB cable idevicesyslog process stops
// Keep trying to restore idevicesyslog connection until code that uses this object will not kill us
Output->Serialize(TEXT("Trying to restore connection to device..."), ELogVerbosity::Log, NAME_None);
FPlatformProcess::CloseProc(SyslogProcHandle);
if (StartSyslogProcess())
{
FPlatformProcess::Sleep(1.0f);
}
else
{
Output->Serialize(TEXT("Failed to start idevicesyslog proccess"), ELogVerbosity::Log, NAME_None);
Stop();
}
}
else
{
SyslogOutput.Append(FPlatformProcess::ReadPipe(SyslogReadPipe));
if (SyslogOutput.Len() > 0)
{
TArray<FString> OutputLines;
SyslogOutput.ParseIntoArray(OutputLines, TEXT("\n"), false);
if (!SyslogOutput.EndsWith(TEXT("\n")))
{
// partial line at the end, do not serialize it until we receive remainder
SyslogOutput = OutputLines.Last();
OutputLines.RemoveAt(OutputLines.Num() - 1);
}
else
{
SyslogOutput.Reset();
}
for (int32 i = 0; i < OutputLines.Num(); ++i)
{
Output->Serialize(*OutputLines[i], ELogVerbosity::Log, NAME_None);
}
}
FPlatformProcess::Sleep(0.1f);
}
}
return 0;
}
inline bool FIOSTargetDeviceOutput::Init(const FIOSTargetDevice& TargetDevice, FOutputDevice* Output)
{
check(Output);
// Output will be produced by background thread
check(Output->CanBeUsedOnAnyThread());
DeviceName = TargetDevice.GetName();
auto* Runnable = new FIOSDeviceOutputReaderRunnable(TargetDevice.GetId().GetDeviceName(), Output);
DeviceOutputThread = TUniquePtr<FRunnableThread>(FRunnableThread::Create(Runnable, TEXT("FIOSDeviceOutputReaderRunnable")));
return true;
}