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