iosiphonejailbreakcydia-substrate

How to change "Call Waiting" programmatically in iOS (jailbreak device)?


I wan't to turn on/off the call waiting feature of iPhone (that can be found at Settings > Phone > Call Waiting) programmatically.

What I have figured out is that the phone settings calls -setCallWaitingEnabled:specifier: method from PhoneSettingsCallWaitingController class found here. I found it in /System/Library/PreferenceBundles/MobilePhoneSettings.bundle/Call Waiting.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>id</key>
    <string>com.apple.preferences.phone.call-waiting</string>
    <key>items</key>
    <array>
        <dict>
            <key>cell</key>
            <string>PSGroupCell</string>
        </dict>
        <dict>
            <key>cell</key>
            <string>PSSwitchCell</string>
            <key>get</key>
            <string>callWaitingEnabled:</string>
            <key>label</key>
            <string>Call Waiting</string>
            <key>set</key>
            <string>setCallWaitingEnabled:specifier:</string>
        </dict>
    </array>
    <key>title</key>
    <string>Call Waiting</string>
</dict>
</plist>

I loaded the bundle manually and initialized the above class and called the method I said but nothing happens. Here's the code:

NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PreferenceBundles/MobilePhoneSettings.bundle"];
BOOL success = [b load];
if (success)
{

    NSLog(@"\n\n\n\n Bundle load successfull! \n\n\n\n ");
    Class PhoneSettingsCallWaitingController = NSClassFromString(@"PhoneSettingsCallWaitingController");
    id tc = [[PhoneSettingsCallWaitingController alloc] init];

    [tc setCallWaitingEnabled:0 specifier:0];

} else NSLog(@"\n\n\n\n Bundle load failure! \n\n\n\n ");

I don't know if I'm in the correct path. Is there another way to turn on/off the Call Waiting setting?


Solution

  • Declarations for CoreTelephony.framework private APIs

    CF_EXTERN_C_BEGIN
    
    CF_EXPORT CFNotificationCenterRef CTTelephonyCenterGetDefault();
    CF_EXPORT void CTTelephonyCenterAddObserver(CFNotificationCenterRef center, const void *observer, CFNotificationCallback callBack, CFStringRef name, const void *object, CFNotificationSuspensionBehavior suspensionBehavior);
    
    CF_EXPORT void CTSettingRequest(NSDictionary* dict);
    CF_EXPORT void CTSettingSave(NSDictionary* dict);
    
    CF_EXPORT NSString* kCTSettingCallClassVoice;
    CF_EXPORT NSString* kCTSettingTypeCallWaiting;
    CF_EXPORT NSString* kCTSettingType;
    CF_EXPORT NSString* kCTSettingCallClass;
    CF_EXPORT NSString* kCTSettingEnabled;
    
    CF_EXTERN_C_END
    

    Setting requests and saves are done asynchronously. Results will be sent to telephony center callback:

    void SettingCallback(CFNotificationCallback center, void* observer, NSString* name, const void* objec, NSDictionary* userInfo)
    {
        if ([name isEqualToString:@"kCTSettingRequestSuccessNotification"])
        {
            //Setting request results are in 'userInfo' argument
        }
        else if ([name isEqualToString:@"kCTSettingRequestErrorNotification"])
        {
            //Setting request error
        }
        else if ([name isEqualToString:@"kCTSettingSaveSuccessNotification"])
        {
            //Setting saved
        }
        else if ([name isEqualToString:@"kCTSettingSaveErrorNotification"])
        {
            //Setting save error
        }
    }
    
    ...
    
    CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, SettingCallback, NULL, NULL, CFNotificationSuspensionBehaviorHold);
    

    Request call waiting setting:

    CTSettingRequest(@{@"STSettingTypeUniqueIdentifier" : kCTSettingTypeCallWaiting,
                       kCTSettingCallClass : kCTSettingCallClassVoice, 
                       kCTSettingType : kCTSettingTypeCallWaiting});
    

    Save call waiting setting (in this case, enabled):

    CTSettingSave(@{@"STSettingTypeUniqueIdentifier" : kCTSettingTypeCallWaiting,
                    kCTSettingCallClass : kCTSettingCallClassVoice, 
                    kCTSettingType : kCTSettingTypeCallWaiting, 
                    kCTSettingEnabled : @YES});