编辑: 在没有任何答案的情况下,我做了一些重大的新发现并对这个问题进行了大量的编辑。
历史上/据我所知,在关闭显示模式下让您的Mac保持清醒,并且不符合Apple的要求,只能通过一个内核扩展(kext)或以root身份运行的命令来实现。然而,最近我发现还必须有另一种方法。我真的需要一些帮助,找出如何使其在(100%免费,无IAP)沙箱化的Mac App Store(MAS)兼容应用程序中使用。
我已确认其他MAS应用程序能够做到这一点,看起来它们可能会向名为clamshellSleepDisabled
的键中写入YES
。或者也许有其他的诡计导致键值被设置为YES?我在IOPMrootDomain.cpp中找到了该函数:void IOPMrootDomain::setDisableClamShellSleep( bool val )
{
if (gIOPMWorkLoop->inGate() == false) {
gIOPMWorkLoop->runAction(
OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setDisableClamShellSleep),
(OSObject *)this,
(void *)val);
return;
}
else {
DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val);
if ( clamshellSleepDisabled != val )
{
clamshellSleepDisabled = val;
// If clamshellSleepDisabled is reset to 0, reevaluate if
// system need to go to sleep due to clamshell state
if ( !clamshellSleepDisabled && clamshellClosed)
handlePowerNotification(kLocalEvalClamshellCommand);
}
}
}
我想尝试一下并查看是否只需要这样,但我不知道如何调用此函数。它显然不是IOPMrootDomain文档的一部分,而且我似乎找不到任何有用的示例代码来处理在IOPMrootDomain文档中的函数,例如
setAggressiveness
或setPMAssertionLevel
。这里是Console根据幕后情况的一些证据:
我有一点使用IOMProotDomain的经验,通过为另一个项目调整ControlPlane的源代码来适应它,但我不知道如何开始。任何帮助都将不胜感激。谢谢!编辑: 在@pmdj的贡献/答案下,这个问题已经解决了!
完整示例项目: https://github.com/x74353/CDMManager 最终结果非常简单/直接:
1.导入头文件:
#import <IOKit/pwr_mgt/IOPMLib.h>
2. 在你的实现文件中添加这个函数:
IOReturn RootDomain_SetDisableClamShellSleep (io_connect_t root_domain_connection, bool disable)
{
uint32_t num_outputs = 0;
uint32_t input_count = 1;
uint64_t input[input_count];
input[0] = (uint64_t) { disable ? 1 : 0 };
return IOConnectCallScalarMethod(root_domain_connection, kPMSetClamshellSleepState, input, input_count, NULL, &num_outputs);
}
3. 使用以下代码从实现的其他位置调用上述函数:
io_connect_t connection = IO_OBJECT_NULL;
io_service_t pmRootDomain = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPMrootDomain"));
IOServiceOpen (pmRootDomain, current_task(), 0, &connection);
// 'enable' is a bool you should assign a YES or NO value to prior to making this call
RootDomain_SetDisableClamShellSleep(connection, enable);
IOServiceClose(connection);