1 //===-- RNBServices.cpp -----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Created by Christopher Friesen on 3/21/08. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #import "RNBServices.h" 15 16 #import <CoreFoundation/CoreFoundation.h> 17 #import <unistd.h> 18 #import "DNBLog.h" 19 20 #if defined (__arm__) 21 #import <SpringBoardServices/SpringBoardServices.h> 22 #endif 23 24 int 25 ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable) 26 { 27 #if defined (__arm__) 28 int result = -1; 29 30 CFAllocatorRef alloc = kCFAllocatorDefault; 31 32 // Create a mutable array that we can populate. Specify zero so it can be of any size. 33 CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks)); 34 35 CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ()); 36 CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable)); 37 38 CFIndex count = ::CFArrayGetCount (sbsAppIDs.get()); 39 CFIndex i = 0; 40 for (i = 0; i < count; i++) 41 { 42 CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i); 43 44 // Create a new mutable dictionary for each application 45 CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 46 47 // Get the process id for the app (if there is one) 48 pid_t pid = INVALID_NUB_PROCESS; 49 if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &pid) == true) 50 { 51 CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid)); 52 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get()); 53 } 54 55 // Set the a boolean to indicate if this is the front most 56 if (sbsFrontAppID.get() && displayIdentifier && (::CFStringCompare (sbsFrontAppID.get(), displayIdentifier, 0) == kCFCompareEqualTo)) 57 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanTrue); 58 else 59 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse); 60 61 62 CFReleaser<CFStringRef> executablePath (::SBSCopyExecutablePathForDisplayIdentifier (displayIdentifier)); 63 if (executablePath.get() != NULL) 64 { 65 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, executablePath.get()); 66 } 67 68 CFReleaser<CFStringRef> iconImagePath (::SBSCopyIconImagePathForDisplayIdentifier (displayIdentifier)) ; 69 if (iconImagePath.get() != NULL) 70 { 71 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, iconImagePath.get()); 72 } 73 74 CFReleaser<CFStringRef> localizedDisplayName (::SBSCopyLocalizedApplicationNameForDisplayIdentifier (displayIdentifier)); 75 if (localizedDisplayName.get() != NULL) 76 { 77 ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, localizedDisplayName.get()); 78 } 79 80 // Append the application info to the plist array 81 ::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get()); 82 } 83 84 CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get())); 85 86 // write plist to service port 87 if (plistData.get() != NULL) 88 { 89 CFIndex size = ::CFDataGetLength (plistData.get()); 90 const UInt8 *bytes = ::CFDataGetBytePtr (plistData.get()); 91 if (bytes != NULL && size > 0) 92 { 93 plist.assign((char *)bytes, size); 94 return 0; // Success 95 } 96 else 97 { 98 DNBLogError("empty application property list."); 99 result = -2; 100 } 101 } 102 else 103 { 104 DNBLogError("serializing task list."); 105 result = -3; 106 } 107 108 return result; 109 #else 110 // TODO: list all current processes 111 DNBLogError("SBS doesn't support getting application list."); 112 return -1; 113 #endif 114 } 115 116 117 bool 118 IsSBProcess (nub_process_t pid) 119 { 120 #if defined (__arm__) 121 bool opt_runningApps = true; 122 bool opt_debuggable = false; 123 124 CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable)); 125 if (sbsAppIDs.get() != NULL) 126 { 127 CFIndex count = ::CFArrayGetCount (sbsAppIDs.get()); 128 CFIndex i = 0; 129 for (i = 0; i < count; i++) 130 { 131 CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i); 132 133 // Get the process id for the app (if there is one) 134 pid_t sbs_pid = INVALID_NUB_PROCESS; 135 if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &sbs_pid) == TRUE) 136 { 137 if (sbs_pid == pid) 138 return true; 139 } 140 } 141 } 142 #endif 143 return false; 144 } 145 146