Keep display on when the proximity sensor is covered

后端 未结 5 1119
隐瞒了意图╮
隐瞒了意图╮ 2021-02-05 12:39

I want to intercept the proximity sensor without turning off the display.

I know by the documentation that I have two Bool variables:

proximityMonitoring         


        
5条回答
  •  一个人的身影
    2021-02-05 13:27

    Although there is no public API to do this, you can hook into IOKit's IOHIDEventSystem and listen for screen dimming notifications:

    // Create and open an event system.
    IOHIDEventSystemRef system = IOHIDEventSystemCreate(NULL);
    
    // Set the PrimaryUsagePage and PrimaryUsage that the AppleProxShim service uses
    int page = 65280;
    int usage = 8;
    
    // Create a dictionary to match the service with
    CFStringRef keys[2];
    CFNumberRef nums[2];
    keys[0] = CFStringCreateWithCString(0, "PrimaryUsagePage", 0);
    keys[1] = CFStringCreateWithCString(0, "PrimaryUsage", 0);
    nums[0] = CFNumberCreate(0, kCFNumberSInt32Type, &page);
    nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage);
    CFDictionaryRef dict = CFDictionaryCreate(0, (const void**)keys, (const void**)nums, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    // Get the total of matching services with the above criteria
    CFArrayRef srvs = (CFArrayRef)IOHIDEventSystemCopyMatchingServices(system, dict, 0, 0, 0, 0);
    
    // Get the service
    IOHIDServiceRef serv = (IOHIDServiceRef)CFArrayGetValueAtIndex(srvs, 0);
    int interval = 1 ;
    
    // Set an interval of 1 , to activate the sensor  
    IOHIDServiceSetProperty((IOHIDServiceRef)serv, CFSTR("ReportInterval"), CFNumberCreate(0, kCFNumberSInt32Type, &interval));
    
    // add your event handler
    IOHIDEventSystemOpen(system, handle_event, NULL, NULL, NULL);
    int defaultInterval = 0;
    IOHIDServiceSetProperty((IOHIDServiceRef)serv, CFSTR("ReportInterval"), CFNumberCreate(0, kCFNumberSInt32Type, &defaultInterval));
    
    // close handles and release the IOHIDEventSystemRef
    IOHIDEventSystemClose(system, NULL);
    CFRelease(system);
    

    Your event handler function pointer will look something like this:

    void handle_event(void* target, void* refcon, IOHIDServiceRef service, IOHIDEventRef event) {
        if (IOHIDEventGetType(event) == kIOHIDEventTypeProximity) { // Proximity Event Received
            // not necessary, but if you want the value from the sensor, get it from IOHIDEventGetIntegerValue
            int proximityValue = IOHIDEventGetIntegerValue(event, (IOHIDEventField)kIOHIDEventFieldProximityDetectionMask); // Get the value of the ProximityChanged Field (0 or 64)
    
            // Call dimScreen with the boolean NO
            int (*SBSSpringBoardServerPort)() = (int (*)())dlsym(RTLD_DEFAULT, "SBSSpringBoardServerPort");
            int port = SBSSpringBoardServerPort(); 
            void (*_SBDimScreen)(int _port,BOOL shouldDim) = (void (*)(int _port,BOOL shouldDim))dlsym(RTLD_DEFAULT, "SBDimScreen");
    
            // This is where the logic to dim the screen based on the sensor value would go.  In this case, I'm hardcoding NO instead of the value of proximityValue from above
            // BOOL dim = proximityValue == 0 ? NO : YES;
            _SBDimScreen(port, NO); 
        }
    }
    

    Calling _SBDimScreen may not even be necessary, as having an empty function pointer may stop all proximity sensor events.

    Code modified from the command line tool example on the AppleProxShim page on the iPhoneDevWiki.

提交回复
热议问题