You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
5.2 KiB
169 lines
5.2 KiB
// 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 <Cocoa/Cocoa.h>
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include <IOKit/IOBSD.h>
|
|
#include <IOKit/IOKitLib.h>
|
|
#include <Carbon/Carbon.h>
|
|
|
|
#include <IOKit/kext/KextManager.h>
|
|
#include <IOKit/storage/IOBlockStorageDevice.h>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <Foundation/NSProcessInfo.h>
|
|
|
|
#include <mach/mach_init.h>
|
|
#include <mach/thread_act.h>
|
|
#include <mach/mach_port.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
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<System::DiskKind> 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
|