I have a SpringBoard hook which listens to Distributed notifications. Various other apps I have hooked post notification which are received in SpringBoard.
If I pass userInfo as null, SpringBoard receives notifications from all apps. If I pass CFDictionaryRef as userInfo, SpringBoard receives notifications from only SpringBoard and SystemApps. However user apps are not able to send notifications. (Or rather not received by Springboard).
CFDictionaryRef is innocent and not the culprit because I am able to pass it when sender and receiver are system apps.
Is there a restriction that User Apps cannot send userInfo object to System Apps?
EDIT: Attaching the code. I compile it using iOSOpenDev. Rely on NSLog to debug. Scenario 1: If you touch SpringBoard, you would see 2 logs for notification send and notification received. Scenario 2: Invoke any system app like clock etc, you would see both logs. Scenario 3: Any app from app store, like SketchBookX etc, and only one log will be printed for notification send. Its not received.
I have tried all flavors of CFNotificationCenterPostNotification but nothing works.
#import <UIKit/UIKit.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFNotificationCenter.h>
#include "GraphicsServices/GSEvent.h"
#define GS_EVENT_TYPE_OFFSET 2
#define HOME_DOWN 1000
#define HOME_UP 1001
#define VOL_DOWN_KEY_DOWN 1008
#define VOL_DOWN_KEY_UP 1009
extern "C" CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void);
void LogEvent(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
NSString *str = [[NSString alloc]initWithFormat:@"%@,%@,%d,%d,%d,%d,%d\r\n",
(NSString*)CFDictionaryGetValue(userInfo,@"strWindow"),
(NSString*)CFDictionaryGetValue(userInfo,@"strView"),
[(NSNumber*)CFDictionaryGetValue(userInfo,@"phase") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"xInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"yInView") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"xInWindow") intValue],
[(NSNumber*)CFDictionaryGetValue(userInfo,@"yInWindow") intValue]];
NSLog(@"Area51 Notification Received: %@",str);
}
%hook UIApplication
-(void) sendEvent:(UIEvent*)event
{
if( [NSStringFromClass([event class]) isEqualToString:@"UITouchesEvent"] )
{
NSSet *touches = [event allTouches];
NSEnumerator *enumerator = [touches objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
UITouch *touch = value;
NSString *strViewClassName;
if(!touch.view)
strViewClassName = @" ";
else
strViewClassName = [NSString stringWithString:NSStringFromClass([[touch view] class])];
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL,0,&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(dictionary, @"phase", [NSNumber numberWithInt:[touch phase]] );
CFDictionaryAddValue(dictionary, @"strWindow", NSStringFromClass([[touch window] class]) );
CFDictionaryAddValue(dictionary, @"strView", strViewClassName);
CFDictionaryAddValue(dictionary, @"xInView", [NSNumber numberWithInt:[touch locationInView:touch.view].x]) ;
CFDictionaryAddValue(dictionary, @"yInView", [NSNumber numberWithInt:[touch locationInView:touch.view].y]) ;
CFDictionaryAddValue(dictionary, @"xInWindow", [NSNumber numberWithInt:[touch locationInView:nil].x]) ;
CFDictionaryAddValue(dictionary, @"yInWindow", [NSNumber numberWithInt:[touch locationInView:nil].y]) ;
CFNotificationCenterPostNotificationWithOptions(
CFNotificationCenterGetDistributedCenter(),
(CFStringRef)@"RecordTouch",
NULL,
dictionary,
kCFNotificationDeliverImmediately|kCFNotificationPostToAllSessions);
NSLog(@"Area 51: Notification Send for App: %@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] );
}
}
%orig;
}
%end
%hook SpringBoard
-(void)applicationDidFinishLaunching:(UIApplication*) application
{
CFNotificationCenterAddObserver(
CFNotificationCenterGetDistributedCenter(),
NULL,
LogEvent,
NULL,
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
NSLog(@"Area51: ObserverAdded");
%orig;
}
%end
__attribute__((constructor)) void area51init() {
%init;
}