ISelfController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Ipc;
  3. using Ryujinx.HLE.HOS.Kernel.Common;
  4. using Ryujinx.HLE.HOS.Kernel.Threading;
  5. using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
  6. using System;
  7. namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
  8. {
  9. class ISelfController : IpcService
  10. {
  11. private readonly ulong _pid;
  12. private KEvent _libraryAppletLaunchableEvent;
  13. private int _libraryAppletLaunchableEventHandle;
  14. private KEvent _accumulatedSuspendedTickChangedEvent;
  15. private int _accumulatedSuspendedTickChangedEventHandle;
  16. private object _fatalSectionLock = new object();
  17. private int _fatalSectionCount;
  18. // TODO: Set this when the game goes in suspension (go back to home menu ect), we currently don't support that so we can keep it set to 0.
  19. private ulong _accumulatedSuspendedTickValue = 0;
  20. // TODO: Determine where those fields are used.
  21. private bool _screenShotPermission = false;
  22. private bool _operationModeChangedNotification = false;
  23. private bool _performanceModeChangedNotification = false;
  24. private bool _restartMessageEnabled = false;
  25. private bool _outOfFocusSuspendingEnabled = false;
  26. private bool _handlesRequestToDisplay = false;
  27. private bool _autoSleepDisabled = false;
  28. private bool _albumImageTakenNotificationEnabled = false;
  29. private bool _recordVolumeMuted = false;
  30. private uint _screenShotImageOrientation = 0;
  31. private uint _idleTimeDetectionExtension = 0;
  32. public ISelfController(ServiceCtx context, ulong pid)
  33. {
  34. _libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
  35. _pid = pid;
  36. }
  37. [CommandHipc(0)]
  38. // Exit()
  39. public ResultCode Exit(ServiceCtx context)
  40. {
  41. Logger.Stub?.PrintStub(LogClass.ServiceAm);
  42. return ResultCode.Success;
  43. }
  44. [CommandHipc(1)]
  45. // LockExit()
  46. public ResultCode LockExit(ServiceCtx context)
  47. {
  48. Logger.Stub?.PrintStub(LogClass.ServiceAm);
  49. return ResultCode.Success;
  50. }
  51. [CommandHipc(2)]
  52. // UnlockExit()
  53. public ResultCode UnlockExit(ServiceCtx context)
  54. {
  55. Logger.Stub?.PrintStub(LogClass.ServiceAm);
  56. return ResultCode.Success;
  57. }
  58. [CommandHipc(3)] // 2.0.0+
  59. // EnterFatalSection()
  60. public ResultCode EnterFatalSection(ServiceCtx context)
  61. {
  62. lock (_fatalSectionLock)
  63. {
  64. _fatalSectionCount++;
  65. }
  66. return ResultCode.Success;
  67. }
  68. [CommandHipc(4)] // 2.0.0+
  69. // LeaveFatalSection()
  70. public ResultCode LeaveFatalSection(ServiceCtx context)
  71. {
  72. ResultCode result = ResultCode.Success;
  73. lock (_fatalSectionLock)
  74. {
  75. if (_fatalSectionCount != 0)
  76. {
  77. _fatalSectionCount--;
  78. }
  79. else
  80. {
  81. result = ResultCode.UnbalancedFatalSection;
  82. }
  83. }
  84. return result;
  85. }
  86. [CommandHipc(9)]
  87. // GetLibraryAppletLaunchableEvent() -> handle<copy>
  88. public ResultCode GetLibraryAppletLaunchableEvent(ServiceCtx context)
  89. {
  90. _libraryAppletLaunchableEvent.ReadableEvent.Signal();
  91. if (_libraryAppletLaunchableEventHandle == 0)
  92. {
  93. if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != KernelResult.Success)
  94. {
  95. throw new InvalidOperationException("Out of handles!");
  96. }
  97. }
  98. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_libraryAppletLaunchableEventHandle);
  99. Logger.Stub?.PrintStub(LogClass.ServiceAm);
  100. return ResultCode.Success;
  101. }
  102. [CommandHipc(10)]
  103. // SetScreenShotPermission(u32)
  104. public ResultCode SetScreenShotPermission(ServiceCtx context)
  105. {
  106. bool screenShotPermission = context.RequestData.ReadBoolean();
  107. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { screenShotPermission });
  108. _screenShotPermission = screenShotPermission;
  109. return ResultCode.Success;
  110. }
  111. [CommandHipc(11)]
  112. // SetOperationModeChangedNotification(b8)
  113. public ResultCode SetOperationModeChangedNotification(ServiceCtx context)
  114. {
  115. bool operationModeChangedNotification = context.RequestData.ReadBoolean();
  116. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { operationModeChangedNotification });
  117. _operationModeChangedNotification = operationModeChangedNotification;
  118. return ResultCode.Success;
  119. }
  120. [CommandHipc(12)]
  121. // SetPerformanceModeChangedNotification(b8)
  122. public ResultCode SetPerformanceModeChangedNotification(ServiceCtx context)
  123. {
  124. bool performanceModeChangedNotification = context.RequestData.ReadBoolean();
  125. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { performanceModeChangedNotification });
  126. _performanceModeChangedNotification = performanceModeChangedNotification;
  127. return ResultCode.Success;
  128. }
  129. [CommandHipc(13)]
  130. // SetFocusHandlingMode(b8, b8, b8)
  131. public ResultCode SetFocusHandlingMode(ServiceCtx context)
  132. {
  133. bool unknownFlag1 = context.RequestData.ReadBoolean();
  134. bool unknownFlag2 = context.RequestData.ReadBoolean();
  135. bool unknownFlag3 = context.RequestData.ReadBoolean();
  136. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { unknownFlag1, unknownFlag2, unknownFlag3 });
  137. return ResultCode.Success;
  138. }
  139. [CommandHipc(14)]
  140. // SetRestartMessageEnabled(b8)
  141. public ResultCode SetRestartMessageEnabled(ServiceCtx context)
  142. {
  143. bool restartMessageEnabled = context.RequestData.ReadBoolean();
  144. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { restartMessageEnabled });
  145. _restartMessageEnabled = restartMessageEnabled;
  146. return ResultCode.Success;
  147. }
  148. [CommandHipc(16)] // 2.0.0+
  149. // SetOutOfFocusSuspendingEnabled(b8)
  150. public ResultCode SetOutOfFocusSuspendingEnabled(ServiceCtx context)
  151. {
  152. bool outOfFocusSuspendingEnabled = context.RequestData.ReadBoolean();
  153. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { outOfFocusSuspendingEnabled });
  154. _outOfFocusSuspendingEnabled = outOfFocusSuspendingEnabled;
  155. return ResultCode.Success;
  156. }
  157. [CommandHipc(19)] // 3.0.0+
  158. // SetScreenShotImageOrientation(u32)
  159. public ResultCode SetScreenShotImageOrientation(ServiceCtx context)
  160. {
  161. uint screenShotImageOrientation = context.RequestData.ReadUInt32();
  162. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { screenShotImageOrientation });
  163. _screenShotImageOrientation = screenShotImageOrientation;
  164. return ResultCode.Success;
  165. }
  166. [CommandHipc(40)]
  167. // CreateManagedDisplayLayer() -> u64
  168. public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
  169. {
  170. context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, _pid);
  171. context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
  172. context.ResponseData.Write(layerId);
  173. return ResultCode.Success;
  174. }
  175. [CommandHipc(41)] // 4.0.0+
  176. // IsSystemBufferSharingEnabled()
  177. public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context)
  178. {
  179. // NOTE: Service checks a private field and return an error if the SystemBufferSharing is disabled.
  180. return ResultCode.NotImplemented;
  181. }
  182. [CommandHipc(44)] // 10.0.0+
  183. // CreateManagedDisplaySeparableLayer() -> (u64, u64)
  184. public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
  185. {
  186. context.Device.System.SurfaceFlinger.CreateLayer(out long displayLayerId, _pid);
  187. context.Device.System.SurfaceFlinger.CreateLayer(out long recordingLayerId, _pid);
  188. context.Device.System.SurfaceFlinger.SetRenderLayer(displayLayerId);
  189. context.ResponseData.Write(displayLayerId);
  190. context.ResponseData.Write(recordingLayerId);
  191. return ResultCode.Success;
  192. }
  193. [CommandHipc(50)]
  194. // SetHandlesRequestToDisplay(b8)
  195. public ResultCode SetHandlesRequestToDisplay(ServiceCtx context)
  196. {
  197. bool handlesRequestToDisplay = context.RequestData.ReadBoolean();
  198. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { handlesRequestToDisplay });
  199. _handlesRequestToDisplay = handlesRequestToDisplay;
  200. return ResultCode.Success;
  201. }
  202. [CommandHipc(62)]
  203. // SetIdleTimeDetectionExtension(u32)
  204. public ResultCode SetIdleTimeDetectionExtension(ServiceCtx context)
  205. {
  206. uint idleTimeDetectionExtension = context.RequestData.ReadUInt32();
  207. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { idleTimeDetectionExtension });
  208. _idleTimeDetectionExtension = idleTimeDetectionExtension;
  209. return ResultCode.Success;
  210. }
  211. [CommandHipc(63)]
  212. // GetIdleTimeDetectionExtension() -> u32
  213. public ResultCode GetIdleTimeDetectionExtension(ServiceCtx context)
  214. {
  215. context.ResponseData.Write(_idleTimeDetectionExtension);
  216. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { _idleTimeDetectionExtension });
  217. return ResultCode.Success;
  218. }
  219. [CommandHipc(65)]
  220. // ReportUserIsActive()
  221. public ResultCode ReportUserIsActive(ServiceCtx context)
  222. {
  223. // TODO: Call idle:sys ReportUserIsActive when implemented.
  224. Logger.Stub?.PrintStub(LogClass.ServiceAm);
  225. return ResultCode.Success;
  226. }
  227. [CommandHipc(68)]
  228. // SetAutoSleepDisabled(u8)
  229. public ResultCode SetAutoSleepDisabled(ServiceCtx context)
  230. {
  231. bool autoSleepDisabled = context.RequestData.ReadBoolean();
  232. _autoSleepDisabled = autoSleepDisabled;
  233. return ResultCode.Success;
  234. }
  235. [CommandHipc(69)]
  236. // IsAutoSleepDisabled() -> u8
  237. public ResultCode IsAutoSleepDisabled(ServiceCtx context)
  238. {
  239. context.ResponseData.Write(_autoSleepDisabled);
  240. return ResultCode.Success;
  241. }
  242. [CommandHipc(80)] // 4.0.0+
  243. // SetWirelessPriorityMode(s32 wireless_priority_mode)
  244. public ResultCode SetWirelessPriorityMode(ServiceCtx context)
  245. {
  246. WirelessPriorityMode wirelessPriorityMode = (WirelessPriorityMode)context.RequestData.ReadInt32();
  247. if (wirelessPriorityMode > WirelessPriorityMode.Unknown2)
  248. {
  249. return ResultCode.InvalidParameters;
  250. }
  251. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { wirelessPriorityMode });
  252. return ResultCode.Success;
  253. }
  254. [CommandHipc(90)] // 6.0.0+
  255. // GetAccumulatedSuspendedTickValue() -> u64
  256. public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context)
  257. {
  258. context.ResponseData.Write(_accumulatedSuspendedTickValue);
  259. return ResultCode.Success;
  260. }
  261. [CommandHipc(91)] // 6.0.0+
  262. // GetAccumulatedSuspendedTickChangedEvent() -> handle<copy>
  263. public ResultCode GetAccumulatedSuspendedTickChangedEvent(ServiceCtx context)
  264. {
  265. if (_accumulatedSuspendedTickChangedEventHandle == 0)
  266. {
  267. _accumulatedSuspendedTickChangedEvent = new KEvent(context.Device.System.KernelContext);
  268. _accumulatedSuspendedTickChangedEvent.ReadableEvent.Signal();
  269. if (context.Process.HandleTable.GenerateHandle(_accumulatedSuspendedTickChangedEvent.ReadableEvent, out _accumulatedSuspendedTickChangedEventHandle) != KernelResult.Success)
  270. {
  271. throw new InvalidOperationException("Out of handles!");
  272. }
  273. }
  274. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_accumulatedSuspendedTickChangedEventHandle);
  275. return ResultCode.Success;
  276. }
  277. [CommandHipc(100)] // 7.0.0+
  278. // SetAlbumImageTakenNotificationEnabled(u8)
  279. public ResultCode SetAlbumImageTakenNotificationEnabled(ServiceCtx context)
  280. {
  281. bool albumImageTakenNotificationEnabled = context.RequestData.ReadBoolean();
  282. _albumImageTakenNotificationEnabled = albumImageTakenNotificationEnabled;
  283. return ResultCode.Success;
  284. }
  285. [CommandHipc(120)] // 11.0.0+
  286. // SaveCurrentScreenshot(s32 album_report_option)
  287. public ResultCode SaveCurrentScreenshot(ServiceCtx context)
  288. {
  289. AlbumReportOption albumReportOption = (AlbumReportOption)context.RequestData.ReadInt32();
  290. if (albumReportOption > AlbumReportOption.Unknown3)
  291. {
  292. return ResultCode.InvalidParameters;
  293. }
  294. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { albumReportOption });
  295. return ResultCode.Success;
  296. }
  297. [CommandHipc(130)] // 13.0.0+
  298. // SetRecordVolumeMuted(b8)
  299. public ResultCode SetRecordVolumeMuted(ServiceCtx context)
  300. {
  301. bool recordVolumeMuted = context.RequestData.ReadBoolean();
  302. Logger.Stub?.PrintStub(LogClass.ServiceAm, new { recordVolumeMuted });
  303. _recordVolumeMuted = recordVolumeMuted;
  304. return ResultCode.Success;
  305. }
  306. }
  307. }