// Copyright 2020 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "android/base/Optional.h" #include "android/base/system/System.h" #include #include #include #include #include #include #include #import #import #include #include #include #include #include namespace android { namespace base { // From: // https://stackoverflow.com/questions/49677034/thread-sleeps-too-long-on-os-x-when-in-background void disableAppNap_macImpl(void) { if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions:reason:)]) { [[NSProcessInfo processInfo] beginActivityWithOptions:0x00FFFFFF reason:@"Not sleepy and don't want to nap"]; } } // based on https://stackoverflow.com/questions/13893134/get-current-pthread-cpu-usage-mac-os-x void cpuUsageCurrentThread_macImpl( uint64_t* user, uint64_t* sys) { kern_return_t kr; mach_msg_type_number_t count; mach_port_t thread; thread_basic_info_data_t info; thread = mach_thread_self(); count = THREAD_BASIC_INFO_COUNT; kr = thread_info( thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count); if (kr == KERN_SUCCESS) { *user = info.user_time.seconds * 1000000ULL + info.user_time.microseconds; *sys = info.system_time.seconds * 1000000ULL + info.system_time.microseconds; } else { fprintf(stderr, "%s: WARNING: could not get thread info for CPU usage\n", __func__); } mach_port_deallocate(mach_task_self(), thread); } Optional nativeDiskKind(int st_dev) { const char* devName = devname(st_dev, S_IFBLK); if (!devName) { return {}; } CFMutableDictionaryRef classesToMatch = IOBSDNameMatching(kIOMasterPortDefault, 0, devName); if (!classesToMatch) { NSLog(@"Could not find io classes of disk"); return {}; } // get iterator of matching services io_iterator_t entryIterator; if (KERN_SUCCESS != IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &entryIterator)) { NSLog(@"Can't iterate services"); return {}; } // iterate over all found medias io_object_t serviceEntry, parentMedia; while ((serviceEntry = IOIteratorNext(entryIterator)) != 0) { // We assume there won't be more levels of nesting here. The limit is // arbitrary and can be increased if we hit it. int maxlevels = 8; do { kern_return_t kernResult = IORegistryEntryGetParentEntry( serviceEntry, kIOServicePlane, &parentMedia); IOObjectRelease(serviceEntry); if (KERN_SUCCESS != kernResult) { serviceEntry = 0; NSLog(@"Error while getting parent service entry"); break; } serviceEntry = parentMedia; if (!parentMedia) { break; // finished iterator } CFTypeRef res = IORegistryEntryCreateCFProperty( serviceEntry, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, 0); if (res) { NSString* type = [(NSDictionary*)res objectForKey:(id)CFSTR(kIOPropertyMediumTypeKey)]; if ([@kIOPropertyMediumTypeSolidStateKey isEqualToString:type]) { CFRelease(res); return System::DiskKind::Ssd; } else if ([@kIOPropertyMediumTypeRotationalKey isEqualToString:type]) { CFRelease(res); return System::DiskKind::Hdd; } CFRelease(res); } } while (maxlevels--); if (serviceEntry) { IOObjectRelease(serviceEntry); } } IOObjectRelease(entryIterator); return {}; } // From: // https://stackoverflow.com/questions/6796028/start-a-gui-process-in-mac-os-x-without-dock-icon void hideDockIcon_macImpl(void) { if (NSApp == nil) { // Initialize the global variable "NSApp" [NSApplication sharedApplication]; } [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; } } // namespace base } // namespace android