View Javadoc
1   /**
2    * Oshi (https://github.com/dblock/oshi)
3    * 
4    * Copyright (c) 2010 - 2015 The Oshi Project Team
5    * 
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Eclipse Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/epl-v10.html
10   * 
11   * Contributors:
12   * dblock[at]dblock[dot]org
13   * alessandro[at]perucchi[dot]org
14   * widdis[at]gmail[dot]com
15   * https://github.com/dblock/oshi/graphs/contributors
16   */
17  package oshi.software.os.mac.local;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import oshi.hardware.PowerSource;
23  import oshi.software.os.mac.local.CoreFoundation.CFArrayRef;
24  import oshi.software.os.mac.local.CoreFoundation.CFDictionaryRef;
25  import oshi.software.os.mac.local.CoreFoundation.CFTypeRef;
26  
27  import com.sun.jna.Memory;
28  import com.sun.jna.Pointer;
29  import com.sun.jna.ptr.IntByReference;
30  
31  /**
32   * A Power Source
33   * 
34   * @author widdis[at]gmail[dot]com
35   */
36  public class MacPowerSource implements PowerSource {
37  
38  	private String name;
39  
40  	private double remainingCapacity;
41  
42  	private double timeRemaining;
43  
44  	public MacPowerSource(String name, double remainingCapacity,
45  			double timeRemaining) {
46  		this.name = name;
47  		this.remainingCapacity = remainingCapacity;
48  		this.timeRemaining = timeRemaining;
49  	}
50  
51  	@Override
52  	public String getName() {
53  		return this.name;
54  	}
55  
56  	@Override
57  	public double getRemainingCapacity() {
58  		return this.remainingCapacity;
59  	}
60  
61  	@Override
62  	public double getTimeRemaining() {
63  		return this.timeRemaining;
64  	}
65  
66  	/**
67  	 * Battery Information
68  	 */
69  	public static PowerSource[] getPowerSources() {
70  		// Get the blob containing current power source state
71  		CFTypeRef powerSourcesInfo = IOKit.INSTANCE.IOPSCopyPowerSourcesInfo();
72  		CFArrayRef powerSourcesList = IOKit.INSTANCE
73  				.IOPSCopyPowerSourcesList(powerSourcesInfo);
74  		int powerSourcesCount = CoreFoundation.INSTANCE
75  				.CFArrayGetCount(powerSourcesList);
76  
77  		// Get time remaining
78  		// -1 = unknown, -2 = unlimited
79  		double timeRemaining = IOKit.INSTANCE.IOPSGetTimeRemainingEstimate();
80  
81  		// For each power source, output various info
82  		List<MacPowerSource> psList = new ArrayList<>(
83  				powerSourcesCount);
84  		for (int ps = 0; ps < powerSourcesCount; ps++) {
85  			// Get the dictionary for that Power Source
86  			CFTypeRef powerSource = CoreFoundation.INSTANCE
87  					.CFArrayGetValueAtIndex(powerSourcesList, ps);
88  			CFDictionaryRef dictionary = IOKit.INSTANCE
89  					.IOPSGetPowerSourceDescription(powerSourcesInfo,
90  							powerSource);
91  
92  			// Get values from dictionary (See IOPSKeys.h)
93  			// Skip if not present
94  			boolean isPresent = false;
95  			Pointer isPresentRef = CoreFoundation.INSTANCE
96  					.CFDictionaryGetValue(dictionary, IOKit.IOPS_IS_PRESENT_KEY);
97  			if (isPresentRef != null)
98  				isPresent = CoreFoundation.INSTANCE
99  						.CFBooleanGetValue(isPresentRef);
100 			if (!isPresent)
101 				continue;
102 
103 			// Name
104 			Pointer name = CoreFoundation.INSTANCE.CFDictionaryGetValue(
105 					dictionary, IOKit.IOPS_NAME_KEY);
106 			long length = CoreFoundation.INSTANCE.CFStringGetLength(name);
107 			long maxSize = CoreFoundation.INSTANCE
108 					.CFStringGetMaximumSizeForEncoding(length,
109 							CoreFoundation.UTF_8);
110 			Pointer nameBuf = new Memory(maxSize);
111 			CoreFoundation.INSTANCE.CFStringGetCString(name, nameBuf, maxSize,
112 					CoreFoundation.UTF_8);
113 
114 			// Remaining Capacity = current / max
115 			IntByReference currentCapacity = new IntByReference();
116 			if (!CoreFoundation.INSTANCE.CFDictionaryGetValueIfPresent(
117 					dictionary, IOKit.IOPS_CURRENT_CAPACITY_KEY,
118 					currentCapacity))
119 				currentCapacity = new IntByReference(0);
120 			IntByReference maxCapacity = new IntByReference();
121 			if (!CoreFoundation.INSTANCE.CFDictionaryGetValueIfPresent(
122 					dictionary, IOKit.IOPS_MAX_CAPACITY_KEY, maxCapacity))
123 				maxCapacity = new IntByReference(1);
124 
125 			// Add to list
126 			psList.add(new MacPowerSource(nameBuf != null ? nameBuf
127 					.getString(0) : "Unknown", (double) currentCapacity
128 					.getValue() / maxCapacity.getValue(), timeRemaining));
129 		}
130 		// Release the blob
131 		CoreFoundation.INSTANCE.CFRelease(powerSourcesInfo);
132 
133 		return psList.toArray(new MacPowerSource[psList.size()]);
134 	}
135 }