newLibraryWithStitchedDescriptor fails with XPC Error - metal

I'm trying to build a stitched metal kernel. My shader code is
[[stitchable]] float add(float a, float b) {
return a + b;
}
[[stitchable]] float load(constant float *a, uint32_t index) {
return a[index];
}
[[stitchable]] void store(device float *a, float value, uint32_t index) {
a[index] = value;
}
[[visible]] void two_inputs(constant float *a, constant float *b, device *c, uint32_t tid);
The driver code is
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> queue = [device newCommandQueue];
id<MTLLibrary> library = [device newDefaultLibrary];
NSArray *functions = #[
[library newFunctionWithName:#"add"],
[library newFunctionWithName:#"load"],
[library newFunctionWithName:#"store"]
];
MTLFunctionStitchingInputNode *srcA = [[MTLFunctionStitchingInputNode alloc] initWithArgumentIndex:0];
MTLFunctionStitchingInputNode *srcB = [[MTLFunctionStitchingInputNode alloc] initWithArgumentIndex:1];
MTLFunctionStitchingInputNode *srcC = [[MTLFunctionStitchingInputNode alloc] initWithArgumentIndex:2];
MTLFunctionStitchingInputNode *srcI = [[MTLFunctionStitchingInputNode alloc] initWithArgumentIndex:3];
MTLFunctionStitchingFunctionNode *loadA = [[MTLFunctionStitchingFunctionNode alloc] initWithName:#"load" arguments:#[srcA, srcI] controlDependencies:#[]];
MTLFunctionStitchingFunctionNode *loadB = [[MTLFunctionStitchingFunctionNode alloc] initWithName:#"load" arguments:#[srcA, srcI] controlDependencies:#[]];
MTLFunctionStitchingFunctionNode *add = [[MTLFunctionStitchingFunctionNode alloc] initWithName:#"load" arguments:#[loadA, loadB] controlDependencies:#[]];
MTLFunctionStitchingFunctionNode *storeC = [[MTLFunctionStitchingFunctionNode alloc] initWithName:#"load" arguments:#[srcC, add, srcI] controlDependencies:#[]];
MTLFunctionStitchingGraph *graph = [[MTLFunctionStitchingGraph alloc] initWithFunctionName:#"two_inputs" nodes:#[loadA, loadB, add] outputNode:storeC attributes:#[]];
MTLStitchedLibraryDescriptor *graphDescriptor = [MTLStitchedLibraryDescriptor new];
graphDescriptor.functions = functions;
graphDescriptor.functionGraphs = #[graph];
NSError *error = NULL;
id<MTLLibrary> graphLibrary = [device newLibraryWithStitchedDescriptor: graphDescriptor.functions error:&error];
NSLog(#"%#", error);
This is causing the metal compiler to fail with the error.
Compiler failed with XPC_ERROR_CONNECTION_INTERRUPTED
MTLCompiler: Compilation failed with XPC_ERROR_CONNECTION_INTERRUPTED on 1 try
...
Error Domain=MTLLibraryErrorDomain Code=3 "Compiler encountered an internal error" UserInfo={NSLocalizedDescription=Compiler encountered an internal error}
I'm trying to run this on an M1 mac.

It turns out the reason the Metal compiler was crashing was this line
MTLFunctionStitchingGraph *graph = [[MTLFunctionStitchingGraph alloc] initWithFunctionName:#"two_inputs" nodes:#[loadA, loadB, add] outputNode:storeC attributes:#[]];
should be
MTLFunctionStitchingGraph *graph = [[MTLFunctionStitchingGraph alloc] initWithFunctionName:#"two_inputs" nodes:#[loadA, loadB, add, storeC] outputNode:NULL attributes:#[]];
instead.

Related

MPSGraph assign variable operation is not updating value

I'm trying to understand the MPSGraph api. Why does the following code failing to change the value of var after the second run call?
#import <Foundation/Foundation.h>
#import <MetalPerformanceShadersGraph/MetalPerformanceShadersGraph.h>
void run(void);
void run(void) {
MPSGraph *graph = [MPSGraph new];
float test1 = 2.0;
float test2 = 3.0;
MPSGraphTensor *constant = [graph constantWithScalar:test1
dataType:MPSDataTypeFloat32];
MPSGraphTensor *var = [graph variableWithData:[NSData dataWithBytes:&test2 length:sizeof(test2)]
shape:#[#1]
dataType:MPSDataTypeFloat32
name:#"var"];
MPSGraphTensorDataDictionary *result = [graph runWithFeeds:#{}
targetTensors:#[constant, var]
targetOperations:NULL];
float test3;
NSInteger temp = sizeof(test3);
[result[var].mpsndarray readBytes:&test3
strideBytes:&temp];
NSLog(#"%f", test3);
[result[constant].mpsndarray readBytes:&test3
strideBytes:&temp];
NSLog(#"%f", test3);
MPSGraphOperation *op = [graph assignVariable:var
withValueOfTensor:constant
name:NULL];
result = [graph runWithFeeds:#{}
targetTensors:#[var]
targetOperations:#[op]];
[result[var].mpsndarray readBytes:&test3
strideBytes:&temp];
NSLog(#"%f", test3);
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
run();
}
return 0;
}
Output:
2022-09-27 13:26:35.708641-0400 MPSGraphExample[9643:2669233] Metal API Validation Enabled
2022-09-27 13:26:35.732058-0400 MPSGraphExample[9643:2669233] 3.000000
2022-09-27 13:26:35.732097-0400 MPSGraphExample[9643:2669233] 2.000000
2022-09-27 13:26:35.733821-0400 MPSGraphExample[9643:2669233] 3.000000
Program ended with exit code: 0
It turns out that the operation is applied after the tensor is evaluated. Changing it to
[graph runWithFeeds:#{}
targetTensors:#[]
targetOperations:#[op]];
result = [graph runWithFeeds:#{}
targetTensors:#[var]
targetOperations:#[]];
now shows the updated values.

Convert array of floats to AVAudioPCMBuffer for speed recognition

I have an array of floats that is raw audio data from a 3rd party source. I would like to pass this through to a Speech Recognition request via appendAudioPCMBuffer but that accepts an AVAudioPCMBuffer. How could I convert my NSMutableArray to AVAudioPCMBuffer?
For reference, this is how the buffer variable gets created before its passed to this function. It is written in C.
void CallNativePlugin( const float buffer[], int size ) {
NSMutableArray *myArray = [[NSMutableArray alloc] init];
for (int i = 0; i < size; i++) {
NSNumber *number = [[NSNumber alloc] initWithFloat:buffer[i]];
[myArray addObject:number];
[delegateObject recognizeSpeechFromBuffer:myArray ];
}
}
Then the current code I have to take that buffer and pass is to the speech recognizer (objective-c):
-(void) recognizeSpeechFromBuffer: (NSMutableArray*) buffer {
NSLog( #"Array length: %lu#", (unsigned long) buffer.count );
recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
recognitionRequest.shouldReportPartialResults = YES;
recognitionTask = [speechRecognizer recognitionTaskWithRequest:recognitionRequest.resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
BOOL isFinal = NO;
if (result) {
NSLog(#"RESULT:%#",result.bestTranscription.formattedString);
isFinal = !result.isFinal;
}
if (error) {
recognitionRequest = nil;
recognitionTask = nil;
}
}];
// Do something like [recognitionRequest appendAudioPCMBuffer:buffer];
}
Since Objective-C is available in CallNativePlugin, you could rework it to create the AVAudioPCMBuffer there, assuming you know the audio sample rate and can adjust the delegate protocol.
// Assuming mono, sample rate ????
void CallNativePlugin( const float buffer[], int size ) {
AVAudioFormat *fmt = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:/* ?? */ channels:1 interleaved:YES];
AVAudioPCMBuffer *buf = [[AVAudioPCMBuffer alloc] initWithPCMFormat:fmt frameCapacity:size];
memcpy(buf.floatChannelData[0], buffer, sizeof(float) * size);
buf.frameLength = size;
[delegateObject recognizeSpeechFromPCMBuffer:buf];
}
If that isn't possible you can create an AVAudioPCMBuffer in -recognizeSpeechFromPCMBuffer: similarly and assign the floats individually.

Print UIImage metadata to label

I'm attempting to read the metadata produced by a UIImage when shot from the UIImagePicker, and I'm having some trouble.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// get the metadata
NSDictionary *imageMetadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSLog (#"imageMetaData %#",imageMetadata);
This successfully prints the metadata dictionary to NSLog.
The issue I'm having is that I would like to access specific indices of the dictionary (such as FNumber, ISO, etc.) and print them to specific labels, but I can't figure out how to access the individual data.
Here is what I have tried so far to pull the data, but it doesn't seem to find the key (it returns as NULL):
NSLog(#"ISO: %#", imageMetadata[#"ISOSpeedRatings"]);
Based off of what NSLog prints for the dictionary, it seems as if there may be dictionaries within the dictionary, and that's what's throwing me off.
Here's what gets printed for the metadata:
imageMetaData {
DPIHeight = 72;
DPIWidth = 72;
Orientation = 6;
"{Exif}" = {
ApertureValue = "2.27500704749987";
BrightnessValue = "-0.6309286396300304";
ColorSpace = 1;
DateTimeDigitized = "2015:04:01 10:33:37";
DateTimeOriginal = "2015:04:01 10:33:37";
ExposureBiasValue = 0;
ExposureMode = 0;
ExposureProgram = 2;
ExposureTime = "0.06666666666666667";
FNumber = "2.2";
Flash = 24;
FocalLenIn35mmFilm = 29;
FocalLength = "4.15";
ISOSpeedRatings = (
320
);
LensMake = Apple;
LensModel = "iPhone 6 back camera 4.15mm f/2.2";
LensSpecification = (
"4.15",
"4.15",
"2.2",
"2.2"
);
MeteringMode = 5;
PixelXDimension = 3264;
PixelYDimension = 2448;
SceneType = 1;
SensingMethod = 2;
ShutterSpeedValue = "3.907056515078773";
SubjectArea = (
1631,
1223,
1795,
1077
);
SubsecTimeDigitized = 705;
SubsecTimeOriginal = 705;
WhiteBalance = 0;
};
"{MakerApple}" = {
1 = 2;
14 = 0;
2 = <0f000b00 06000900 04005000 a900b100 b700bb00 c400cd00 cd00a400 b100c700 14000b00 05000900 06000a00 8a00a800 b000b800 c300cb00 c900cd00 b300a600 2f000700 06000700 0a000400 3500a400 ab00b300 bc00c300 cf00d300 b4007f00 3f000700 09000700 0a000700 05007100 a100af00 b500c200 ce00cd00 a9006b00 1f000a00 0b000900 0a000c00 05001e00 9c00aa00 b400c200 cc00d000 d4005700 2b001900 0d001000 10000d00 08000600 5b00a700 b300bf00 cb00d500 e3008600 eb002800 1a001700 14000c00 0b000700 10009400 b100c000 ce00e000 f400bd00 cf013e00 2a001200 17000f00 0d000800 07004200 b100c000 d300e900 fd000401 ff011101 1d000700 16001400 09000700 07000900 8900bf00 d800ec00 07011f01 10021102 39000b00 10001900 0e000800 0a000700 2c00bf00 dd00f400 0b012401 1e023802 1f010d00 07001900 16000c00 0c000800 21007000 c500f400 0a012e01 10022202 01022500 08001000 18001100 0d001800 1601cc00 d100eb00 09012201 fb011002 26020401 0f000700 16001400 3200e801 6001b000 ce00f400 08011601 e1010602 1a020302 23001700 21002300 84009300 9f00ad00 bf00e800 02011401 ca01fc01 19024002 08013d00 3500ca00 7c009200 9e00ab00 c200d700 f8000a01 b401f101 1b024802 28023000 4a007f00 7f008e00 a000b100 bd00d000 ec00fe00>;
3 = {
epoch = 0;
flags = 1;
timescale = 1000000000;
value = 777291330499583;
};
4 = 1;
5 = 128;
6 = 123;
7 = 1;
8 = (
"0.2226092",
"-0.5721548",
"-0.7796207"
);
9 = 275;
};
"{TIFF}" = {
DateTime = "2015:04:01 10:33:37";
Make = Apple;
Model = "iPhone 6";
Software = "8.1.2";
XResolution = 72;
YResolution = 72;
};
}
Is the data I'm looking for within another NSDictionary named Exif? And if so, how do I access it?
#david strauss can you try this once
- (void) saveImage:(UIImage *)imageToSave withInfo:(NSDictionary *)info{
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Get the image metadata (EXIF & TIFF)
NSMutableDictionary * imageMetadata = [[info objectForKey:UIImagePickerControllerMediaMetadata] mutableCopy];
// add GPS data
CLLocation * loc = <•••>; // need a location here
if ( loc ) {
[imageMetadata setObject:[self gpsDictionaryForLocation:loc] forKey:(NSString*)kCGImagePropertyGPSDictionary];
}
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image %# with metadata %# to Photo Library",newURL,imageMetadata);
}
};
// Save the new image to the Camera Roll
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage]
metadata:imageMetadata
completionBlock:imageWriteCompletionBlock];
[imageMetadata release];
[library release];
}
The metadata dictionary as you've noticed consists of several dictionaries.
So to answer your question - yes, if you're looking for specific values you can access the inner dictionaries. Also, you'd better use the proper keys from ImageIO constants; for example:
NSLog(#"%#", imageMetadata[(NSString*)kCGImagePropertyExifDictionary][(NSString*)kCGImagePropertyExifISOSpeedRatings]);
Or, you can use a key-path:
NSString *keyPath = [NSString stringWithFormat:#"%#.%#",
(NSString*)kCGImagePropertyExifDictionary, (NSString*)kCGImagePropertyExifISOSpeedRatings];
NSLog(#"%#", [imageMetadata valueForKeyPath:keyPath]);
your all required data is within this dictionary only.
you can use json formatter to see the exact location of your data.
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject: imageMetadata
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"jsonString: %#", jsonString);
}
after this get the exact location of your data from json

AppAi.de appears to violate sandbox policy [duplicate]

There is an app called "Activity Monitor Touch" in the App Store, which displays background processes as well as free memory.
So there MUST be an public API to access this information. The evidence:
I'm already searching for days but can't find any good starting point. How can this app figure all this stuff out without any jailbreaking / hacking / etc.?
Until recently I was sure that something like this is absolutely impossible on iOS.
I've found this code snippet:
- (NSArray *)runningProcesses {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName", nil]];
[processID release];
[processName release];
[array addObject:dict];
[dict release];
}
free(process);
return [array autorelease];
}
}
}
return nil;
}
But I can't make it run on the iPhone. Xcode doesn't know these symbols:
CTL_KERN, KERN_PROC, KERN_PROC_ALL
So of course I must import a header file or library. Does anyone know where these belong to, and how the headers must be imported to make this work?
Works like a charm:
#import <sys/sysctl.h>
sysctl is no longer accessible to sandboxed iOS 9 apps.
From WWDC 2015 session 703 Privacy and Your App:
In iOS 9, the sandbox now prevents a process from accessing the
kern.proc, kern.procargs, and kern.procargs2 values for other
processes
and
iOS apps are not permitted to see what other apps are running
So even if you find a way, you are likely to get rejected from the App Store.
https://developer.apple.com/videos/play/wwdc2015-703/

how to determine which apps are background and which app is foreground on iOS by application id

Using the method described in this question, I can get a list of apps running on an iOS device.
I know PIDs and have access to their kinfo_proc structures.
How can I determine which are foreground processes and which are background (assuming my app is background)?
I tried to find this out base on information in kinfo_proc (see 1st link), via kp_proc.p_priority, but it looks like it is not possible to infer background/foreground state from priority.
I don't really care if this works correctly for AppStore Review but I would prefer a method that will work without a jailbreak(i.e. Private APIs are ok but which ones?). I want this to work at least on iOS 5
I considered writing a simple MobileSubstrate extension, injecting it into all apps and just hook everyone's applicationDidBecomeActive, but this requires a jailbreak and is too invasive.
Well, looks like some usage of nm and IDA on SpringBoardServices binary from simulator helped me on this.
Following code works on iOS 5.0.1 running on iPod Touch 4, iPhone 4 and iPad1 WiFi(all non-JB)
Of course you should never try to submit that to AppStore
- (NSArray*) getActiveApps
{
mach_port_t *p;
void *uikit = dlopen(UIKITPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(uikit, "SBSSpringBoardServerPort");
p = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(uikit);
void *sbserv = dlopen(SBSERVPATH, RTLD_LAZY);
NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) =
dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers");
//SBDisplayIdentifierForPID - protype assumed,verification of params done
void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) =
dlsym(sbserv, "SBDisplayIdentifierForPID");
//SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not)
void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) =
dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier");
//Get frontmost application
char frontmostAppS[256];
memset(frontmostAppS,sizeof(frontmostAppS),0);
SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS);
NSString * frontmostApp=[NSString stringWithFormat:#"%s",frontmostAppS];
//NSLog(#"Frontmost app is %#",frontmostApp);
//get list of running apps from SpringBoard
NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO);
//Really returns ACTIVE applications(from multitasking bar)
/* NSLog(#"Active applications:");
for(NSString *identifier in allApplications) {
// NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier);
NSLog(#"Active Application:%#",identifier);
}
*/
//get list of all apps from kernel
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
int ruid=process[i].kp_eproc.e_pcred.p_ruid;
int uid=process[i].kp_eproc.e_ucred.cr_uid;
//short int nice=process[i].kp_proc.p_nice;
//short int u_prio=process[i].kp_proc.p_usrpri;
short int prio=process[i].kp_proc.p_priority;
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
BOOL systemProcess=YES;
if (ruid==501)
systemProcess=NO;
char * appid[256];
memset(appid,sizeof(appid),0);
int intID,intID2;
intID=process[i].kp_proc.p_pid,appid;
SBDisplayIdentifierForPID(p,intID,appid);/
NSString * appId=[NSString stringWithFormat:#"%s",appid];
if (systemProcess==NO)
{
if ([appId isEqualToString:#""])
{
//final check.if no appid this is not springboard app
NSLog(#"(potentially system)Found process with PID:%# name %#,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio);
}
else
{
BOOL isFrontmost=NO;
if ([frontmostApp isEqualToString:appId])
{
isFrontmost=YES;
}
NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName",#"AppID",#"isFrontmost", nil]];
NSLog(#"PID:%#, name: %#, AppID:%#,isFrontmost:%d",processID,processName,appId,isFrontmost);
[array addObject:dict];
}
}
}
free(process);
return array;
}
}
}
dlclose(sbserv);
}
Of course 2nd loop is not strictly necessary but I needed non-localized names & PIDs too.
Great answer! But there is a small typo in your code, it should be:
First make sure that SBSERVPATH is defined and the correct header files are included:
#import <sys/sysctl.h>
#import <dlfcn.h>
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
Then first find the correct SB port:
mach_port_t *port;
void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(lib, "SBSSpringBoardServerPort");
port = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(lib);
And then find the active app:
mach_port_t * port = [self getSpringBoardPort];
// open springboard lib
void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
// retrieve function SBFrontmostApplicationDisplayIdentifier
void *(*SBFrontmostApplicationDisplayIdentifier)(mach_port_t *port, char *result) =
dlsym(lib, "SBFrontmostApplicationDisplayIdentifier");
// reserve memory for name
char appId[256];
memset(appId, 0, sizeof(appId));
// retrieve front app name
SBFrontmostApplicationDisplayIdentifier(port, appId);
// close dynlib
dlclose(lib);
This is what works for me on all IOS devices:
#define UIKITPATH "/System/Library/Framework/UIKit.framework/UIKit"
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
- (NSArray*) getActiveApps
{
mach_port_t *p;
void *uikit = dlopen(UIKITPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(uikit, "SBSSpringBoardServerPort");
p = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(uikit);
if(self.frameWorkPath == nil || self.frameWorkPath.length == 0)
{
self.frameWorkPath = #SBSERVPATH;
self.frameWorkPath = [self.frameWorkPath stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}
const char *cString = [self.frameWorkPath cStringUsingEncoding:NSUTF8StringEncoding];
//const char *bar = [self.frameWorkPath UTF8String];
void *sbserv = dlopen(cString, RTLD_LAZY);
NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) =
dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers");
//SBDisplayIdentifierForPID - protype assumed,verification of params done
void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) =
dlsym(sbserv, "SBDisplayIdentifierForPID");
//SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not)
void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) =
dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier");
//Get frontmost application
char frontmostAppS[512];
memset(frontmostAppS,sizeof(frontmostAppS),0);
SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS);
NSString * frontmostApp=[NSString stringWithFormat:#"%s",frontmostAppS];
if([self iOsMajorVersion] >= 7){
NSNumber *topmost = [NSNumber numberWithBool:YES];
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
NSMutableArray * splitted = [frontmostApp componentsSeparatedByString:#"."];
if(frontmostApp.length > 0 && splitted != nil && splitted.count > 1 && topmost.boolValue == YES){
NSString *appname = [splitted lastObject];
[dict setObject:[appname capitalizedString] forKey:#"ProcessName"];
[dict setObject:frontmostApp forKey:#"ProcessID"];
[dict setObject:frontmostApp forKey:#"AppID"];
[dict setObject:topmost forKey:#"isFrontmost"];
NSLog(#"Running TOPMOST App %#",dict);
return #[dict];
}
else{
return nil;
}
}
//NSLog(#"Frontmost app is %#",frontmostApp);
//get list of running apps from SpringBoard
NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO);
//Really returns ACTIVE applications(from multitasking bar)
NSLog(#"Active applications:");
for(NSString *identifier in allApplications) {
// NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier);
NSLog(#"Active Application:%#",identifier);
}
//get list of all apps from kernel
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
int ruid=process[i].kp_eproc.e_pcred.p_ruid;
int uid=process[i].kp_eproc.e_ucred.cr_uid;
//short int nice=process[i].kp_proc.p_nice;
//short int u_prio=process[i].kp_proc.p_usrpri;
short int prio=process[i].kp_proc.p_priority;
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
BOOL systemProcess=YES;
if (ruid==501){
systemProcess=NO;
}
char * appid[256];
memset(appid,sizeof(appid),0);
int intID,intID2;
intID=process[i].kp_proc.p_pid,appid;
SBDisplayIdentifierForPID(p,intID,appid);
NSString * appId=[NSString stringWithFormat:#"%s",appid];
if (systemProcess==NO)
{
if ([appId isEqualToString:#""])
{
//final check.if no appid this is not springboard app
//NSLog(#"(potentially system)Found process with PID:%# name %#,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio);
}
else
{
BOOL isFrontmost=NO;
if ([frontmostApp isEqualToString:appId])
{
isFrontmost=YES;
}
NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName",#"AppID",#"isFrontmost", nil]];
NSLog(#"PID:%#, name: %#, AppID:%#,isFrontmost:%d",processID,processName,appId,isFrontmost);
[array addObject:dict];
}
}
}
free(process);
return array;
}
}
}
dlclose(sbserv);
}

Resources