└── applications └── Gauge ├── .DS_Store ├── .gitignore ├── README.md ├── WhatsThis.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── .DS_Store │ ├── androidTest │ └── java │ │ └── com │ │ └── happen │ │ └── it │ │ └── make │ │ └── whatisit │ │ └── ApplicationTest.java │ └── main │ ├── .DS_Store │ ├── AndroidManifest.xml │ ├── aidl │ └── edu │ │ └── umich │ │ └── PowerTutor │ │ ├── PowerNotifications.aidl │ │ └── service │ │ └── ICounterService.aidl │ ├── assets │ ├── cat.jpg │ ├── keyboard.jpg │ ├── night.jpg │ ├── red-car.jpg │ ├── sea.jpg │ └── sky.jpg │ ├── java │ ├── com │ │ └── happen │ │ │ └── it │ │ │ └── make │ │ │ └── whatisit │ │ │ ├── Constants.java │ │ │ ├── MxNetGauge.java │ │ │ ├── MxNetUtils.java │ │ │ ├── WhatsActivity.java │ │ │ └── WhatsApplication.java │ ├── edu │ │ └── umich │ │ │ └── PowerTutor │ │ │ ├── .DS_Store │ │ │ ├── components │ │ │ ├── Audio.java │ │ │ ├── CPU.java │ │ │ ├── GPS.java │ │ │ ├── LCD.java │ │ │ ├── OLED.java │ │ │ ├── PowerComponent.java │ │ │ ├── Sensors.java │ │ │ ├── Threeg.java │ │ │ └── Wifi.java │ │ │ ├── phone │ │ │ ├── DreamConstants.java │ │ │ ├── DreamPowerCalculator.java │ │ │ ├── PassionConstants.java │ │ │ ├── PassionPowerCalculator.java │ │ │ ├── PhoneConstants.java │ │ │ ├── PhonePowerCalculator.java │ │ │ ├── PhoneSelector.java │ │ │ ├── PowerFunction.java │ │ │ ├── SapphireConstants.java │ │ │ └── SapphirePowerCalculator.java │ │ │ ├── service │ │ │ ├── IterationData.java │ │ │ ├── LogUploader.java │ │ │ ├── PowerData.java │ │ │ ├── PowerEstimator.java │ │ │ ├── UMLoggerService.java │ │ │ └── UidInfo.java │ │ │ └── util │ │ │ ├── BatteryStats.java │ │ │ ├── Counter.java │ │ │ ├── ForegroundDetector.java │ │ │ ├── HexEncode.java │ │ │ ├── HistoryBuffer.java │ │ │ ├── NativeLoader.java │ │ │ ├── NotificationService.java │ │ │ ├── Recycler.java │ │ │ └── SystemInfo.java │ ├── monet │ │ └── experiment │ │ │ ├── DatasetSize.java │ │ │ ├── Experiment.java │ │ │ └── ProcessLevel.java │ └── org │ │ └── dmlc │ │ └── mxnet │ │ ├── ModelLoader.java │ │ ├── MxnetException.java │ │ └── Predictor.java │ ├── jniLibs │ └── armeabi │ │ └── libmxnet_predict.so │ ├── libs │ └── achartengine-1.0.0.jar │ └── res │ ├── .DS_Store │ ├── drawable │ ├── .DS_Store │ ├── cat.jpg │ ├── round_add.png │ └── text_border.xml │ ├── layout │ └── activity_whats.xml │ ├── menu │ └── menu_whats.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── raw │ ├── inception_bn_mean │ ├── inception_bn_params │ ├── inception_bn_symbol.json │ ├── inception_bn_synset.txt │ ├── mean.json │ ├── params │ ├── symbol.json │ └── synset.txt │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── data ├── cat.jpg ├── keyboard.jpg ├── night.jpg ├── red-car.jpg ├── sea.jpg └── sky.jpg ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── notebook ├── plots.ipynb └── utils.py └── settings.gradle /applications/Gauge/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/.DS_Store -------------------------------------------------------------------------------- /applications/Gauge/.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | 28 | # Android Studio Navigation editor temp files 29 | .navigation/ 30 | 31 | # Android Studio captures folder 32 | captures/ 33 | 34 | .idea/ 35 | -------------------------------------------------------------------------------- /applications/Gauge/README.md: -------------------------------------------------------------------------------- 1 | # WhatsThis 2 | 3 | "What is it?" -- asked Disco the talking budgie. 4 | 5 | This is an android example of using mxnet to classify pictures. 6 | ``` 7 | -main 8 | | 9 | ----java 10 | | | 11 | | ----com.happen.it.make.whatisit -- the UI module 12 | | | 13 | | ----org.dmlc.mxnet -- the java interface 14 | | 15 | ----jniLibs 16 | | | 17 | | -----armeabi -- the directory containing dynamic link lib for android 18 | | | 19 | | -------------- libmxnet_predict.so --- the prediction lib 20 | | 21 | ----res 22 | | 23 | -----raw 24 | | 25 | ------params 26 | | 27 | ------symbol.json 28 | | 29 | ------synset.txt 30 | | 31 | ------mean.json 32 | 33 | ``` 34 | 35 | The example in mxnet doesn't include the model and pre-compiled native library for repo-size consideration. 36 | 37 | To compile the android lib by yourself, have a look at mxnet/amalgamation. 38 | 39 | To download a complete example with precompiled lib and a simple model, clone https://github.com/Leliana/WhatsThis.git . 40 | 41 | NOTE: This example doesn't run with emulator unless you build a native lib for android emulator. 42 | -------------------------------------------------------------------------------- /applications/Gauge/WhatsThis.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /applications/Gauge/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /applications/Gauge/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /applications/Gauge/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.happen.it.make.whatsthis" 9 | minSdkVersion 21 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar', '*.so']) 24 | compile 'com.android.support:appcompat-v7:22.2.1' 25 | compile files('src/main/libs/achartengine-1.0.0.jar') 26 | } 27 | -------------------------------------------------------------------------------- /applications/Gauge/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/leliana/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/.DS_Store -------------------------------------------------------------------------------- /applications/Gauge/app/src/androidTest/java/com/happen/it/make/whatisit/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.happen.it.make.whatisit; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.test.AndroidTestCase; 6 | import android.test.ApplicationTestCase; 7 | import android.test.InstrumentationTestCase; 8 | import android.test.mock.MockContext; 9 | 10 | /** 11 | * Testing Fundamentals 12 | */ 13 | public class ApplicationTest extends InstrumentationTestCase { 14 | public Context context; 15 | 16 | public void setUp() throws Exception { 17 | super.setUp(); 18 | // 19 | context = getInstrumentation().getContext(); 20 | // 21 | // assertNotNull(context); 22 | } 23 | 24 | public void testMxNetForwardPass() { 25 | MxNetGauge mxNetGauge = new MxNetGauge(context, 10); 26 | mxNetGauge.runTest(); 27 | System.out.println(mxNetGauge.toString()); 28 | } 29 | } -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/.DS_Store -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/aidl/edu/umich/PowerTutor/PowerNotifications.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor; 21 | 22 | interface PowerNotifications { 23 | // These are the notifications that are actually supported. The rest have 24 | // potential to be supported but aren't needed at the moment so aren't 25 | // actually hooked. 26 | void noteStartWakelock(int uid, String name, int type); 27 | void noteStopWakelock(int uid, String name, int type); 28 | void noteStartSensor(int uid, int sensor); 29 | void noteStopSensor(int uid, int sensor); 30 | void noteStartGps(int uid); 31 | void noteStopGps(int uid); 32 | void noteScreenBrightness(int brightness); 33 | void noteStartMedia(int uid, int id); 34 | void noteStopMedia(int uid, int id); 35 | void noteVideoSize(int uid, int id, int width, int height); 36 | void noteSystemMediaCall(int uid); 37 | 38 | void noteScreenOn(); 39 | void noteScreenOff(); 40 | void noteInputEvent(); 41 | void noteUserActivity(int uid, int event); 42 | void notePhoneOn(); 43 | void notePhoneOff(); 44 | void notePhoneDataConnectionState(int dataType, boolean hasData); 45 | void noteWifiOn(int uid); 46 | void noteWifiOff(int uid); 47 | void noteWifiRunning(); 48 | void noteWifiStopped(); 49 | void noteBluetoothOn(); 50 | void noteBluetoothOff(); 51 | void noteFullWifiLockAcquired(int uid); 52 | void noteFullWifiLockReleased(int uid); 53 | void noteScanWifiLockAcquired(int uid); 54 | void noteScanWifiLockReleased(int uid); 55 | void noteWifiMulticastEnabled(int uid); 56 | void noteWifiMulticastDisabled(int uid); 57 | void setOnBattery(boolean onBattery, int level); 58 | void recordCurrentLevel(int level); 59 | /* Also got rid of the non-notification calls. 60 | * byte[] getStatistics(); 61 | * long getAwakeTimeBattery(); 62 | * long getAwakeTimePlugged(); 63 | */ 64 | 65 | /* Added functions to the normal IBatteryStats interface. */ 66 | void noteVideoOn(int uid); 67 | void noteVideoOff(int uid); 68 | void noteAudioOn(int uid); 69 | void noteAudioOff(int uid); 70 | } 71 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/aidl/edu/umich/PowerTutor/service/ICounterService.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | interface ICounterService { 23 | // Returns the name of the components that are being logged. 24 | String[] getComponents(); 25 | 26 | // Returns the maximum power usage for each of the components being logged. 27 | int[] getComponentsMaxPower(); 28 | 29 | // Returns a bit mask with a 1 in the ith bit if component i doesn't have 30 | // uid specific information. 31 | int getNoUidMask(); 32 | 33 | // Returns the power consumption in mW for component componentId for the last 34 | // count iterations. uid can be specified to make this data only include a 35 | // specific user id or you can provide SystemInfo.AID_ALL to request 36 | // global power state information. 37 | int[] getComponentHistory(int count, int componentId, int uid); 38 | 39 | // Returns the total energy consumption for each component in the same order 40 | // that the components were returned in getComponents() and in the same order 41 | // that the components are populated by PhoneSelector.generateComponents(). 42 | // 43 | // uid can be specified to make the information specific to a single user 44 | // id or SystemInfo.AID_ALL can be specified to request global information. 45 | // 46 | // windowType should be one of Counter.WINDOW_MINUTE, Counter.WINDOW_HOUR, 47 | // Counter.WINDOW_DAY, Counter.WINDOW_TOTAL to request the window that the 48 | // energy usage will be calculated over. 49 | // 50 | // The returned result is given in mJ. 51 | long[] getTotals(int uid, int windowType); 52 | 53 | // Like getTotals() except that each entry is divided by how long the given 54 | // uid was running. If SystemInfo.AID_ALL is provided this is effectively 55 | // like dividing each entry by the window size. (unless PowerTutor hasn't 56 | // been running that long). 57 | long[] getMeans(int uid, int windowType); 58 | 59 | // Gets the total time that this uid has been running in seconds. 60 | long getRuntime(int uid, int windowType); 61 | 62 | // Returns a byte array representing a serialized array of UidInfo structures. 63 | // See UidInfo.java for what information is given. Note that members marked 64 | // as transient are not filled in. 65 | // Power contributions from component i will be dropped if the ith bit is set 66 | // in ignoreMask. Providing 0 for ignoreMask will give results for all 67 | // components. 68 | // 69 | // Example Usage: 70 | // byte[] rawUidInfo = counterService.getUidInfo(windowType); 71 | // UidInfo[] uidInfos = (UidInfo[])new ObjectInputStream( 72 | // new ByteArrayInputStream(rawUidInfo)).readObject(); 73 | byte[] getUidInfo(int windowType, int ignoreMask); 74 | 75 | // Return miscellaneous data point for the passed uid. 76 | // Current extras included: 77 | // OLEDSCORE 78 | long getUidExtra(String name, int uid); 79 | } 80 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/cat.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/keyboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/keyboard.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/night.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/night.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/red-car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/red-car.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/sea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/sea.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/assets/sky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/assets/sky.jpg -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/com/happen/it/make/whatisit/Constants.java: -------------------------------------------------------------------------------- 1 | package com.happen.it.make.whatisit; 2 | 3 | /** 4 | * Created by leliana on 8/5/15. 5 | */ 6 | public class Constants { 7 | public static final int SELECT_PHOTO_CODE = 1; 8 | public static final int CAPTURE_PHOTO_CODE = 2; 9 | } 10 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/com/happen/it/make/whatisit/MxNetUtils.java: -------------------------------------------------------------------------------- 1 | package com.happen.it.make.whatisit; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | 6 | import org.dmlc.mxnet.Predictor; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.nio.ByteBuffer; 12 | 13 | /** 14 | * Created by leliana on 11/6/15. 15 | */ 16 | public class MxNetUtils { 17 | private static boolean libLoaded = false; 18 | private MxNetUtils() {} 19 | 20 | public static String identifyImage(MxNetGauge gauge, final Bitmap bitmap) { 21 | float[] colors = gauge.loader.toColor(gauge.loader.preprocess(bitmap)); 22 | 23 | Predictor predictor = gauge.getPredictor(); 24 | predictor.forward("data", colors); 25 | 26 | final float[] result = predictor.getOutput(0); 27 | int index = 0; 28 | for (int i = 0; i < result.length; ++i) { 29 | if (result[index] < result[i]) index = i; 30 | } 31 | 32 | String tag = gauge.getName(index); 33 | return tag; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/com/happen/it/make/whatisit/WhatsApplication.java: -------------------------------------------------------------------------------- 1 | package com.happen.it.make.whatisit; 2 | 3 | import android.app.Application; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.os.BatteryManager; 9 | 10 | import org.dmlc.mxnet.Predictor; 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | 14 | import java.io.BufferedReader; 15 | import java.io.ByteArrayOutputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.io.InputStreamReader; 19 | import java.text.DecimalFormat; 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | /** 26 | * Created by leliana on 8/5/15. 27 | */ 28 | public class WhatsApplication extends Application{ 29 | @Override 30 | public void onCreate() { 31 | super.onCreate(); 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/java/edu/umich/PowerTutor/.DS_Store -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/Audio.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.PowerNotifications; 23 | import edu.umich.PowerTutor.service.IterationData; 24 | import edu.umich.PowerTutor.service.PowerData; 25 | import edu.umich.PowerTutor.util.NotificationService; 26 | import edu.umich.PowerTutor.util.Recycler; 27 | 28 | import android.content.Context; 29 | import android.media.AudioManager; 30 | 31 | import java.io.IOException; 32 | import java.io.OutputStreamWriter; 33 | import java.util.TreeSet; 34 | 35 | /**This class aims to log the audio device status once per log interval*/ 36 | public class Audio extends PowerComponent { 37 | /**This class is the logger data file corresponding to Audio*/ 38 | public static class AudioData extends PowerData { 39 | private static Recycler recycler = new Recycler(); 40 | 41 | public static AudioData obtain() { 42 | AudioData result = recycler.obtain(); 43 | if(result != null) return result; 44 | return new AudioData(); 45 | } 46 | 47 | @Override 48 | public void recycle() { 49 | recycler.recycle(this); 50 | } 51 | 52 | public boolean musicOn; 53 | 54 | private AudioData() { 55 | } 56 | 57 | public void init(boolean musicOn) { 58 | this.musicOn = musicOn; 59 | } 60 | 61 | public void writeLogDataInfo(OutputStreamWriter out) throws IOException { 62 | out.write("Audio-on " + musicOn + "\n"); 63 | } 64 | } 65 | 66 | private static class MediaData implements Comparable { 67 | private static Recycler recycler = new Recycler(); 68 | 69 | public static MediaData obtain() { 70 | MediaData result = recycler.obtain(); 71 | if(result != null) return result; 72 | return new MediaData(); 73 | } 74 | 75 | public void recycle() { 76 | recycler.recycle(this); 77 | } 78 | 79 | public int uid; 80 | public int id; 81 | public int assignUid; 82 | 83 | public int compareTo(Object obj) { 84 | MediaData x = (MediaData)obj; 85 | if(uid < x.uid) return -1; 86 | if(uid > x.uid) return 1; 87 | if(id < x.id) return -1; 88 | if(id > x.id) return 1; 89 | return 0; 90 | } 91 | 92 | public boolean equals(Object obj) { 93 | MediaData x = (MediaData)obj; 94 | return uid == x.uid && id == x.id; 95 | } 96 | } 97 | 98 | private AudioManager audioManager; 99 | private PowerNotifications audioNotif; 100 | private TreeSet uidData; 101 | 102 | public Audio(Context context) { 103 | if(NotificationService.available()) { 104 | uidData = new TreeSet(); 105 | audioNotif = new NotificationService.DefaultReceiver() { 106 | private int sysUid = -1; 107 | 108 | @Override 109 | public void noteSystemMediaCall(int uid) { 110 | sysUid = uid; 111 | } 112 | 113 | @Override 114 | public void noteStartMedia(int uid, int id) { 115 | MediaData data = MediaData.obtain(); 116 | data.uid = uid; 117 | data.id = id; 118 | if(uid == 1000 && sysUid != -1) { 119 | data.assignUid = sysUid; 120 | sysUid = -1; 121 | } else { 122 | data.assignUid = uid; 123 | } 124 | synchronized(uidData) { 125 | if(!uidData.add(data)) { 126 | data.recycle(); 127 | } 128 | } 129 | } 130 | 131 | @Override 132 | public void noteStopMedia(int uid, int id) { 133 | MediaData data = MediaData.obtain(); 134 | data.uid = uid; 135 | data.id = id; 136 | synchronized(uidData) { 137 | uidData.remove(data); 138 | } 139 | data.recycle(); 140 | } 141 | }; 142 | NotificationService.addHook(audioNotif); 143 | } 144 | 145 | audioManager = (AudioManager)context.getSystemService( 146 | Context.AUDIO_SERVICE); 147 | } 148 | 149 | @Override 150 | protected void onExit() { 151 | if(audioNotif != null) { 152 | NotificationService.removeHook(audioNotif); 153 | } 154 | } 155 | 156 | @Override 157 | public IterationData calculateIteration(long iteration) { 158 | IterationData result = IterationData.obtain(); 159 | AudioData data = AudioData.obtain(); 160 | data.init(uidData != null && !uidData.isEmpty() || 161 | audioManager.isMusicActive()); 162 | result.setPowerData(data); 163 | 164 | if(uidData != null) synchronized(uidData) { 165 | int last_uid = -1; 166 | for(MediaData dat : uidData) { 167 | if(dat.uid != last_uid) { 168 | AudioData audioPower = AudioData.obtain(); 169 | audioPower.init(true); 170 | result.addUidPowerData(dat.assignUid, audioPower); 171 | } 172 | last_uid = dat.uid; 173 | } 174 | } 175 | 176 | return result; 177 | } 178 | 179 | @Override 180 | public boolean hasUidInformation() { 181 | return audioNotif != null; 182 | } 183 | 184 | @Override 185 | public String getComponentName() { 186 | return "Audio"; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/CPU.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.phone.PhoneConstants; 23 | import edu.umich.PowerTutor.service.IterationData; 24 | import edu.umich.PowerTutor.service.PowerData; 25 | import edu.umich.PowerTutor.util.Recycler; 26 | import edu.umich.PowerTutor.util.SystemInfo; 27 | 28 | import android.util.Log; 29 | import android.os.Process; 30 | import android.os.SystemClock; 31 | import android.util.SparseArray; 32 | 33 | import java.io.BufferedReader; 34 | import java.io.FileNotFoundException; 35 | import java.io.FileReader; 36 | import java.io.IOException; 37 | import java.io.OutputStreamWriter; 38 | import java.lang.reflect.Method; 39 | import java.lang.reflect.InvocationTargetException; 40 | 41 | public class CPU extends PowerComponent { 42 | public static class CpuData extends PowerData { 43 | private static Recycler recycler = new Recycler(); 44 | 45 | public static CpuData obtain() { 46 | CpuData result = recycler.obtain(); 47 | if(result != null) return result; 48 | return new CpuData(); 49 | } 50 | 51 | @Override 52 | public void recycle() { 53 | recycler.recycle(this); 54 | } 55 | 56 | public double sysPerc; 57 | public double usrPerc; 58 | public double freq; 59 | 60 | private CpuData() { 61 | } 62 | 63 | public void init(double sysPerc, double usrPerc, double freq) { 64 | this.sysPerc = sysPerc; 65 | this.usrPerc = usrPerc; 66 | this.freq = freq; 67 | } 68 | 69 | public void writeLogDataInfo(OutputStreamWriter out) throws IOException { 70 | StringBuilder res = new StringBuilder(); 71 | res.append("CPU-sys ").append((long)Math.round(sysPerc)) 72 | .append("\nCPU-usr ").append((long)Math.round(usrPerc)) 73 | .append("\nCPU-freq ").append(freq) 74 | .append("\n"); 75 | out.write(res.toString()); 76 | } 77 | } 78 | 79 | private static final String TAG = "CPU"; 80 | private static final String CPU_FREQ_FILE = "/proc/cpuinfo"; 81 | private static final String STAT_FILE = "/proc/stat"; 82 | 83 | private CpuStateKeeper cpuState; 84 | private SparseArray pidStates; 85 | private SparseArray uidLinks; 86 | 87 | private int[] pids; 88 | private long[] statsBuf; 89 | 90 | private PhoneConstants constants; 91 | 92 | public CPU(PhoneConstants constants) { 93 | this.constants = constants; 94 | cpuState = new CpuStateKeeper(SystemInfo.AID_ALL); 95 | pidStates = new SparseArray(); 96 | uidLinks = new SparseArray(); 97 | statsBuf = new long[7]; 98 | } 99 | 100 | @Override 101 | public IterationData calculateIteration(long iteration) { 102 | IterationData result = IterationData.obtain(); 103 | 104 | SystemInfo sysInfo = SystemInfo.getInstance(); 105 | double freq = readCpuFreq(sysInfo); 106 | if(freq < 0) { 107 | Log.w(TAG, "Failed to read cpu frequency"); 108 | return result; 109 | } 110 | 111 | if(!sysInfo.getUsrSysTotalTime(statsBuf)) { 112 | Log.w(TAG, "Failed to read cpu times"); 113 | return result; 114 | } 115 | 116 | long usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; 117 | long sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; 118 | long totalTime = statsBuf[SystemInfo.INDEX_TOTAL_TIME]; 119 | 120 | boolean init = cpuState.isInitialized(); 121 | cpuState.updateState(usrTime, sysTime, totalTime, iteration); 122 | 123 | if(init) { 124 | CpuData data = CpuData.obtain(); 125 | data.init(cpuState.getUsrPerc(), cpuState.getSysPerc(), freq); 126 | result.setPowerData(data); 127 | } 128 | 129 | uidLinks.clear(); 130 | pids = sysInfo.getPids(pids); 131 | int pidInd = 0; 132 | if(pids != null) for(int pid : pids) { 133 | if(pid < 0) { 134 | break; 135 | } 136 | 137 | CpuStateKeeper pidState; 138 | if(pidInd < pidStates.size() && pidStates.keyAt(pidInd) == pid) { 139 | pidState = pidStates.valueAt(pidInd); 140 | } else { 141 | int uid = sysInfo.getUidForPid(pid); 142 | if(uid >= 0) { 143 | pidState = new CpuStateKeeper(uid); 144 | pidStates.put(pid, pidState); 145 | } else { 146 | /* Assume that this process no longer exists. */ 147 | continue; 148 | } 149 | } 150 | pidInd++; 151 | 152 | if(!pidState.isStale(iteration)) { 153 | /* Nothing much is going on with this pid recently. We'll just 154 | * assume that it's not using any of the cpu for this iteration. 155 | */ 156 | pidState.updateIteration(iteration, totalTime); 157 | } else if(sysInfo.getPidUsrSysTime(pid, statsBuf)) { 158 | usrTime = statsBuf[SystemInfo.INDEX_USER_TIME]; 159 | sysTime = statsBuf[SystemInfo.INDEX_SYS_TIME]; 160 | 161 | init = pidState.isInitialized(); 162 | pidState.updateState(usrTime, sysTime, totalTime, iteration); 163 | 164 | if(!init) { 165 | continue; 166 | } 167 | } 168 | 169 | CpuStateKeeper linkState = uidLinks.get(pidState.getUid()); 170 | if(linkState == null) { 171 | uidLinks.put(pidState.getUid(), pidState); 172 | } else { 173 | linkState.absorb(pidState); 174 | } 175 | } 176 | 177 | /* Remove processes that are no longer active. */ 178 | for(int i = 0; i < pidStates.size(); i++) { 179 | if(!pidStates.valueAt(i).isAlive(iteration)) { 180 | pidStates.remove(pidStates.keyAt(i--)); 181 | } 182 | } 183 | 184 | /* Collect the summed uid information. */ 185 | for(int i = 0; i < uidLinks.size(); i++) { 186 | int uid = uidLinks.keyAt(i); 187 | CpuStateKeeper linkState = uidLinks.valueAt(i); 188 | 189 | CpuData uidData = CpuData.obtain(); 190 | predictAppUidState(uidData, linkState.getUsrPerc(), 191 | linkState.getSysPerc(), freq); 192 | result.addUidPowerData(uid, uidData); 193 | } 194 | 195 | return result; 196 | } 197 | 198 | /* This is the function that is responsible for predicting the cpu frequency 199 | * state of the individual uid as though it were the only thing running. It 200 | * simply is finding the lowest frequency that keeps the cpu usage under 201 | * 70% assuming there is a linear relationship to the cpu utilization at 202 | * different frequencies. 203 | */ 204 | private void predictAppUidState(CpuData uidData, double usrPerc, 205 | double sysPerc, double freq) { 206 | double[] freqs = constants.cpuFreqs(); 207 | if(usrPerc + sysPerc < 1e-6) { 208 | /* Don't waste time with the binary search if there is no utilization 209 | * which will be the case a lot. 210 | */ 211 | uidData.init(sysPerc, usrPerc, freqs[0]); 212 | return; 213 | } 214 | int lo = 0; 215 | int hi = freqs.length - 1; 216 | double perc = sysPerc + usrPerc; 217 | while(lo < hi) { 218 | int mid = (lo + hi) / 2; 219 | double nperc = perc * freq / freqs[mid]; 220 | if(nperc < 70) { 221 | hi = mid; 222 | } else { 223 | lo = mid + 1; 224 | } 225 | } 226 | uidData.init(sysPerc * freq / freqs[lo], usrPerc * freq / freqs[lo], 227 | freqs[lo]); 228 | } 229 | 230 | private static class CpuStateKeeper { 231 | private int uid; 232 | private long iteration; 233 | private long lastUpdateIteration; 234 | private long inactiveIterations; 235 | 236 | private long lastUsr; 237 | private long lastSys; 238 | private long lastTotal; 239 | 240 | private long sumUsr; 241 | private long sumSys; 242 | private long deltaTotal; 243 | 244 | private CpuStateKeeper(int uid) { 245 | this.uid = uid; 246 | lastUsr = lastSys = -1; 247 | lastUpdateIteration = iteration = -1; 248 | inactiveIterations = 0; 249 | } 250 | 251 | public boolean isInitialized() { 252 | return lastUsr != -1; 253 | } 254 | 255 | public void updateIteration(long iteration, long totalTime) { 256 | /* Process is still running but actually reading the cpu utilization has 257 | * been skipped this iteration to avoid wasting cpu cycles as this process 258 | * has not been very active recently. */ 259 | sumUsr = 0; 260 | sumSys = 0; 261 | deltaTotal = totalTime - lastTotal; 262 | if(deltaTotal < 1) deltaTotal = 1; 263 | lastTotal = totalTime; 264 | this.iteration = iteration; 265 | } 266 | 267 | public void updateState(long usrTime, long sysTime, long totalTime, 268 | long iteration) { 269 | sumUsr = usrTime - lastUsr; 270 | sumSys = sysTime - lastSys; 271 | deltaTotal = totalTime - lastTotal; 272 | if(deltaTotal < 1) deltaTotal = 1; 273 | lastUsr = usrTime; 274 | lastSys = sysTime; 275 | lastTotal = totalTime; 276 | lastUpdateIteration = this.iteration = iteration; 277 | 278 | if(getUsrPerc() + getSysPerc() < 0.1) { 279 | inactiveIterations++; 280 | } else { 281 | inactiveIterations = 0; 282 | } 283 | } 284 | 285 | public int getUid() { 286 | return uid; 287 | } 288 | 289 | public void absorb(CpuStateKeeper s) { 290 | sumUsr += s.sumUsr; 291 | sumSys += s.sumSys; 292 | } 293 | 294 | public double getUsrPerc() { 295 | return 100.0 * sumUsr / Math.max(sumUsr + sumSys, deltaTotal); 296 | } 297 | 298 | public double getSysPerc() { 299 | return 100.0 * sumSys / Math.max(sumUsr + sumSys, deltaTotal); 300 | } 301 | 302 | public boolean isAlive(long iteration) { 303 | return this.iteration == iteration; 304 | } 305 | 306 | public boolean isStale(long iteration) { 307 | return 1L << (iteration - lastUpdateIteration) > 308 | inactiveIterations * inactiveIterations; 309 | } 310 | } 311 | 312 | @Override 313 | public boolean hasUidInformation() { 314 | return true; 315 | } 316 | 317 | @Override 318 | public String getComponentName() { 319 | return "CPU"; 320 | } 321 | 322 | /* Returns the frequency of the processor in Mhz. If the frequency cannot 323 | * be determined returns a negative value instead. 324 | */ 325 | private double readCpuFreq(SystemInfo sysInfo) { 326 | /* Try to read from the /sys/devices file first. If that doesn't work 327 | * try manually inspecting the /proc/cpuinfo file. 328 | */ 329 | long cpuFreqKhz = sysInfo.readLongFromFile( 330 | "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"); 331 | if(cpuFreqKhz != -1) { 332 | return cpuFreqKhz / 1000.0; 333 | } 334 | 335 | FileReader fstream; 336 | try { 337 | fstream = new FileReader(CPU_FREQ_FILE); 338 | } catch (FileNotFoundException e) { 339 | Log.w(TAG, "Could not read cpu frequency file"); 340 | return -1; 341 | } 342 | BufferedReader in = new BufferedReader(fstream, 500); 343 | String line; 344 | try { 345 | while((line = in.readLine()) != null) { 346 | if(line.startsWith("BogoMIPS")) { 347 | return Double.parseDouble(line.trim().split("[ :]+")[1]); 348 | } 349 | } 350 | } catch(IOException e) { 351 | /* Failed to read from the cpu freq file. */ 352 | } catch(NumberFormatException e) { 353 | /* Frequency not formatted properly as a double. */ 354 | } 355 | Log.w(TAG, "Failed to read cpu frequency"); 356 | return -1; 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/LCD.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.PowerNotifications; 23 | import edu.umich.PowerTutor.service.IterationData; 24 | import edu.umich.PowerTutor.service.PowerData; 25 | import edu.umich.PowerTutor.util.ForegroundDetector; 26 | import edu.umich.PowerTutor.util.NotificationService; 27 | import edu.umich.PowerTutor.util.Recycler; 28 | import edu.umich.PowerTutor.util.SystemInfo; 29 | 30 | import android.app.ActivityManager; 31 | import android.content.BroadcastReceiver; 32 | import android.content.Context; 33 | import android.content.Intent; 34 | import android.content.IntentFilter; 35 | import android.provider.Settings; 36 | import android.os.Process; 37 | import android.util.Log; 38 | 39 | import java.io.File; 40 | import java.io.IOException; 41 | import java.io.OutputStreamWriter; 42 | import java.util.List; 43 | 44 | public class LCD extends PowerComponent { 45 | public static class LcdData extends PowerData { 46 | private static Recycler recycler = new Recycler(); 47 | 48 | public static LcdData obtain() { 49 | LcdData result = recycler.obtain(); 50 | if(result != null) return result; 51 | return new LcdData(); 52 | } 53 | 54 | @Override 55 | public void recycle() { 56 | recycler.recycle(this); 57 | } 58 | 59 | public int brightness; 60 | public boolean screenOn; 61 | 62 | private LcdData() { 63 | } 64 | 65 | public void init(int brightness, boolean screenOn) { 66 | this.brightness = brightness; 67 | this.screenOn = screenOn; 68 | } 69 | 70 | public void writeLogDataInfo(OutputStreamWriter out) throws IOException { 71 | StringBuilder res = new StringBuilder(); 72 | res.append("LCD-brightness ").append(brightness) 73 | .append("\nLCD-screen-on ").append(screenOn).append("\n"); 74 | out.write(res.toString()); 75 | } 76 | } 77 | 78 | private final String TAG = "LCD"; 79 | private static final String[] BACKLIGHT_BRIGHTNESS_FILES = { 80 | "/sys/devices/virtual/leds/lcd-backlight/brightness", 81 | "/sys/devices/platform/trout-backlight.0/leds/lcd-backlight/brightness", 82 | }; 83 | 84 | private Context context; 85 | private ForegroundDetector foregroundDetector; 86 | private BroadcastReceiver broadcastReceiver; 87 | private boolean screenOn; 88 | 89 | private String brightnessFile; 90 | 91 | public LCD(Context context) { 92 | this.context = context; 93 | screenOn = true; 94 | 95 | if(context == null) { 96 | return; 97 | } 98 | 99 | foregroundDetector = new ForegroundDetector((ActivityManager) 100 | context.getSystemService(context.ACTIVITY_SERVICE)); 101 | broadcastReceiver = new BroadcastReceiver() { 102 | public void onReceive(Context context, Intent intent) { 103 | synchronized(this) { 104 | if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 105 | screenOn = false; 106 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 107 | screenOn = true; 108 | } 109 | } 110 | }; 111 | }; 112 | IntentFilter intentFilter = new IntentFilter(); 113 | intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 114 | intentFilter.addAction(Intent.ACTION_SCREEN_ON); 115 | context.registerReceiver(broadcastReceiver, intentFilter); 116 | 117 | for(int i = 0; i < BACKLIGHT_BRIGHTNESS_FILES.length; i++) { 118 | if(new File(BACKLIGHT_BRIGHTNESS_FILES[i]).exists()) { 119 | brightnessFile = BACKLIGHT_BRIGHTNESS_FILES[i]; 120 | } 121 | } 122 | } 123 | 124 | @Override 125 | protected void onExit() { 126 | context.unregisterReceiver(broadcastReceiver); 127 | super.onExit(); 128 | } 129 | 130 | @Override 131 | public IterationData calculateIteration(long iteration) { 132 | IterationData result = IterationData.obtain(); 133 | 134 | boolean screen; 135 | synchronized(this) { 136 | screen = screenOn; 137 | } 138 | 139 | int brightness; 140 | if(brightnessFile != null) { 141 | brightness = (int)SystemInfo.getInstance() 142 | .readLongFromFile(brightnessFile); 143 | } else { 144 | try { 145 | brightness = Settings.System.getInt(context.getContentResolver(), 146 | Settings.System.SCREEN_BRIGHTNESS); 147 | } catch(Settings.SettingNotFoundException ex) { 148 | Log.w(TAG, "Could not retrieve brightness information"); 149 | return result; 150 | } 151 | } 152 | if(brightness < 0 || 255 < brightness) { 153 | Log.w(TAG, "Could not retrieve brightness information"); 154 | return result; 155 | } 156 | 157 | LcdData data = LcdData.obtain(); 158 | data.init(brightness, screen); 159 | result.setPowerData(data); 160 | 161 | if(screen) { 162 | LcdData uidData = LcdData.obtain(); 163 | uidData.init(brightness, screen); 164 | result.addUidPowerData(foregroundDetector.getForegroundUid(), uidData); 165 | } 166 | 167 | return result; 168 | } 169 | 170 | @Override 171 | public boolean hasUidInformation() { 172 | return true; 173 | } 174 | 175 | @Override 176 | public String getComponentName() { 177 | return "LCD"; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/OLED.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.PowerNotifications; 23 | import edu.umich.PowerTutor.phone.PhoneConstants; 24 | import edu.umich.PowerTutor.service.IterationData; 25 | import edu.umich.PowerTutor.service.PowerData; 26 | import edu.umich.PowerTutor.util.NativeLoader; 27 | import edu.umich.PowerTutor.util.NotificationService; 28 | import edu.umich.PowerTutor.util.Recycler; 29 | import edu.umich.PowerTutor.util.SystemInfo; 30 | import edu.umich.PowerTutor.util.ForegroundDetector; 31 | 32 | import android.app.ActivityManager; 33 | import android.content.BroadcastReceiver; 34 | import android.content.Context; 35 | import android.content.Intent; 36 | import android.content.IntentFilter; 37 | import android.provider.Settings; 38 | import android.os.Process; 39 | import android.util.Log; 40 | import android.util.DisplayMetrics; 41 | import android.view.WindowManager; 42 | 43 | import java.io.DataOutputStream; 44 | import java.io.File; 45 | import java.io.FileInputStream; 46 | import java.io.FileNotFoundException; 47 | import java.io.RandomAccessFile; 48 | import java.io.IOException; 49 | import java.io.OutputStreamWriter; 50 | import java.util.List; 51 | import java.util.Random; 52 | 53 | import java.io.*; 54 | import java.nio.*; 55 | import java.nio.channels.*; 56 | 57 | public class OLED extends PowerComponent { 58 | public static class OledData extends PowerData { 59 | private static Recycler recycler = new Recycler(); 60 | 61 | public static OledData obtain() { 62 | OledData result = recycler.obtain(); 63 | if(result != null) return result; 64 | return new OledData(); 65 | } 66 | 67 | @Override 68 | public void recycle() { 69 | recycler.recycle(this); 70 | } 71 | 72 | public int brightness; 73 | public double pixPower; 74 | public boolean screenOn; 75 | 76 | private OledData() { 77 | } 78 | 79 | public void init() { 80 | this.screenOn = false; 81 | } 82 | 83 | public void init(int brightness, double pixPower) { 84 | screenOn = true; 85 | this.brightness = brightness; 86 | this.pixPower = pixPower; 87 | } 88 | 89 | public void writeLogDataInfo(OutputStreamWriter out) throws IOException { 90 | out.write("OLED-brightness " + brightness + "\n"); 91 | out.write("OLED-pix-power " + pixPower + "\n"); 92 | out.write("OLED-screen-on " + screenOn + "\n"); 93 | } 94 | } 95 | 96 | private static final String TAG = "OLED"; 97 | private static final String[] BACKLIGHT_BRIGHTNESS_FILES = { 98 | "/sys/class/leds/lcd-backlight/brightness", 99 | "/sys/devices/virtual/leds/lcd-backlight/brightness", 100 | "/sys/devices/platform/trout-backlight.0/leds/lcd-backlight/brightness", 101 | }; 102 | 103 | private Context context; 104 | private ForegroundDetector foregroundDetector; 105 | private BroadcastReceiver broadcastReceiver; 106 | private boolean screenOn; 107 | 108 | private File frameBufferFile; 109 | 110 | private int screenWidth; 111 | private int screenHeight; 112 | 113 | private static final int NUMBER_OF_SAMPLES = 500; 114 | private int[] samples; 115 | 116 | private String brightnessFile; 117 | 118 | /* Coefficients pre-computed for pix power calculations. 119 | */ 120 | private double rcoef; 121 | private double gcoef; 122 | private double bcoef; 123 | private double modul_coef; 124 | 125 | public OLED(Context context, PhoneConstants constants) { 126 | this.context = context; 127 | screenOn = true; 128 | 129 | foregroundDetector = new ForegroundDetector((ActivityManager) 130 | context.getSystemService(context.ACTIVITY_SERVICE)); 131 | broadcastReceiver = new BroadcastReceiver() { 132 | public void onReceive(Context context, Intent intent) { 133 | synchronized(this) { 134 | if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 135 | screenOn = false; 136 | } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { 137 | screenOn = true; 138 | } 139 | } 140 | }; 141 | }; 142 | IntentFilter intentFilter = new IntentFilter(); 143 | intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 144 | intentFilter.addAction(Intent.ACTION_SCREEN_ON); 145 | context.registerReceiver(broadcastReceiver, intentFilter); 146 | 147 | frameBufferFile = new File("/dev/fb0"); 148 | if(!frameBufferFile.exists()) { 149 | frameBufferFile = new File("/dev/graphics/fb0"); 150 | } 151 | if(frameBufferFile.exists()) try { 152 | /* Check if we already have permission to read the frame buffer. */ 153 | boolean readOk = false; 154 | try { 155 | RandomAccessFile fin = new RandomAccessFile(frameBufferFile, "r"); 156 | int b = fin.read(); 157 | fin.close(); 158 | readOk = true; 159 | } catch(IOException e) { 160 | } 161 | /* Don't have permission, try to change permission as root. */ 162 | if(!readOk) { 163 | java.lang.Process p = Runtime.getRuntime().exec("su"); 164 | DataOutputStream os = new DataOutputStream(p.getOutputStream()); 165 | os.writeBytes("chown " + android.os.Process.myUid() + 166 | " " + frameBufferFile.getAbsolutePath() + "\n"); 167 | os.writeBytes("chown app_" + (android.os.Process.myUid() - 168 | SystemInfo.AID_APP) + 169 | " " + frameBufferFile.getAbsolutePath() + "\n"); 170 | os.writeBytes("chmod 660 " + frameBufferFile.getAbsolutePath() + "\n"); 171 | os.writeBytes("exit\n"); 172 | os.flush(); 173 | p.waitFor(); 174 | if(p.exitValue() != 0) { 175 | Log.i(TAG, "failed to change permissions on frame buffer"); 176 | } 177 | } 178 | } catch (InterruptedException e) { 179 | Log.i(TAG, "changing permissions on frame buffer interrupted"); 180 | } catch (IOException e) { 181 | Log.i(TAG, "unexpected exception while changing permission on " + 182 | "frame buffer"); 183 | e.printStackTrace(); 184 | } 185 | 186 | DisplayMetrics metrics = new DisplayMetrics(); 187 | WindowManager windowManager = 188 | (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 189 | windowManager.getDefaultDisplay().getMetrics(metrics); 190 | screenWidth = metrics.widthPixels; 191 | screenHeight = metrics.heightPixels; 192 | 193 | Random r = new Random(); 194 | samples = new int[NUMBER_OF_SAMPLES]; 195 | for(int i = 0; i < NUMBER_OF_SAMPLES; i++) { 196 | int a = screenWidth * screenHeight * i / NUMBER_OF_SAMPLES; 197 | int b = screenWidth * screenHeight * (i + 1) / NUMBER_OF_SAMPLES; 198 | samples[i] = a + r.nextInt(b - a); 199 | } 200 | 201 | double[] channel = constants.oledChannelPower(); 202 | rcoef = channel[0] / 255 / 255; 203 | gcoef = channel[1] / 255 / 255; 204 | bcoef = channel[2] / 255 / 255; 205 | modul_coef = constants.oledModulation() / 255 / 255 / 3 / 3; 206 | 207 | for(int i = 0; i < BACKLIGHT_BRIGHTNESS_FILES.length; i++) { 208 | if(new File(BACKLIGHT_BRIGHTNESS_FILES[i]).exists()) { 209 | brightnessFile = BACKLIGHT_BRIGHTNESS_FILES[i]; 210 | } 211 | } 212 | } 213 | 214 | @Override 215 | protected void onExit() { 216 | context.unregisterReceiver(broadcastReceiver); 217 | super.onExit(); 218 | } 219 | 220 | @Override 221 | public IterationData calculateIteration(long iteration) { 222 | IterationData result = IterationData.obtain(); 223 | 224 | boolean screen; 225 | synchronized(this) { 226 | screen = screenOn; 227 | } 228 | 229 | int brightness; 230 | if(brightnessFile != null) { 231 | brightness = (int)SystemInfo.getInstance() 232 | .readLongFromFile(brightnessFile); 233 | } else { 234 | try { 235 | brightness = Settings.System.getInt(context.getContentResolver(), 236 | Settings.System.SCREEN_BRIGHTNESS); 237 | } catch(Settings.SettingNotFoundException ex) { 238 | Log.w(TAG, "Could not retrieve brightness information"); 239 | return result; 240 | } 241 | } 242 | if(brightness < 0 || 255 < brightness) { 243 | Log.w(TAG, "Could not retrieve brightness information"); 244 | return result; 245 | } 246 | 247 | double pixPower = 0; 248 | if(screen && frameBufferFile.exists()) { 249 | if(NativeLoader.jniLoaded()) { 250 | pixPower = getScreenPixPower(rcoef, gcoef, bcoef, modul_coef); 251 | } else try { 252 | RandomAccessFile fin = new RandomAccessFile(frameBufferFile, "r"); 253 | 254 | for(int x : samples) { 255 | fin.seek(x * 4); 256 | int px = fin.readInt(); 257 | int b = px >> 8 & 0xFF; 258 | int g = px >> 16 & 0xFF; 259 | int r = px >> 24 & 0xFF; 260 | 261 | /* Calculate the power usage of this one pixel if it were at full 262 | * brightness. Linearly scale by brightness to get true power 263 | * consumption. To calculate whole screen compute average of sampled 264 | * region and multiply by number of pixels. 265 | */ 266 | int modul_val = r + g + b; 267 | pixPower += rcoef * (r * r) + gcoef * (g * g) + bcoef * (b * b) - 268 | modul_coef * (modul_val * modul_val); 269 | } 270 | fin.close(); 271 | } catch(FileNotFoundException e) { 272 | pixPower = -1; 273 | } catch(IOException e) { 274 | pixPower = -1; 275 | e.printStackTrace(); 276 | } 277 | if(pixPower >= 0) { 278 | pixPower *= 1.0 * screenWidth * screenHeight / NUMBER_OF_SAMPLES; 279 | } 280 | } 281 | 282 | OledData data = OledData.obtain(); 283 | if(!screen) { 284 | data.init(); 285 | } else { 286 | data.init(brightness, pixPower); 287 | } 288 | result.setPowerData(data); 289 | 290 | if(screen) { 291 | OledData uidData = OledData.obtain(); 292 | uidData.init(brightness, pixPower); 293 | result.addUidPowerData(foregroundDetector.getForegroundUid(), uidData); 294 | } 295 | 296 | return result; 297 | } 298 | 299 | @Override 300 | public boolean hasUidInformation() { 301 | return true; 302 | } 303 | 304 | @Override 305 | public String getComponentName() { 306 | return "OLED"; 307 | } 308 | 309 | public static native double getScreenPixPower(double rcoef, double gcoef, 310 | double bcoef, double modul_coef); 311 | } 312 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/PowerComponent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.service.IterationData; 23 | 24 | import android.os.SystemClock; 25 | import android.util.Log; 26 | 27 | public abstract class PowerComponent extends Thread { 28 | private final String TAG = "PowerComponent"; 29 | 30 | /* Extending classes need to override the calculateIteration function. It 31 | * should calculate the data point for the given component in a timely 32 | * manner (under 1 second, longer times will cause data to be missed). 33 | * The iteration parameter can be ignored in most cases. 34 | */ 35 | protected abstract IterationData calculateIteration(long iteration); 36 | 37 | /* Extending classes should provide a recognizable name for this component 38 | * to be used when writing to logs. 39 | */ 40 | public abstract String getComponentName(); 41 | 42 | /* Returns true if this component collects usage information per uid. 43 | */ 44 | public boolean hasUidInformation() { 45 | return false; 46 | } 47 | 48 | /* Called when the thread running this interface is asked to exit. 49 | */ 50 | protected void onExit() { 51 | } 52 | 53 | /* In general we should only need to buffer two data elements. 54 | */ 55 | private IterationData data1; 56 | private IterationData data2; 57 | private long iteration1; 58 | private long iteration2; 59 | 60 | protected long beginTime; 61 | protected long iterationInterval; 62 | 63 | public PowerComponent() { 64 | setDaemon(true); 65 | } 66 | 67 | /* This is called once at the begginning of the daemon loop. 68 | */ 69 | public void init(long beginTime, long iterationInterval) { 70 | this.beginTime = beginTime; 71 | this.iterationInterval = iterationInterval; 72 | data1 = data2 = null; 73 | iteration1 = iteration2 = -1; 74 | } 75 | 76 | /* Runs the daemon loop that collects data for this component. */ 77 | public void run() { 78 | android.os.Process.setThreadPriority( 79 | android.os.Process.THREAD_PRIORITY_MORE_FAVORABLE); 80 | for(long iter = 0; !Thread.interrupted(); ) { 81 | /* Hand off to the client class to actually calculate the information 82 | * we want for this component. 83 | */ 84 | IterationData data = calculateIteration(iter); 85 | if(data != null) { 86 | synchronized(this) { 87 | if(iteration1 < iteration2) { 88 | iteration1 = iter; 89 | data1 = data; 90 | } else { 91 | iteration2 = iter; 92 | data2 = data; 93 | } 94 | } 95 | } 96 | if(interrupted()) { 97 | break; 98 | } 99 | 100 | long curTime = SystemClock.elapsedRealtime(); 101 | /* Compute the next iteration that we can make the start of. */ 102 | long oldIter = iter; 103 | iter = (long)Math.max(iter + 1, 104 | 1 + (curTime - beginTime) / iterationInterval); 105 | if(oldIter + 1 != iter) { 106 | Log.w(TAG, "[" + getComponentName() + "] Had to skip from iteration " + 107 | oldIter + " to " + iter); 108 | } 109 | /* Sleep until the next iteration completes. */ 110 | try { 111 | sleep(beginTime + iter * iterationInterval - curTime); 112 | } catch(InterruptedException e) { 113 | break; 114 | } 115 | } 116 | onExit(); 117 | } 118 | 119 | /* Returns the data point for the given iteration. This method will be called 120 | with a strictly increasing iteration parameter. 121 | */ 122 | public IterationData getData(long iteration) { 123 | synchronized(this) { 124 | IterationData ret = null; 125 | if(iteration == iteration1) ret = data1; 126 | if(iteration == iteration2) ret = data2; 127 | if(iteration1 <= iteration) { 128 | data1 = null; 129 | iteration1 = -1; 130 | } 131 | if(iteration2 <= iteration) { 132 | data2 = null; 133 | iteration2 = -1; 134 | } 135 | if(ret == null) { 136 | Log.w(TAG, "[" + getComponentName() + "] Could not find data for " + 137 | "requested iteration"); 138 | } 139 | return ret; 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/components/Sensors.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.components; 21 | 22 | import edu.umich.PowerTutor.PowerNotifications; 23 | import edu.umich.PowerTutor.service.IterationData; 24 | import edu.umich.PowerTutor.service.PowerData; 25 | import edu.umich.PowerTutor.util.NotificationService; 26 | import edu.umich.PowerTutor.util.Recycler; 27 | import edu.umich.PowerTutor.util.SystemInfo; 28 | 29 | import android.content.Context; 30 | import android.hardware.SensorManager; 31 | import android.os.SystemClock; 32 | import android.util.Log; 33 | import android.util.SparseArray; 34 | 35 | import java.io.IOException; 36 | import java.io.OutputStreamWriter; 37 | import java.util.Set; 38 | import java.util.TreeSet; 39 | import java.util.Map; 40 | import java.util.TreeMap; 41 | 42 | public class Sensors extends PowerComponent { 43 | private final String TAG = "Sensors"; 44 | public static final int MAX_SENSORS = 10; 45 | 46 | public static class SensorData extends PowerData { 47 | private static Recycler recycler = new Recycler(); 48 | 49 | public static SensorData obtain() { 50 | SensorData result = recycler.obtain(); 51 | if(result != null) return result; 52 | return new SensorData(); 53 | } 54 | 55 | @Override 56 | public void recycle() { 57 | recycler.recycle(this); 58 | } 59 | 60 | public double[] onTime; 61 | 62 | private SensorData() { 63 | onTime = new double[MAX_SENSORS]; 64 | } 65 | 66 | public void writeLogDataInfo(OutputStreamWriter out) throws IOException { 67 | StringBuilder res = new StringBuilder(); 68 | for(int i = 0; i < MAX_SENSORS; i++) { 69 | if(onTime[i] > 1e-7) { 70 | res.append("Sensors-time ").append(i).append(" ") 71 | .append(onTime[i]).append("\n"); 72 | } 73 | } 74 | out.write(res.toString()); 75 | } 76 | } 77 | 78 | private Context context; 79 | private SensorManager sensorManager; 80 | private PowerNotifications sensorHook; 81 | 82 | private SensorStateKeeper sensorState; 83 | private SparseArray uidStates; 84 | 85 | public Sensors(Context context) { 86 | this.context = context; 87 | sensorState = new SensorStateKeeper(); 88 | uidStates = new SparseArray(); 89 | 90 | if(!NotificationService.available()) { 91 | Log.w(TAG, "Sensor component created although no notification service " + 92 | "available to receive sensor usage information"); 93 | return; 94 | } 95 | sensorManager = (SensorManager)context.getSystemService( 96 | Context.SENSOR_SERVICE); 97 | sensorHook = new NotificationService.DefaultReceiver() { 98 | public void noteStartSensor(int uid, int sensor) { 99 | if(sensor < 0 || MAX_SENSORS <= sensor) { 100 | Log.w(TAG, "Received sensor outside of accepted range"); 101 | return; 102 | } 103 | synchronized(sensorState) { 104 | sensorState.startSensor(sensor); 105 | SensorStateKeeper uidState = uidStates.get(uid); 106 | if(uidState == null) { 107 | uidState = new SensorStateKeeper(); 108 | uidStates.put(uid, uidState); 109 | } 110 | uidState.startSensor(sensor); 111 | } 112 | } 113 | 114 | public void noteStopSensor(int uid, int sensor) { 115 | if(sensor < 0 || MAX_SENSORS <= sensor) { 116 | Log.w(TAG, "Received sensor outside of accepted range"); 117 | return; 118 | } 119 | synchronized(sensorState) { 120 | sensorState.stopSensor(sensor); 121 | SensorStateKeeper uidState = uidStates.get(uid); 122 | if(uidState == null) { 123 | uidState = new SensorStateKeeper(); 124 | uidStates.put(uid, uidState); 125 | } 126 | uidState.stopSensor(sensor); 127 | } 128 | } 129 | }; 130 | NotificationService.addHook(sensorHook); 131 | } 132 | 133 | @Override 134 | protected void onExit() { 135 | super.onExit(); 136 | NotificationService.removeHook(sensorHook); 137 | } 138 | 139 | @Override 140 | public IterationData calculateIteration(long iteration) { 141 | IterationData result = IterationData.obtain(); 142 | synchronized(sensorState) { 143 | SensorData globalData = SensorData.obtain(); 144 | sensorState.setupSensorTimes(globalData.onTime, iterationInterval); 145 | result.setPowerData(globalData); 146 | 147 | for(int i = 0; i < uidStates.size(); i++) { 148 | int uid = uidStates.keyAt(i); 149 | SensorStateKeeper uidState = uidStates.valueAt(i); 150 | SensorData uidData = SensorData.obtain(); 151 | uidState.setupSensorTimes(uidData.onTime, iterationInterval); 152 | result.addUidPowerData(uid, uidData); 153 | 154 | if(uidState.sensorsOn() == 0) { 155 | uidStates.remove(uid); 156 | i--; 157 | } 158 | } 159 | } 160 | return result; 161 | } 162 | 163 | private static class SensorStateKeeper { 164 | private int[] nesting; 165 | private long[] times; 166 | private long lastTime; 167 | private int count; 168 | 169 | public SensorStateKeeper() { 170 | nesting = new int[MAX_SENSORS]; 171 | times = new long[MAX_SENSORS]; 172 | lastTime = SystemClock.elapsedRealtime(); 173 | } 174 | 175 | public void startSensor(int sensor) { 176 | if(nesting[sensor]++ == 0) { 177 | times[sensor] -= SystemClock.elapsedRealtime() - lastTime; 178 | count++; 179 | } 180 | } 181 | 182 | public void stopSensor(int sensor) { 183 | if(nesting[sensor] == 0) { 184 | return; 185 | } else if(--nesting[sensor] == 0) { 186 | times[sensor] += SystemClock.elapsedRealtime() - lastTime; 187 | count--; 188 | } 189 | } 190 | 191 | public int sensorsOn() { 192 | return count; 193 | } 194 | 195 | public void setupSensorTimes(double[] sensorTimes, long iterationInterval) { 196 | long now = SystemClock.elapsedRealtime(); 197 | long div = now - lastTime; 198 | if(div <= 0) div = 1; 199 | for(int i = 0; i < MAX_SENSORS; i++) { 200 | sensorTimes[i] = 1.0 * (times[i] + 201 | (nesting[i] > 0 ? now - lastTime : 0)) / div; 202 | times[i] = 0; 203 | } 204 | lastTime = now; 205 | } 206 | } 207 | 208 | @Override 209 | public boolean hasUidInformation() { 210 | return true; 211 | } 212 | 213 | @Override 214 | public String getComponentName() { 215 | return "Sensors"; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/DreamConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import android.content.Context; 23 | import android.hardware.Sensor; 24 | import android.hardware.SensorManager; 25 | 26 | import edu.umich.PowerTutor.components.Sensors; 27 | 28 | public class DreamConstants implements PhoneConstants { 29 | protected static final String OPER_TMOBILE = "T - Mobile"; 30 | protected static final String OPER_ATT = "AT&T"; 31 | 32 | /* TODO: Figure out if this is really appropriate or how we should convert 33 | * the sensor power ratings (in mA) to mW. I'm not sure we'll try to model 34 | * these thing's power usage but for the developer it's definitely interesting 35 | * to get some (perhaps rough?) idea of how much power sensors are using. 36 | */ 37 | protected double BATTERY_VOLTAGE = 3.7; 38 | 39 | public DreamConstants(Context context) { 40 | SensorManager sensorManager = (SensorManager)context.getSystemService( 41 | Context.SENSOR_SERVICE); 42 | sensorPowerArray = new double[Sensors.MAX_SENSORS]; 43 | for(int i = 0; i < Sensors.MAX_SENSORS; i++) { 44 | Sensor sensor = sensorManager.getDefaultSensor(i); 45 | if(sensor != null) { 46 | sensorPowerArray[i] = sensor.getPower() * BATTERY_VOLTAGE; 47 | } 48 | } 49 | } 50 | 51 | public String modelName() { 52 | return "dream"; 53 | } 54 | 55 | public double maxPower() { 56 | return 2800; 57 | } 58 | 59 | public double lcdBrightness() { 60 | return 2.40276; 61 | } 62 | 63 | public double lcdBacklight() { 64 | return 121.4606 + 166.5; 65 | } 66 | 67 | public double oledBasePower() { 68 | throw new RuntimeException("oledBasePower() called on device with no " + 69 | "OLED display"); 70 | } 71 | 72 | public double[] oledChannelPower() { 73 | throw new RuntimeException("oledChannelPower() called on device with no " + 74 | "OLED display"); 75 | } 76 | 77 | public double oledModulation() { 78 | throw new RuntimeException("oledModulation() called on device with no " + 79 | "OLED display"); 80 | } 81 | 82 | private static final double[] arrayCpuPowerRatios = {3.4169, 4.3388}; 83 | public double[] cpuPowerRatios() { 84 | return arrayCpuPowerRatios; 85 | } 86 | 87 | private static final double[] arrayCpuFreqs = {245.36, 383.38}; 88 | public double[] cpuFreqs() { 89 | return arrayCpuFreqs; 90 | } 91 | 92 | public double audioPower() { 93 | return 384.62; 94 | } 95 | 96 | private static final double[] arrayGpsStatePower = {0.0, 173.55, 429.55}; 97 | public double[] gpsStatePower() { 98 | return arrayGpsStatePower; 99 | } 100 | 101 | public double gpsSleepTime() { 102 | return 6.0; 103 | } 104 | 105 | public double wifiLowPower() { 106 | return 38.554; 107 | } 108 | 109 | public double wifiHighPower() { 110 | return 720; 111 | } 112 | 113 | public double wifiLowHighTransition() { 114 | return 15; 115 | } 116 | 117 | public double wifiHighLowTransition() { 118 | return 8; 119 | } 120 | 121 | private static final double[] arrayWifiLinkRatios = { 122 | 47.122645, 46.354821, 43.667437, 43.283525, 40.980053, 39.44422, 38.676581, 123 | 34.069637, 29.462693, 20.248805, 11.034917, 6.427122 124 | }; 125 | public double[] wifiLinkRatios() { 126 | return arrayWifiLinkRatios; 127 | } 128 | 129 | private static final double[] arrayWifiLinkSpeeds = { 130 | 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54 131 | }; 132 | public double[] wifiLinkSpeeds() { 133 | return arrayWifiLinkSpeeds; 134 | } 135 | 136 | public String threegInterface() { 137 | return "rmnet0"; 138 | } 139 | 140 | public double threegIdlePower(String oper) { 141 | if(OPER_TMOBILE.equals(oper)) { 142 | return 10; 143 | } 144 | return 10; 145 | } 146 | 147 | public double threegFachPower(String oper) { 148 | if(OPER_TMOBILE.equals(oper)) { 149 | return 401; 150 | } 151 | return 401; 152 | } 153 | 154 | public double threegDchPower(String oper) { 155 | if(OPER_TMOBILE.equals(oper)) { 156 | return 570; 157 | } 158 | return 570; 159 | } 160 | 161 | public int threegDchFachDelay(String oper) { 162 | if(OPER_TMOBILE.equals(oper)) { 163 | return 6; 164 | } else if(OPER_ATT.equals(oper)) { 165 | return 5; 166 | } 167 | return 4; 168 | } 169 | 170 | public int threegFachIdleDelay(String oper) { 171 | if(OPER_TMOBILE.equals(oper)) { 172 | return 4; 173 | } else if(OPER_ATT.equals(oper)) { 174 | return 12; 175 | } 176 | return 6; 177 | } 178 | 179 | public int threegUplinkQueue(String oper) { 180 | return 151; 181 | } 182 | 183 | public int threegDownlinkQueue(String oper) { 184 | return 119; 185 | } 186 | 187 | private double[] sensorPowerArray; 188 | public double[] sensorPower() { 189 | return sensorPowerArray; 190 | } 191 | 192 | public double getMaxPower(String componentName) { 193 | if("LCD".equals(componentName)) { 194 | return lcdBacklight() + lcdBrightness() * 255; 195 | } else if("CPU".equals(componentName)) { 196 | double[] ratios = cpuPowerRatios(); 197 | return ratios[ratios.length - 1] * 100; 198 | } else if("Audio".equals(componentName)) { 199 | return audioPower(); 200 | } else if("GPS".equals(componentName)) { 201 | double[] gpsPow = gpsStatePower(); 202 | return gpsPow[gpsPow.length - 1]; 203 | } else if("Wifi".equals(componentName)) { 204 | // TODO: Get a better estimation going here. 205 | return 800; 206 | } else if("3G".equals(componentName)) { 207 | return threegDchPower(""); 208 | } else if("Sensors".equals(componentName)) { 209 | double res = 0; 210 | for(double x : sensorPower()) res += x; 211 | return res; 212 | } else { 213 | return 900; 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/DreamPowerCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import edu.umich.PowerTutor.components.*; 23 | import edu.umich.PowerTutor.components.LCD.LcdData; 24 | import edu.umich.PowerTutor.components.OLED.OledData; 25 | import edu.umich.PowerTutor.components.CPU.CpuData; 26 | import edu.umich.PowerTutor.components.Audio.AudioData; 27 | import edu.umich.PowerTutor.components.GPS.GpsData; 28 | import edu.umich.PowerTutor.components.Wifi.WifiData; 29 | import edu.umich.PowerTutor.components.Threeg.ThreegData; 30 | import edu.umich.PowerTutor.components.Sensors.SensorData; 31 | 32 | import android.content.Context; 33 | 34 | public class DreamPowerCalculator implements PhonePowerCalculator { 35 | protected PhoneConstants coeffs; 36 | 37 | public DreamPowerCalculator(Context context) { 38 | this(new DreamConstants(context)); 39 | } 40 | 41 | protected DreamPowerCalculator(PhoneConstants coeffs) { 42 | this.coeffs = coeffs; 43 | } 44 | 45 | public double getLcdPower(LcdData data) { 46 | return data.screenOn ? 47 | coeffs.lcdBrightness() * data.brightness + coeffs.lcdBacklight() : 0; 48 | } 49 | 50 | public double getOledPower(OledData data) { 51 | throw new RuntimeException("getOledPower() should not be called for Dream"); 52 | } 53 | 54 | public double getCpuPower(CpuData data) { 55 | /* Find the two nearest cpu frequency and linearly interpolate 56 | * the power ratio for that frequency. 57 | */ 58 | double[] powerRatios = coeffs.cpuPowerRatios(); 59 | double[] freqs = coeffs.cpuFreqs(); 60 | double ratio; 61 | if(powerRatios.length == 1) { 62 | ratio = powerRatios[0]; 63 | } else { 64 | double sfreq = data.freq; 65 | if(sfreq < freqs[0]) sfreq = freqs[0]; 66 | if(sfreq > freqs[freqs.length - 1]) sfreq = freqs[freqs.length - 1]; 67 | 68 | int ind = upperBound(freqs, sfreq); 69 | if(ind == 0) ind++; 70 | if(ind == freqs.length) ind--; 71 | ratio = powerRatios[ind - 1] + (powerRatios[ind] - powerRatios[ind - 1]) / 72 | (freqs[ind] - freqs[ind - 1]) * 73 | (sfreq - freqs[ind - 1]); 74 | } 75 | return Math.max(0, ratio * (data.usrPerc + data.sysPerc)); 76 | } 77 | 78 | public double getAudioPower(AudioData data) { 79 | return data.musicOn ? coeffs.audioPower() : 0; 80 | } 81 | 82 | public double getGpsPower(GpsData data) { 83 | double result = 0; 84 | double statePower[] = coeffs.gpsStatePower(); 85 | for(int i = 0; i < GPS.POWER_STATES; i++) { 86 | result += data.stateTimes[i] * statePower[i]; 87 | } 88 | return result; 89 | } 90 | 91 | public double getWifiPower(WifiData data) { 92 | if(!data.wifiOn) { 93 | return 0; 94 | } else if(data.powerState == Wifi.POWER_STATE_LOW) { 95 | return coeffs.wifiLowPower(); 96 | } else if(data.powerState == Wifi.POWER_STATE_HIGH) { 97 | double[] linkSpeeds = coeffs.wifiLinkSpeeds(); 98 | double[] linkRatios = coeffs.wifiLinkRatios(); 99 | double ratio; 100 | if(linkSpeeds.length == 1) { 101 | /* If there is only one set speed we have to use its ratio as we have 102 | * nothing else to go on. 103 | */ 104 | ratio = linkRatios[0]; 105 | } else { 106 | /* Find the two nearest speed/ratio pairs and linearly interpolate 107 | * the ratio for this link speed. 108 | */ 109 | int ind = upperBound(linkSpeeds, data.linkSpeed); 110 | if(ind == 0) ind++; 111 | if(ind == linkSpeeds.length) ind--; 112 | ratio = linkRatios[ind - 1] + (linkRatios[ind] - linkRatios[ind - 1]) / 113 | (linkSpeeds[ind] - linkSpeeds[ind - 1]) * 114 | (data.linkSpeed - linkSpeeds[ind - 1]); 115 | } 116 | return Math.max(0, coeffs.wifiHighPower() + ratio * data.uplinkRate); 117 | } 118 | throw new RuntimeException("Unexpected power state"); 119 | } 120 | 121 | public double getThreeGPower(ThreegData data) { 122 | if(!data.threegOn) { 123 | return 0; 124 | } else { 125 | switch(data.powerState) { 126 | case Threeg.POWER_STATE_IDLE: 127 | return coeffs.threegIdlePower(data.oper); 128 | case Threeg.POWER_STATE_FACH: 129 | return coeffs.threegFachPower(data.oper); 130 | case Threeg.POWER_STATE_DCH: 131 | return coeffs.threegDchPower(data.oper); 132 | } 133 | } 134 | return 0; 135 | } 136 | 137 | public double getSensorPower(SensorData data) { 138 | double result = 0; 139 | double[] powerUse = coeffs.sensorPower(); 140 | for(int i = 0; i < Sensors.MAX_SENSORS; i++) { 141 | result += data.onTime[i] * powerUse[i]; 142 | } 143 | return result; 144 | } 145 | 146 | /* Returns the largest index y such that if x were inserted into A (which 147 | * should already be sorted) at y then A would remain sorted. 148 | */ 149 | protected static int upperBound(double[] A, double x) { 150 | int lo = 0; 151 | int hi = A.length; 152 | while(lo < hi) { 153 | int mid = lo + (hi - lo) / 2; 154 | if(A[mid] <= x) { 155 | lo = mid + 1; 156 | } else { 157 | hi = mid; 158 | } 159 | } 160 | return lo; 161 | } 162 | } 163 | 164 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PassionConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import android.content.Context; 23 | import android.util.DisplayMetrics; 24 | import android.view.WindowManager; 25 | 26 | public class PassionConstants extends DreamConstants { 27 | protected int screenWidth; 28 | protected int screenHeight; 29 | 30 | public PassionConstants(Context context) { 31 | super(context); 32 | DisplayMetrics metrics = new DisplayMetrics(); 33 | WindowManager windowManager = 34 | (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 35 | windowManager.getDefaultDisplay().getMetrics(metrics); 36 | screenWidth = metrics.widthPixels; 37 | screenHeight = metrics.heightPixels; 38 | } 39 | 40 | public String modelName() { 41 | return "passion"; 42 | } 43 | 44 | public double maxPower() { 45 | return 2800; 46 | } 47 | 48 | public double lcdBrightness() { 49 | return 1.2217; 50 | } 51 | 52 | public double lcdBacklight() { 53 | throw new RuntimeException("lcdBacklight() for passion which has no LCD " + 54 | "display"); 55 | } 56 | 57 | public double oledBasePower() { 58 | return 365; // This incorporates all the constant component in the model. 59 | } 60 | 61 | private static final double[] arrayChannelPower = { 62 | 3.0647e-006, 4.4799e-006, 6.4045e-006}; 63 | public double[] oledChannelPower() { 64 | return arrayChannelPower; 65 | } 66 | 67 | public double oledModulation() { 68 | return 1.7582e-006; 69 | } 70 | 71 | private static final double[] arrayCpuPowerRatios = {1.1273, 1.5907, 1.8736, 72 | 2.1745, 2.6031, 2.9612, 3.1373,3.4513, 3.9073 ,4.1959, 4.6492, 5.4818}; 73 | public double[] cpuPowerRatios() { 74 | return arrayCpuPowerRatios; 75 | } 76 | 77 | private static final double[] arrayCpuFreqs = {245, 384, 460, 499, 576, 614, 78 | 653, 691, 768, 806, 845, 998}; 79 | public double[] cpuFreqs() { 80 | return arrayCpuFreqs; 81 | } 82 | 83 | public double audioPower() { 84 | return 106.81; 85 | } 86 | 87 | private static final double[] arrayGpsStatePower = {0.0, 17.5, 268.94}; 88 | public double[] gpsStatePower() { 89 | return arrayGpsStatePower; 90 | } 91 | 92 | public double gpsSleepTime() { 93 | return 6.0; 94 | } 95 | 96 | public double wifiLowPower() { 97 | return 34.37; 98 | } 99 | 100 | public double wifiHighPower() { 101 | return 404.46 ; 102 | } 103 | 104 | public double wifiLowHighTransition() { 105 | return 15; 106 | } 107 | 108 | public double wifiHighLowTransition() { 109 | return 8; 110 | } 111 | 112 | private static final double[] arrayWifiLinkRatios = { 113 | 47.122645, 46.354821, 43.667437, 43.283525, 40.980053, 39.44422, 38.676581, 114 | 34.069637, 29.462693, 20.248805, 11.034917, 6.427122 115 | }; 116 | public double[] wifiLinkRatios() { 117 | return arrayWifiLinkRatios; 118 | } 119 | 120 | private static final double[] arrayWifiLinkSpeeds = { 121 | 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54 122 | }; 123 | public double[] wifiLinkSpeeds() { 124 | return arrayWifiLinkSpeeds; 125 | } 126 | 127 | public String threegInterface() { 128 | return "rmnet0"; 129 | } 130 | 131 | public double threegIdlePower(String oper) { 132 | if(OPER_TMOBILE.equals(oper)) { 133 | return 10; 134 | } 135 | return 10; // Return the worst case for unknown operators. 136 | } 137 | 138 | public double threegFachPower(String oper) { 139 | if(OPER_TMOBILE.equals(oper)) { 140 | return 405.81; 141 | } 142 | return 405.81; // Return the worst case for unknown operators. 143 | } 144 | 145 | public double threegDchPower(String oper) { 146 | if(OPER_TMOBILE.equals(oper)) { 147 | return 902.03; 148 | } 149 | return 902.03; // Return the worst case for unknown operators. 150 | } 151 | 152 | public double getMaxPower(String componentName) { 153 | if("OLED".equals(componentName)) { 154 | double[] channel = oledChannelPower(); 155 | return oledBasePower() + 255 * screenWidth * screenHeight * 156 | (channel[0] + channel[1] + channel[2] - oledModulation()); 157 | } 158 | return super.getMaxPower(componentName); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PassionPowerCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import edu.umich.PowerTutor.components.LCD.LcdData; 23 | import edu.umich.PowerTutor.components.OLED.OledData; 24 | import edu.umich.PowerTutor.components.CPU.CpuData; 25 | import edu.umich.PowerTutor.components.Audio.AudioData; 26 | import edu.umich.PowerTutor.components.GPS.GpsData; 27 | import edu.umich.PowerTutor.components.Wifi.WifiData; 28 | import edu.umich.PowerTutor.components.Threeg.ThreegData; 29 | 30 | import android.content.Context; 31 | 32 | /* Most of this file should be inheritted from DreamPowerCalculator as most of 33 | * the hardware model details will be the same modulo the coefficients. 34 | */ 35 | public class PassionPowerCalculator extends DreamPowerCalculator { 36 | public PassionPowerCalculator(Context context) { 37 | super(new PassionConstants(context)); 38 | } 39 | 40 | public PassionPowerCalculator(PhoneConstants coeffs) { 41 | super(coeffs); 42 | } 43 | 44 | @Override 45 | public double getOledPower(OledData data) { 46 | if(!data.screenOn) { 47 | return 0; 48 | } 49 | if(data.pixPower == -1) { 50 | /* No pixel power available :(. */ 51 | return coeffs.oledBasePower() + coeffs.lcdBrightness() * data.brightness; 52 | } else { 53 | return coeffs.oledBasePower() + data.pixPower * data.brightness; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PhoneConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | public interface PhoneConstants { 23 | /* Return the name of the model represented by these constants 24 | */ 25 | public String modelName(); 26 | 27 | /* Gives the maximum power that this phone can drain from its battery. 28 | */ 29 | public double maxPower(); 30 | 31 | /* Gives the coefficient to multiply the LCD display's brightness by to 32 | * calculate power usage. 33 | */ 34 | public double lcdBrightness(); 35 | 36 | /* Gives the power usage for the lcd display that is incurred by the display 37 | * just being turned on. 38 | */ 39 | public double lcdBacklight(); 40 | 41 | /* Gives the base power usage for the OLED display for just being on. 42 | */ 43 | public double oledBasePower(); 44 | 45 | /* Gives the power coefficient for rgb channels (in that order) for a signle 46 | * pixel. 47 | */ 48 | public double[] oledChannelPower(); 49 | 50 | /* Gives the modulation coefficient for the per pixel power calculation. 51 | */ 52 | public double oledModulation(); 53 | 54 | /* Gives the coefficients at different cpu frequencies for the amount of 55 | * power/cpu utilization the processor is using. 56 | */ 57 | public double[] cpuPowerRatios(); 58 | 59 | /* Gives the frequency for each of the power ratios listed in 60 | * cpuPowerRatios(). 61 | */ 62 | public double[] cpuFreqs(); 63 | 64 | /* Gives the usage for the audio output being used. The model doesn't 65 | * currently take into account volume. 66 | */ 67 | public double audioPower(); 68 | 69 | /* Gives the power consumption for each of the GPS states. These states are 70 | * {OFF, SLEEP, ON} in that order. See GPS.java. 71 | */ 72 | public double[] gpsStatePower(); 73 | 74 | /* Gives the time in seconds that the GPS sleeps for after the session 75 | * has ended. 76 | */ 77 | public double gpsSleepTime(); 78 | 79 | /* Gives the power consumption of wifi in the low power state. 80 | */ 81 | public double wifiLowPower(); 82 | 83 | /* Gives the base power consumption while the wifi is in high power mode. 84 | */ 85 | public double wifiHighPower(); 86 | 87 | /* Gives the packet rate needed to transition from the low power state 88 | * to the high power state. 89 | */ 90 | public double wifiLowHighTransition(); 91 | 92 | /* Gives the packet rate needed to transition from the high power state 93 | * to the low power state. 94 | */ 95 | public double wifiHighLowTransition(); 96 | 97 | /* Gives the power/uplinkrate for different link speeds for wifi in high 98 | * power mode. 99 | */ 100 | public double[] wifiLinkRatios(); 101 | 102 | /* Gives the link speed associated with each link power ratio. Elements 103 | * should be in increasing order. Should have the same number of elements 104 | * as wifiLinkRatios(). 105 | */ 106 | public double[] wifiLinkSpeeds(); 107 | 108 | /* Gives the name of the 3G interface for this phone. 109 | */ 110 | public String threegInterface(); 111 | 112 | /* Gives the power consumed while the 3G interface is in the idle state. 113 | */ 114 | public double threegIdlePower(String oper); 115 | 116 | /* Gives the power consumed while the 3G interface is in the FACH state. 117 | */ 118 | public double threegFachPower(String oper); 119 | 120 | /* Gives the power consumed while the 3G interface is in the DCH state. 121 | */ 122 | public double threegDchPower(String oper); 123 | 124 | /* Gives the number of bytes in the uplink queue. 125 | */ 126 | public int threegUplinkQueue(String oper); 127 | 128 | /* Gives the number of bytes in the downlink queue. 129 | */ 130 | public int threegDownlinkQueue(String oper); 131 | 132 | /* Gives the time in seconds that the 3G interface stays idle in the DCH state 133 | * before transitioning to the FACH state. 134 | */ 135 | public int threegDchFachDelay(String oper); 136 | 137 | /* Gives the time in seconds that the 3G interface stays idle in the FACH 138 | * state before transitioning to the IDLE state. 139 | */ 140 | public int threegFachIdleDelay(String oper); 141 | 142 | /* Gives the power consumed by each of the sensors. Should have the same size 143 | * as Sensors.MAX_SENSORS. 144 | */ 145 | public double[] sensorPower(); 146 | 147 | /* Gives the maximum power in mW that the named component can generate. 148 | */ 149 | public double getMaxPower(String componentName); 150 | } 151 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PhonePowerCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import edu.umich.PowerTutor.components.LCD.LcdData; 23 | import edu.umich.PowerTutor.components.OLED.OledData; 24 | import edu.umich.PowerTutor.components.CPU.CpuData; 25 | import edu.umich.PowerTutor.components.Audio.AudioData; 26 | import edu.umich.PowerTutor.components.GPS.GpsData; 27 | import edu.umich.PowerTutor.components.Wifi.WifiData; 28 | import edu.umich.PowerTutor.components.Threeg.ThreegData; 29 | import edu.umich.PowerTutor.components.Sensors.SensorData; 30 | 31 | public interface PhonePowerCalculator { 32 | public double getLcdPower(LcdData data); 33 | 34 | public double getOledPower(OledData data); 35 | 36 | public double getCpuPower(CpuData data); 37 | 38 | public double getAudioPower(AudioData data); 39 | 40 | public double getGpsPower(GpsData data); 41 | 42 | public double getWifiPower(WifiData data); 43 | 44 | public double getThreeGPower(ThreegData data); 45 | 46 | public double getSensorPower(SensorData data); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PhoneSelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import java.util.List; 23 | 24 | import android.content.Context; 25 | import android.os.Build; 26 | import android.util.Log; 27 | import edu.umich.PowerTutor.components.Audio; 28 | import edu.umich.PowerTutor.components.CPU; 29 | import edu.umich.PowerTutor.components.GPS; 30 | import edu.umich.PowerTutor.components.LCD; 31 | import edu.umich.PowerTutor.components.OLED; 32 | import edu.umich.PowerTutor.components.PowerComponent; 33 | import edu.umich.PowerTutor.components.Sensors; 34 | import edu.umich.PowerTutor.components.Threeg; 35 | import edu.umich.PowerTutor.components.Wifi; 36 | import edu.umich.PowerTutor.components.Audio.AudioData; 37 | import edu.umich.PowerTutor.components.CPU.CpuData; 38 | import edu.umich.PowerTutor.components.GPS.GpsData; 39 | import edu.umich.PowerTutor.components.LCD.LcdData; 40 | import edu.umich.PowerTutor.components.OLED.OledData; 41 | import edu.umich.PowerTutor.components.Sensors.SensorData; 42 | import edu.umich.PowerTutor.components.Threeg.ThreegData; 43 | import edu.umich.PowerTutor.components.Wifi.WifiData; 44 | import edu.umich.PowerTutor.service.PowerData; 45 | import edu.umich.PowerTutor.util.NotificationService; 46 | import edu.umich.PowerTutor.util.SystemInfo; 47 | 48 | public class PhoneSelector { 49 | private static final String TAG = "PhoneSelector"; 50 | 51 | public static final int PHONE_UNKNOWN = 0; 52 | public static final int PHONE_DREAM = 1; /* G1 */ 53 | public static final int PHONE_SAPPHIRE = 2; /* G2 */ 54 | public static final int PHONE_PASSION = 3; /* Nexus One */ 55 | 56 | /* A hard-coded list of phones that have OLED screens. */ 57 | public static final String[] OLED_PHONES = { 58 | "bravo", 59 | "passion", 60 | "GT-I9000", 61 | "inc", 62 | "legend", 63 | "GT-I7500", 64 | "SPH-M900", 65 | "SGH-I897", 66 | "SGH-T959", 67 | "desirec", 68 | }; 69 | 70 | 71 | /* This class is not supposed to be instantiated. Just use the static 72 | * members. 73 | */ 74 | private PhoneSelector() {} 75 | 76 | public static boolean phoneSupported() { 77 | return getPhoneType() != PHONE_UNKNOWN; 78 | } 79 | 80 | public static boolean hasOled() { 81 | for(int i = 0; i < OLED_PHONES.length; i++) { 82 | if(Build.DEVICE.equals(OLED_PHONES[i])) { 83 | return true; 84 | } 85 | } 86 | return false; 87 | } 88 | 89 | public static int getPhoneType() { 90 | if(Build.DEVICE.startsWith("dream")) return PHONE_DREAM; 91 | if(Build.DEVICE.startsWith("sapphire")) return PHONE_SAPPHIRE; 92 | if(Build.DEVICE.startsWith("passion")) return PHONE_PASSION; 93 | return PHONE_UNKNOWN; 94 | } 95 | 96 | public static PhoneConstants getConstants(Context context) { 97 | switch(getPhoneType()) { 98 | case PHONE_DREAM: 99 | return new DreamConstants(context); 100 | case PHONE_SAPPHIRE: 101 | return new SapphireConstants(context); 102 | case PHONE_PASSION: 103 | return new PassionConstants(context); 104 | default: 105 | boolean oled = hasOled(); 106 | Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + "), using " + 107 | (oled ? "Passion" : "Dream") + " constants"); 108 | return oled ? new PassionConstants(context) : 109 | new DreamConstants(context); 110 | } 111 | } 112 | 113 | public static PhonePowerCalculator getCalculator(Context context) { 114 | switch(getPhoneType()) { 115 | case PHONE_DREAM: 116 | return new DreamPowerCalculator(context); 117 | case PHONE_SAPPHIRE: 118 | return new SapphirePowerCalculator(context); 119 | case PHONE_PASSION: 120 | return new PassionPowerCalculator(context); 121 | default: 122 | boolean oled = hasOled(); 123 | Log.w(TAG, "Phone type not recognized (" + Build.DEVICE + "), using " + 124 | (oled ? "Passion" : "Dream") + " calculator"); 125 | return oled ? new PassionPowerCalculator(context) : 126 | new DreamPowerCalculator(context); 127 | } 128 | } 129 | 130 | public static void generateComponents(Context context, 131 | List components, 132 | List functions) { 133 | final PhoneConstants constants = getConstants(context); 134 | final PhonePowerCalculator calculator = getCalculator(context); 135 | 136 | //TODO: What about bluetooth? 137 | //TODO: LED light on the Nexus 138 | 139 | /* Add display component. */ 140 | if(hasOled()) { 141 | components.add(new OLED(context, constants)); 142 | functions.add(new PowerFunction() { 143 | public double calculate(PowerData data) { 144 | return calculator.getOledPower((OledData)data); 145 | }}); 146 | } else { 147 | components.add(new LCD(context)); 148 | functions.add(new PowerFunction() { 149 | public double calculate(PowerData data) { 150 | return calculator.getLcdPower((LcdData)data); 151 | }}); 152 | } 153 | 154 | /* Add CPU component. */ 155 | components.add(new CPU(constants)); 156 | functions.add(new PowerFunction() { 157 | public double calculate(PowerData data) { 158 | return calculator.getCpuPower((CpuData)data); 159 | }}); 160 | 161 | /* Add Wifi component. */ 162 | String wifiInterface = 163 | SystemInfo.getInstance().getProperty("wifi.interface"); 164 | if(wifiInterface != null && wifiInterface.length() != 0) { 165 | components.add(new Wifi(context, constants)); 166 | functions.add(new PowerFunction() { 167 | public double calculate(PowerData data) { 168 | return calculator.getWifiPower((WifiData)data); 169 | }}); 170 | } 171 | 172 | /* Add 3G component. */ 173 | if(constants.threegInterface().length() != 0) { 174 | components.add(new Threeg(context, constants)); 175 | functions.add(new PowerFunction() { 176 | public double calculate(PowerData data) { 177 | return calculator.getThreeGPower((ThreegData)data); 178 | }}); 179 | } 180 | 181 | /* Add GPS component. */ 182 | components.add(new GPS(context, constants)); 183 | functions.add(new PowerFunction() { 184 | public double calculate(PowerData data) { 185 | return calculator.getGpsPower((GpsData)data); 186 | }}); 187 | 188 | /* Add Audio component. */ 189 | components.add(new Audio(context)); 190 | functions.add(new PowerFunction() { 191 | public double calculate(PowerData data) { 192 | return calculator.getAudioPower((AudioData)data); 193 | }}); 194 | 195 | /* Add Sensors component if avaialble. */ 196 | if(NotificationService.available()) { 197 | components.add(new Sensors(context)); 198 | functions.add(new PowerFunction() { 199 | public double calculate(PowerData data) { 200 | return calculator.getSensorPower((SensorData)data); 201 | }}); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/PowerFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import edu.umich.PowerTutor.service.PowerData; 23 | 24 | public interface PowerFunction { 25 | public double calculate(PowerData data); 26 | } 27 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/SapphireConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import android.content.Context; 23 | 24 | public class SapphireConstants extends DreamConstants { 25 | public SapphireConstants(Context context) { 26 | super(context); 27 | } 28 | 29 | public String modelName() { 30 | return "sapphire"; 31 | } 32 | 33 | public double maxPower() { 34 | return 2800; 35 | } 36 | 37 | public double lcdBrightness() { 38 | return 1.72686; 39 | } 40 | 41 | public double lcdBacklight() { 42 | return 340.8305; 43 | } 44 | 45 | private static final double[] arrayCpuPowerRatios = {1.4169, 2.3997}; 46 | public double[] cpuPowerRatios() { 47 | return arrayCpuPowerRatios; 48 | } 49 | 50 | private static final double[] arrayCpuFreqs = {245.36, 383.38}; 51 | public double[] cpuFreqs() { 52 | return arrayCpuFreqs; 53 | } 54 | 55 | public double audioPower() { 56 | return 184.62; 57 | } 58 | 59 | private static final double[] arrayGpsStatePower = {0.0, 33.577, 284.7624}; 60 | public double[] gpsStatePower() { 61 | return arrayGpsStatePower; 62 | } 63 | 64 | public double gpsSleepTime() { 65 | return 6.0; 66 | } 67 | 68 | public double wifiLowPower() { 69 | return 38.554; 70 | } 71 | 72 | public double wifiHighPower() { 73 | return 733.7631; 74 | } 75 | 76 | public double wifiLowHighTransition() { 77 | return 15; 78 | } 79 | 80 | public double wifiHighLowTransition() { 81 | return 8; 82 | } 83 | 84 | private static final double[] arrayWifiLinkRatios = { 85 | 47.122645, 46.354821, 43.667437, 43.283525, 40.980053, 39.44422, 38.676581, 86 | 34.069637, 29.462693, 20.248805, 11.034917, 6.427122 87 | }; 88 | public double[] wifiLinkRatios() { 89 | return arrayWifiLinkRatios; 90 | } 91 | 92 | private static final double[] arrayWifiLinkSpeeds = { 93 | 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54 94 | }; 95 | public double[] wifiLinkSpeeds() { 96 | return arrayWifiLinkSpeeds; 97 | } 98 | 99 | public String threegInterface() { 100 | return "rmnet0"; 101 | } 102 | 103 | public double threegIdlePower(String oper) { 104 | if(OPER_TMOBILE.equals(oper)) { 105 | return 10; 106 | } 107 | return 10; 108 | } 109 | 110 | public double threegFachPower(String oper) { 111 | if(OPER_TMOBILE.equals(oper)) { 112 | return 413.9689; 113 | } 114 | return 413.9689; 115 | } 116 | 117 | public double threegDchPower(String oper) { 118 | if(OPER_TMOBILE.equals(oper)) { 119 | return 944.3891; 120 | } 121 | return 944.3891; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/phone/SapphirePowerCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.phone; 21 | 22 | import edu.umich.PowerTutor.components.LCD.LcdData; 23 | import edu.umich.PowerTutor.components.CPU.CpuData; 24 | import edu.umich.PowerTutor.components.Audio.AudioData; 25 | import edu.umich.PowerTutor.components.GPS.GpsData; 26 | import edu.umich.PowerTutor.components.Wifi.WifiData; 27 | import edu.umich.PowerTutor.components.Threeg.ThreegData; 28 | 29 | import android.content.Context; 30 | 31 | /* Most of this file should be inheritted from DreamPowerCalculator as most of 32 | * the hardware model details will be the same modulo the coefficients. 33 | */ 34 | public class SapphirePowerCalculator extends DreamPowerCalculator { 35 | public SapphirePowerCalculator(Context context) { 36 | super(new SapphireConstants(context)); 37 | } 38 | 39 | public SapphirePowerCalculator(PhoneConstants coeffs) { 40 | super(coeffs); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/service/IterationData.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | import edu.umich.PowerTutor.util.Recycler; 23 | import edu.umich.PowerTutor.util.SystemInfo; 24 | 25 | import android.util.SparseArray; 26 | 27 | /* Class that encloses physical hardware power data as well as estimated power 28 | * data for each uid that contributes a non-negligable amount of power for this 29 | * component. 30 | */ 31 | public class IterationData { 32 | private static Recycler recycler = 33 | new Recycler(); 34 | 35 | private SparseArray uidPower; 36 | 37 | public static IterationData obtain() { 38 | IterationData result = recycler.obtain(); 39 | if(result != null) return result; 40 | return new IterationData(); 41 | } 42 | 43 | private IterationData() { 44 | uidPower = new SparseArray(); 45 | } 46 | 47 | /* Initialize the members of this structure. Remember that this class may not 48 | * have just been instantiated and may have been used in past iterations. 49 | */ 50 | public void init() { 51 | uidPower.clear(); 52 | } 53 | 54 | /* Allow this class to be recycled and to recycle all of the PowerData 55 | * PowerData elements contained within it. 56 | */ 57 | public void recycle() { 58 | for(int i = 0; i < uidPower.size(); i++) { 59 | uidPower.valueAt(i).recycle(); 60 | } 61 | uidPower.clear(); 62 | recycler.recycle(this); 63 | } 64 | 65 | public void setPowerData(PowerData power) { 66 | addUidPowerData(SystemInfo.AID_ALL, power); 67 | } 68 | 69 | public void addUidPowerData(int uid, PowerData power) { 70 | uidPower.put(uid, power); 71 | } 72 | 73 | public SparseArray getUidPowerData() { 74 | return uidPower; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/service/LogUploader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | import android.content.Context; 23 | 24 | /* This class is responsible for implementing all policy decisions on when to 25 | * send log information back to an external server. Upon a successful call to 26 | * shouldUpload() PowerEstimator will then call upload(file). After the call to 27 | * upload the file with the passed path may be overwritten. 28 | * 29 | * This is a stub implementation not supporting log uploading. 30 | */ 31 | public class LogUploader { 32 | public LogUploader(Context context) { 33 | } 34 | 35 | /* Returns true if this module supports uploading logs. */ 36 | public static boolean uploadSupported() { 37 | return false; 38 | } 39 | 40 | /* Returns true if the log should be uploaded now. This may depend on log 41 | * file size, network conditions, etc. */ 42 | // TODO: This should probably give the file name of the log 43 | public boolean shouldUpload() { 44 | return false; 45 | } 46 | 47 | /* Called when the device is plugged in or unplugged. The intended use of 48 | * this is to improve upload policy decisions. */ 49 | public void plug(boolean plugged) { 50 | } 51 | 52 | /* Initiate the upload of the file with the passed location. */ 53 | public void upload(String origFile) { 54 | } 55 | 56 | /* Returns true if a file is currently being uploaded. */ 57 | public boolean isUploading() { 58 | return false; 59 | } 60 | 61 | /* Interrupt any threads doing upload work. */ 62 | public void interrupt() { 63 | } 64 | 65 | /* Join any threads that may be performing log upload work. */ 66 | public void join() throws InterruptedException { 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/service/PowerData.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | import java.io.OutputStreamWriter; 23 | import java.io.IOException; 24 | import java.util.Vector; 25 | 26 | public abstract class PowerData { 27 | private int cachedPower; 28 | 29 | public PowerData() { 30 | } 31 | 32 | public void setCachedPower(int power) { 33 | cachedPower = power; 34 | } 35 | 36 | public int getCachedPower() { 37 | return cachedPower; 38 | } 39 | 40 | /* To be called when the PowerData object is no longer in use so that it can 41 | * be used again in the next iteration if it chooses to be. 42 | */ 43 | public void recycle() {} 44 | 45 | /* Simply writes out log information to the passed stream. */ 46 | public abstract void writeLogDataInfo(OutputStreamWriter out) 47 | throws IOException; 48 | } 49 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/service/UMLoggerService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | import edu.umich.PowerTutor.util.SystemInfo; 23 | 24 | import android.app.Notification; 25 | import android.app.NotificationManager; 26 | import android.app.Service; 27 | import android.content.BroadcastReceiver; 28 | import android.content.Context; 29 | import android.content.Intent; 30 | import android.content.IntentFilter; 31 | import android.os.Bundle; 32 | import android.os.IBinder; 33 | import android.telephony.PhoneStateListener; 34 | import android.telephony.ServiceState; 35 | import android.telephony.TelephonyManager; 36 | import android.util.Log; 37 | 38 | import java.io.ByteArrayOutputStream; 39 | import java.io.ObjectOutputStream; 40 | import java.io.IOException; 41 | 42 | 43 | public class UMLoggerService extends Service{ 44 | private static final String TAG = "UMLoggerService"; 45 | 46 | private static final int NOTIFICATION_ID = 1; 47 | private static final int NOTIFICATION_ID_LETTER = 2; 48 | 49 | private Thread estimatorThread; 50 | private PowerEstimator powerEstimator; 51 | 52 | private Notification notification; 53 | 54 | private NotificationManager notificationManager; 55 | private TelephonyManager phoneManager; 56 | 57 | @Override 58 | public IBinder onBind(Intent intent) { 59 | return binder; 60 | } 61 | 62 | @Override 63 | public void onCreate() { 64 | System.out.println("UMLLogger service created"); 65 | powerEstimator = new PowerEstimator(this); 66 | /* Register to receive phone state messages. */ 67 | phoneManager = (TelephonyManager)this.getSystemService(TELEPHONY_SERVICE); 68 | phoneManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE | 69 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | 70 | PhoneStateListener.LISTEN_SERVICE_STATE | 71 | PhoneStateListener.LISTEN_SIGNAL_STRENGTH); 72 | 73 | /* Register to receive airplane mode and battery low messages. */ 74 | IntentFilter filter = new IntentFilter(); 75 | filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 76 | filter.addAction(Intent.ACTION_BATTERY_LOW); 77 | filter.addAction(Intent.ACTION_BATTERY_CHANGED); 78 | filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 79 | filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 80 | registerReceiver(broadcastIntentReceiver, filter); 81 | 82 | notificationManager = (NotificationManager)getSystemService( 83 | NOTIFICATION_SERVICE); 84 | } 85 | 86 | @Override 87 | public int onStartCommand(Intent intent, int flag, int startId) { 88 | System.out.println("UMLLogger service started"); 89 | super.onStartCommand(intent, flag, startId); 90 | //android.os.Debug.startMethodTracing("pt.trace"); 91 | 92 | if(intent.getBooleanExtra("stop", false)) { 93 | stopSelf(); 94 | return 0; 95 | } else if(estimatorThread != null) { 96 | return 0; 97 | } 98 | 99 | estimatorThread = new Thread(powerEstimator); 100 | estimatorThread.start(); 101 | 102 | return 0; 103 | } 104 | 105 | @Override 106 | public void onDestroy() { 107 | //android.os.Debug.stopMethodTracing(); 108 | if(estimatorThread != null) { 109 | estimatorThread.interrupt(); 110 | while(estimatorThread.isAlive()) { 111 | try { 112 | estimatorThread.join(); 113 | } catch(InterruptedException e) { 114 | } 115 | } 116 | } 117 | unregisterReceiver(broadcastIntentReceiver); 118 | 119 | 120 | super.onDestroy(); 121 | }; 122 | 123 | private final ICounterService.Stub binder = 124 | new ICounterService.Stub() { 125 | public String[] getComponents() { 126 | return powerEstimator.getComponents(); 127 | } 128 | 129 | public int[] getComponentsMaxPower() { 130 | return powerEstimator.getComponentsMaxPower(); 131 | } 132 | 133 | public int getNoUidMask() { 134 | return powerEstimator.getNoUidMask(); 135 | } 136 | 137 | public int[] getComponentHistory(int count, int componentId, int uid) { 138 | return powerEstimator.getComponentHistory(count, componentId, uid, -1); 139 | } 140 | 141 | public long[] getTotals(int uid, int windowType) { 142 | return powerEstimator.getTotals(uid, windowType); 143 | } 144 | 145 | public long getRuntime(int uid, int windowType) { 146 | return powerEstimator.getRuntime(uid, windowType); 147 | } 148 | 149 | public long[] getMeans(int uid, int windowType) { 150 | return powerEstimator.getMeans(uid, windowType); 151 | } 152 | 153 | public byte[] getUidInfo(int windowType, int ignoreMask) { 154 | UidInfo[] infos = powerEstimator.getUidInfo(windowType, ignoreMask); 155 | ByteArrayOutputStream output = new ByteArrayOutputStream(); 156 | try { 157 | new ObjectOutputStream(output).writeObject(infos); 158 | } catch(IOException e) { 159 | return null; 160 | } 161 | for(UidInfo info : infos) { 162 | info.recycle(); 163 | } 164 | return output.toByteArray(); 165 | } 166 | 167 | public long getUidExtra(String name, int uid) { 168 | return powerEstimator.getUidExtra(name, uid); 169 | } 170 | }; 171 | 172 | 173 | BroadcastReceiver broadcastIntentReceiver = new BroadcastReceiver() { 174 | public void onReceive(Context context, Intent intent) { 175 | if(intent.getAction().equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 176 | Bundle extra = intent.getExtras(); 177 | try { 178 | if ((Boolean)extra.get("state")) { 179 | powerEstimator.writeToLog("airplane-mode on\n"); 180 | } else { 181 | powerEstimator.writeToLog("airplane-mode off\n"); 182 | } 183 | } catch(ClassCastException e) { 184 | // Some people apparently are having this problem. I'm not really 185 | // sure why this should happen. 186 | Log.w(TAG, "Couldn't determine airplane mode state"); 187 | } 188 | } else if(intent.getAction().equals(Intent.ACTION_BATTERY_LOW)) { 189 | powerEstimator.writeToLog("battery low\n"); 190 | } else if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { 191 | powerEstimator.writeToLog("battery-change " + 192 | intent.getIntExtra("plugged", -1) + " " + 193 | intent.getIntExtra("level", -1) + "/" + 194 | intent.getIntExtra("scale", -1) + " " + 195 | intent.getIntExtra("voltage", -1) + 196 | intent.getIntExtra("temperature", -1) + "\n"); 197 | powerEstimator.plug( 198 | intent.getIntExtra("plugged", -1) != 0); 199 | } else if(intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED) || 200 | intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) { 201 | // A package has either been removed or its metadata has changed and we 202 | // need to clear the cache of metadata for that app. 203 | SystemInfo.getInstance().voidUidCache( 204 | intent.getIntExtra(Intent.EXTRA_UID, -1)); 205 | } 206 | }; 207 | }; 208 | 209 | PhoneStateListener phoneListener = new PhoneStateListener() { 210 | public void onServiceStateChanged(ServiceState serviceState) { 211 | switch(serviceState.getState()) { 212 | case ServiceState.STATE_EMERGENCY_ONLY: 213 | powerEstimator.writeToLog("phone-service emergency-only\n"); 214 | break; 215 | case ServiceState.STATE_IN_SERVICE: 216 | powerEstimator.writeToLog("phone-service in-service\n"); 217 | switch(phoneManager.getNetworkType()) { 218 | case(TelephonyManager.NETWORK_TYPE_EDGE): 219 | powerEstimator.writeToLog("phone-network edge\n"); 220 | break; 221 | case(TelephonyManager.NETWORK_TYPE_GPRS): 222 | powerEstimator.writeToLog("phone-network GPRS\n"); 223 | break; 224 | case 8: 225 | powerEstimator.writeToLog("phone-network HSDPA\n"); 226 | break; 227 | case(TelephonyManager.NETWORK_TYPE_UMTS): 228 | powerEstimator.writeToLog("phone-network UMTS\n"); 229 | break; 230 | default: 231 | powerEstimator.writeToLog("phone-network " + 232 | phoneManager.getNetworkType() + "\n"); 233 | } 234 | break; 235 | case ServiceState.STATE_OUT_OF_SERVICE: 236 | powerEstimator.writeToLog("phone-service out-of-service\n"); 237 | break; 238 | case ServiceState.STATE_POWER_OFF: 239 | powerEstimator.writeToLog("phone-service power-off\n"); 240 | break; 241 | } 242 | } 243 | 244 | public void onCallStateChanged(int state, String incomingNumber) { 245 | switch(state) { 246 | case TelephonyManager.CALL_STATE_IDLE: 247 | powerEstimator.writeToLog("phone-call idle\n"); 248 | break; 249 | case TelephonyManager.CALL_STATE_OFFHOOK: 250 | powerEstimator.writeToLog("phone-call off-hook\n"); 251 | break; 252 | case TelephonyManager.CALL_STATE_RINGING: 253 | powerEstimator.writeToLog("phone-call ringing\n"); 254 | break; 255 | } 256 | } 257 | 258 | public void onDataConnectionStateChanged(int state) { 259 | switch(state) { 260 | case TelephonyManager.DATA_DISCONNECTED: 261 | powerEstimator.writeToLog("data disconnected\n"); 262 | break; 263 | case TelephonyManager.DATA_CONNECTING: 264 | powerEstimator.writeToLog("data connecting\n"); 265 | break; 266 | case TelephonyManager.DATA_CONNECTED: 267 | powerEstimator.writeToLog("data connected\n"); 268 | break; 269 | case TelephonyManager.DATA_SUSPENDED: 270 | powerEstimator.writeToLog("data suspended\n"); 271 | break; 272 | } 273 | } 274 | 275 | public void onSignalStrengthChanged(int asu) { 276 | powerEstimator.writeToLog("signal " + asu + "\n"); 277 | } 278 | }; 279 | } 280 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/service/UidInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.service; 21 | 22 | import edu.umich.PowerTutor.util.Recycler; 23 | 24 | import java.io.Serializable; 25 | 26 | public class UidInfo implements Serializable, Comparable { 27 | private static Recycler recycler = new Recycler(); 28 | 29 | public static UidInfo obtain() { 30 | UidInfo result = recycler.obtain(); 31 | if(result != null) return result; 32 | return new UidInfo(); 33 | } 34 | 35 | public void recycle() { 36 | recycler.recycle(this); 37 | } 38 | 39 | public int uid; 40 | public int currentPower; 41 | public long totalEnergy; 42 | public long runtime; 43 | 44 | public transient double key; 45 | public transient double percentage; 46 | public transient String unit; 47 | 48 | private UidInfo() { 49 | } 50 | 51 | public void init(int uid, int currentPower, long totalEnergy, 52 | long runtime) { 53 | this.uid = uid; 54 | this.currentPower = currentPower; 55 | this.totalEnergy = totalEnergy; 56 | this.runtime = runtime; 57 | } 58 | 59 | public int compareTo(Object o) { 60 | UidInfo x = (UidInfo)o; 61 | if(key > x.key) return -1; 62 | if(key == x.key) return 0; 63 | return 1; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/BatteryStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import java.io.File; 23 | 24 | public class BatteryStats { 25 | private static final String TAG = "BatteryStats"; 26 | private static BatteryStats instance = null; 27 | 28 | public static BatteryStats getInstance() { 29 | if(instance == null) { 30 | instance = new BatteryStats(); 31 | } 32 | return instance; 33 | } 34 | 35 | private static final String[] VOLTAGE_FILES = { 36 | "/sys/class/power_supply/battery/voltage_now", 37 | "/sys/class/power_supply/battery/batt_vol", 38 | }; 39 | private static final double[] VOLTAGE_CONV = { 40 | 1e-6, // Source in microvolts. 41 | 1e-3, // Source in millivolts. 42 | }; 43 | 44 | private static final String[] CURRENT_FILES = { 45 | "/sys/class/power_supply/battery/current_now", 46 | //"/sys/class/power_supply/battery/batt_current", Doesn't seem good 47 | }; 48 | private static final double[] CURRENT_CONV = { 49 | 1e-6, // Source in microamps. 50 | //1e-3, // Source in milliamps. 51 | }; 52 | 53 | private static final String[] TEMP_FILES = { 54 | "/sys/class/power_supply/battery/temp", 55 | "/sys/class/power_supply/battery/batt_temp", 56 | }; 57 | private static final double[] TEMP_CONV = { 58 | 1e-1, // Source in tenths of a centigrade. 59 | 1e-1, // Source in tenths of a centigrade. 60 | }; 61 | 62 | private static final String[] CHARGE_FILES = { 63 | "/sys/class/power_supply/battery/charge_counter", 64 | }; 65 | private static final double[] CHARGE_CONV = { 66 | 60*60*1e-6, // Source in micro amp hours. 67 | }; 68 | 69 | private static final String[] CAPACITY_FILES = { 70 | "/sys/class/power_supply/battery/capacity", 71 | }; 72 | private static final double[] CAPACITY_CONV = { 73 | 1e-2, // Source in percentage. 74 | }; 75 | 76 | private static final String[] FULL_CAPACITY_FILES = { 77 | "/sys/class/power_supply/battery/full_bat", 78 | }; 79 | private static final double[] FULL_CAPACITY_CONV = { 80 | 60*60*1e-6, // Source in micro amp hours. 81 | }; 82 | 83 | SystemInfo sysInfo; 84 | 85 | String voltageFile; 86 | String currentFile; 87 | String tempFile; 88 | String chargeFile; 89 | String capacityFile; 90 | String fullCapacityFile; 91 | 92 | double voltageConv; 93 | double currentConv; 94 | double tempConv; 95 | double chargeConv; 96 | double capacityConv; 97 | double fullCapacityConv; 98 | 99 | private BatteryStats() { 100 | sysInfo = SystemInfo.getInstance(); 101 | 102 | // Get voltage information. 103 | for(int i = 0; i < VOLTAGE_FILES.length; i++) { 104 | if(new File(VOLTAGE_FILES[i]).exists()) { 105 | voltageFile = VOLTAGE_FILES[i]; 106 | voltageConv = VOLTAGE_CONV[i]; 107 | } 108 | } 109 | 110 | // Get current information. 111 | for(int i = 0; i < CURRENT_FILES.length; i++) { 112 | if(new File(CURRENT_FILES[i]).exists()) { 113 | currentFile = CURRENT_FILES[i]; 114 | currentConv = CURRENT_CONV[i]; 115 | } 116 | } 117 | 118 | // Get temperature information. 119 | for(int i = 0; i < TEMP_FILES.length; i++) { 120 | if(new File(TEMP_FILES[i]).exists()) { 121 | tempFile = TEMP_FILES[i]; 122 | tempConv = TEMP_CONV[i]; 123 | } 124 | } 125 | 126 | // Get charge information. 127 | for(int i = 0; i < CHARGE_FILES.length; i++) { 128 | if(new File(CHARGE_FILES[i]).exists()) { 129 | chargeFile = CHARGE_FILES[i]; 130 | chargeConv = CHARGE_CONV[i]; 131 | } 132 | } 133 | 134 | // Get capacity information. 135 | for(int i = 0; i < CAPACITY_FILES.length; i++) { 136 | if(new File(CAPACITY_FILES[i]).exists()) { 137 | capacityFile = CAPACITY_FILES[i]; 138 | capacityConv = CAPACITY_CONV[i]; 139 | } 140 | } 141 | 142 | // Get full capacity information. 143 | for(int i = 0; i < FULL_CAPACITY_FILES.length; i++) { 144 | if(new File(FULL_CAPACITY_FILES[i]).exists()) { 145 | fullCapacityFile = FULL_CAPACITY_FILES[i]; 146 | fullCapacityConv = FULL_CAPACITY_CONV[i]; 147 | } 148 | } 149 | } 150 | 151 | public boolean hasVoltage() { 152 | return voltageFile != null; 153 | } 154 | 155 | public double getVoltage() { 156 | if(voltageFile == null) return -1.0; 157 | long volt = sysInfo.readLongFromFile(voltageFile); 158 | return volt == -1 ? -1.0 : voltageConv * volt; 159 | } 160 | 161 | public boolean hasCurrent() { 162 | return currentFile != null; 163 | } 164 | 165 | public double getCurrent() { 166 | long curr = sysInfo.readLongFromFile(currentFile); 167 | return curr == -1 ? -1.0 : currentConv * curr; 168 | } 169 | 170 | public boolean hasTemp() { 171 | return tempFile != null; 172 | } 173 | 174 | public double getTemp() { 175 | if(tempFile == null) return -1.0; 176 | long temp = sysInfo.readLongFromFile(tempFile); 177 | return temp == -1 ? -1.0 : tempConv * temp; 178 | } 179 | 180 | public boolean hasCharge() { 181 | return chargeFile != null || 182 | hasFullCapacity() && hasCapacity(); 183 | } 184 | 185 | public double getCharge() { 186 | if(chargeFile == null) { 187 | double r1 = getCapacity(); 188 | double r2 = getFullCapacity(); 189 | return r1 < 0 || r2 < 0 ? -1.0 : r1 * r2; 190 | } 191 | long charge = sysInfo.readLongFromFile(chargeFile); 192 | return charge == -1 ? -1.0 : chargeConv * charge; 193 | } 194 | 195 | public boolean hasCapacity() { 196 | return capacityFile != null; 197 | } 198 | 199 | public double getCapacity() { 200 | if(capacityFile == null) return -1.0; 201 | long cap = sysInfo.readLongFromFile(capacityFile); 202 | return cap == -1 ? -1.0 : capacityConv * cap; 203 | } 204 | 205 | public boolean hasFullCapacity() { 206 | return fullCapacityFile != null; 207 | } 208 | 209 | public double getFullCapacity() { 210 | if(fullCapacityFile == null) return -1.0; 211 | long cap = sysInfo.readLongFromFile(fullCapacityFile); 212 | return cap == -1 ? -1.0 : fullCapacityConv * cap; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/Counter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import android.os.SystemClock; 23 | 24 | public class Counter { 25 | public static final int WINDOW_MINUTE = 0; 26 | public static final int WINDOW_HOUR = 1; 27 | public static final int WINDOW_DAY = 2; 28 | public static final int WINDOW_TOTAL = 3; 29 | public static final CharSequence[] WINDOW_NAMES = { "Last minute", 30 | "Last Hour", "Last Day", "Total"}; 31 | // To be used for constructions like "Showing X over ..." 32 | public static final CharSequence[] WINDOW_DESCS = { "the last minute", 33 | "the last hour", "the last day", "all time"}; 34 | private static final long WINDOW_DURATIONS[] = { 60 * 1000, 60 * 60 * 1000, 35 | 24 * 60 * 60 * 1000}; 36 | 37 | private long startTime; 38 | private long total; 39 | private SingleCounter[] counters; 40 | 41 | public Counter() { 42 | total = 0; 43 | startTime = SystemClock.elapsedRealtime(); 44 | counters = new SingleCounter[WINDOW_DURATIONS.length]; 45 | for(int i = 0; i < counters.length; i++) { 46 | counters[i] = new SingleCounter(); 47 | } 48 | } 49 | 50 | public void add(long x) { 51 | total += x; 52 | long now = SystemClock.elapsedRealtime() - startTime; 53 | for(int i = 0; i < counters.length; i++) { 54 | counters[i].add(x, now * SingleCounter.BUCKETS / WINDOW_DURATIONS[i]); 55 | } 56 | } 57 | 58 | public long get(int window) { 59 | if(window == WINDOW_TOTAL) { 60 | return total; 61 | } 62 | long now = SystemClock.elapsedRealtime() - startTime; 63 | return counters[window].get( 64 | now * SingleCounter.BUCKETS / WINDOW_DURATIONS[window], 65 | (1.0 * now * SingleCounter.BUCKETS % WINDOW_DURATIONS[window]) / 66 | WINDOW_DURATIONS[window]); 67 | } 68 | 69 | private static class SingleCounter { 70 | public static final int BUCKETS = 60; 71 | 72 | private long base; 73 | private int baseIdx; 74 | private long droppingBucket; 75 | private long[] bucketSum; 76 | private long total; 77 | 78 | public SingleCounter() { 79 | bucketSum = new long[BUCKETS]; 80 | } 81 | 82 | private void wind(long now) { 83 | if(base + 2 * BUCKETS <= now) { 84 | /* Completly clear the data structure. */ 85 | droppingBucket = 0; 86 | for(int i = 0; i < BUCKETS; i++) { 87 | bucketSum[i] = 0; 88 | } 89 | total = 0; 90 | base = now; 91 | baseIdx = 0; 92 | } else while(base + BUCKETS <= now) { 93 | droppingBucket = bucketSum[baseIdx]; 94 | total -= droppingBucket; 95 | bucketSum[baseIdx] = 0; 96 | base++; 97 | baseIdx = baseIdx + 1 == BUCKETS ? 0 : baseIdx + 1; 98 | } 99 | } 100 | 101 | public void add(long x, long now) { 102 | wind(now); 103 | total += x; 104 | int idx = (int)(baseIdx + now - base); 105 | bucketSum[idx < BUCKETS ? idx : idx - BUCKETS] += x; 106 | } 107 | 108 | /* now gives the time slice that we want information for. 109 | * prog, between 0 and 1, gives the progress through the current time slice 110 | * with 0 indicating that it just started and 1 indicating that it is about 111 | * to end. 112 | */ 113 | public long get(long now, double prog) { 114 | wind(now); 115 | return total + (long)((1.0 - prog) * droppingBucket); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/ForegroundDetector.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import edu.umich.PowerTutor.util.SystemInfo; 23 | 24 | import android.app.ActivityManager; 25 | 26 | import java.util.Arrays; 27 | import java.util.BitSet; 28 | import java.util.List; 29 | 30 | /* This detector looks for transitions where one app leaves the foreground and 31 | * another enters the foreground to detect apps that are legitimately in the 32 | * foreground. If no application is known to be legitimate system is returned. 33 | */ 34 | public class ForegroundDetector { 35 | int lastSize; 36 | int[] lastUids; 37 | int nowSize; 38 | int[] nowUids; 39 | 40 | private BitSet validated; 41 | 42 | private ActivityManager activityManager; 43 | 44 | public ForegroundDetector(ActivityManager activityManager) { 45 | lastSize = nowSize = 0; 46 | lastUids = new int[10]; 47 | nowUids = new int[10]; 48 | validated = new BitSet(1 << 16); 49 | validated.set(android.os.Process.myUid()); 50 | this.activityManager = activityManager; 51 | } 52 | 53 | // Figure out what uid should be charged for screen usage. 54 | public int getForegroundUid() { 55 | SystemInfo sysInfo = SystemInfo.getInstance(); 56 | List appProcs = 57 | activityManager.getRunningAppProcesses(); 58 | 59 | // Move the last iteration to last and resize the other array if needed. 60 | int[] tmp = lastUids; 61 | lastUids = nowUids; 62 | lastSize = nowSize; 63 | if(tmp.length < appProcs.size()) { 64 | tmp = new int[appProcs.size()]; 65 | } 66 | nowUids = tmp; 67 | 68 | // Fill in the uids from appProcs. 69 | nowSize = 0; 70 | for(ActivityManager.RunningAppProcessInfo app : appProcs) { 71 | if(app.importance == 72 | ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { 73 | int uid = sysInfo.getUidForPid(app.pid); 74 | if(SystemInfo.AID_APP <= uid && uid < 1 << 16) { 75 | nowUids[nowSize++] = uid; 76 | } 77 | } 78 | } 79 | Arrays.sort(nowUids, 0, nowSize); 80 | 81 | // Find app-exit app-enter transitions. 82 | int appExit = -1; 83 | int appEnter = -1; 84 | int indNow = 0; 85 | int indLast = 0; 86 | while(indNow < nowSize && indLast < lastSize) { 87 | if(nowUids[indNow] == lastUids[indLast]) { 88 | indNow++; indLast++; 89 | } else if(nowUids[indNow] < lastUids[indLast]) { 90 | appEnter = nowUids[indNow++]; 91 | } else { 92 | appExit = lastUids[indLast++]; 93 | } 94 | } 95 | if(indNow < nowSize) appEnter = nowUids[indNow]; 96 | if(indLast < lastSize) appExit = lastUids[indLast]; 97 | 98 | // Found an interesting transition. Validate both applications. 99 | if(appEnter != -1 && appExit != -1) { 100 | validated.set(appEnter); 101 | validated.set(appExit); 102 | } 103 | 104 | // Now find a valid application now. Hopefully there is only one. If there 105 | // are none return system. If there are several return the one with the 106 | // highest uid. 107 | for(int i = nowSize - 1; i >= 0; i--) { 108 | if(validated.get(nowUids[i])) { 109 | return nowUids[i]; 110 | } 111 | } 112 | return SystemInfo.AID_SYSTEM; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/HexEncode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | public class HexEncode { 23 | public static String encode(byte[] bytes) { 24 | StringBuilder bld = new StringBuilder(); 25 | for(int i = 0; i < bytes.length; i++) { 26 | bld.append((char)('a' + (bytes[i] >> 4 & 0xF))); 27 | bld.append((char)('a' + (bytes[i] & 0xF))); 28 | } 29 | return bld.toString(); 30 | } 31 | 32 | public static byte[] decode(String dat) { 33 | int N = dat.length() / 2; 34 | byte[] ret = new byte[N]; 35 | for(int i = 0; i < N; i++) { 36 | ret[i] = (byte)(dat.charAt(2 * i) - 'a' << 4 | 37 | dat.charAt(2 * i + 1) - 'a'); 38 | } 39 | return ret; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/HistoryBuffer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import android.util.SparseArray; 23 | 24 | import java.util.LinkedList; 25 | import java.util.ListIterator; 26 | 27 | public class HistoryBuffer { 28 | private static class UidData { 29 | public LinkedList queue; 30 | public Counter sum; 31 | public Counter count; 32 | 33 | public UidData() { 34 | queue = new LinkedList(); 35 | sum = new Counter(); 36 | count = new Counter(); 37 | } 38 | } 39 | 40 | private static class HistoryDatum { 41 | public HistoryDatum() { 42 | } 43 | 44 | public void init(long iteration, int power) { 45 | this.iteration = iteration; 46 | this.power = power; 47 | } 48 | 49 | public long iteration; 50 | public int power; 51 | } 52 | 53 | private int maxSize; 54 | private SparseArray uidData; 55 | 56 | public HistoryBuffer(int maxSize) { 57 | this.maxSize = maxSize; 58 | uidData = new SparseArray(); 59 | } 60 | 61 | /* The iteration should only increase across successive adds. */ 62 | public synchronized void add(int uid, long iteration, int power) { 63 | UidData data = uidData.get(uid); 64 | if(data == null) { 65 | data = new UidData(); 66 | uidData.put(uid, data); 67 | } 68 | data.count.add(1); 69 | if(power == 0) { 70 | return; 71 | } 72 | data.sum.add(power); 73 | if(maxSize == 0) { 74 | return; 75 | } 76 | 77 | LinkedList queue = data.queue; 78 | HistoryDatum datum; 79 | if(maxSize <= queue.size()) { 80 | datum = queue.getLast(); 81 | queue.removeLast(); 82 | } else { 83 | datum = new HistoryDatum(); 84 | } 85 | datum.init(iteration, power); 86 | queue.addFirst(datum); 87 | } 88 | 89 | /* Fills in the previous number timestamps starting from a timestamp and 90 | * working backwards. Any timestamp with no information is just treated 91 | * as using no power. 92 | */ 93 | public synchronized int[] get(int uid, long timestamp, int number) { 94 | int ind = 0; 95 | if(number < 0) number = 0; 96 | if(number > maxSize) number = maxSize; 97 | int[] ret = new int[number]; 98 | UidData data = uidData.get(uid); 99 | LinkedList queue = data == null ? null : data.queue; 100 | if(queue == null || queue.isEmpty()) { 101 | return ret; 102 | } 103 | if(timestamp == -1) { 104 | timestamp = queue.getFirst().iteration; 105 | } 106 | for(ListIterator iter = queue.listIterator(); 107 | iter.hasNext(); ) { 108 | HistoryDatum datum = iter.next(); 109 | while(datum.iteration < timestamp && ind < number) { 110 | ind++; 111 | timestamp--; 112 | } 113 | if(ind == number) { 114 | break; 115 | } 116 | if(datum.iteration == timestamp) { 117 | ret[ind++] = datum.power; 118 | timestamp--; 119 | } else { 120 | /* datum happened after requested interval. */ 121 | } 122 | } 123 | return ret; 124 | } 125 | 126 | public synchronized long getTotal(int uid, int windowType) { 127 | UidData data = uidData.get(uid); 128 | return data == null ? 0 : data.sum.get(windowType); 129 | } 130 | 131 | public synchronized long getCount(int uid, int windowType) { 132 | UidData data = uidData.get(uid); 133 | return data == null ? 0 : data.count.get(windowType); 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/NativeLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import android.util.Log; 23 | 24 | public class NativeLoader { 25 | private static final String TAG = "NativeLoader"; 26 | 27 | private static boolean loadOk = false; 28 | 29 | static { 30 | try { 31 | System.loadLibrary("bindings"); 32 | loadOk = true; 33 | } catch(SecurityException e) { 34 | Log.w(TAG, "Failed to load jni dll, will fall back on pure java"); 35 | loadOk = false; 36 | } catch(UnsatisfiedLinkError e) { 37 | Log.w(TAG, "Failed to load jni dll, will fall back on pure java"); 38 | loadOk = false; 39 | } 40 | } 41 | 42 | public static boolean jniLoaded() { 43 | return loadOk; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/NotificationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import java.lang.reflect.InvocationTargetException; 23 | import java.lang.reflect.Method; 24 | import java.util.Iterator; 25 | import java.util.Vector; 26 | 27 | import android.os.Binder; 28 | import android.os.IBinder; 29 | import android.os.Parcel; 30 | import android.os.RemoteException; 31 | import android.util.Log; 32 | import edu.umich.PowerTutor.PowerNotifications; 33 | 34 | @SuppressWarnings("unchecked") 35 | public class NotificationService { 36 | private static final String TAG = "NotificationService"; 37 | 38 | /* We haven't tried to install the hook yet. */ 39 | private static final int STATE_INIT = 0; 40 | /* The hook was installed successfully and we should be receiving power 41 | * related notifications from the battery service. 42 | */ 43 | private static final int STATE_HOOK_INSTALLED = 1; 44 | /* The hook failed to install. This should be the case for most phones as a 45 | * hack is required to get this to work. 46 | */ 47 | private static final int STATE_HOOK_FAILED = 2; 48 | 49 | private static int hookState = STATE_INIT; 50 | private static Binder notifier = new NotificationForwarder(); 51 | private static Vector hooks = 52 | new Vector(); 53 | 54 | private static Method methodGetService; 55 | 56 | static { 57 | try { 58 | Class classServiceManager = Class.forName("android.os.ServiceManager"); 59 | methodGetService = classServiceManager.getMethod("getService", String.class); 60 | } catch(NoSuchMethodException e) { 61 | Log.w(TAG, "Could not find method gerService"); 62 | } catch(ClassNotFoundException e) { 63 | Log.w(TAG, "Could not find class android.os.ServiceManager"); 64 | } 65 | } 66 | 67 | private static IBinder getBatteryService() { 68 | if(methodGetService == null) return null; 69 | try { 70 | return (IBinder)methodGetService.invoke(null, "batteryhook"); 71 | } catch(InvocationTargetException e) { 72 | Log.w(TAG, "Call to get service failed"); 73 | } catch(IllegalAccessException e) { 74 | Log.w(TAG, "Call to get service failed"); 75 | } 76 | return null; 77 | } 78 | 79 | public static boolean available() { 80 | synchronized(hooks) { 81 | if(hookState == STATE_INIT) { 82 | return getBatteryService() != null; 83 | } 84 | return hookState == STATE_HOOK_INSTALLED; 85 | } 86 | } 87 | 88 | public static void addHook(PowerNotifications notif) { 89 | synchronized(hooks) { 90 | if(hookState == STATE_INIT) { 91 | installHook(); 92 | } 93 | if(hookState != STATE_HOOK_INSTALLED) { 94 | Log.w(TAG, "Attempted to add hook though no " + 95 | "notification service available"); 96 | } else { 97 | hooks.add(notif); 98 | } 99 | } 100 | } 101 | 102 | public static void removeHook(PowerNotifications notif) { 103 | synchronized(hooks) { 104 | hooks.remove(notif); 105 | } 106 | } 107 | 108 | private static void installHook() { 109 | Parcel outBinder = Parcel.obtain(); 110 | outBinder.writeStrongBinder(notifier); 111 | hookState = STATE_HOOK_FAILED; 112 | try { 113 | IBinder batteryHook = getBatteryService(); 114 | if(batteryHook == null) { 115 | /* This should be the case on un-hacked phone. Maybe one day 116 | * phones will support this service or similar by default. 117 | */ 118 | Log.i(TAG, "No power notification hook service installed"); 119 | } else if(!batteryHook.transact(0, outBinder, null, 0)) { 120 | Log.w(TAG, "Failed to register forwarder"); 121 | } else { 122 | hookState = STATE_HOOK_INSTALLED; 123 | } 124 | } catch(RemoteException e) { 125 | Log.w(TAG, "Failed to register forwarder"); 126 | } 127 | outBinder.recycle(); 128 | } 129 | 130 | /* Class responsible for forwarding power notifications to registered 131 | * hooks. 132 | */ 133 | private static class NotificationForwarder extends DefaultReceiver { 134 | public boolean onTransact(int code, Parcel data, 135 | Parcel reply, int flags) throws RemoteException { 136 | synchronized(hooks) { 137 | for(Iterator iter = hooks.iterator(); 138 | iter.hasNext(); ) { 139 | Parcel junk = Parcel.obtain(); 140 | try { 141 | iter.next().asBinder().transact(code, data, junk, flags); 142 | } catch(RemoteException e) { 143 | iter.remove(); 144 | } 145 | data.setDataPosition(0); 146 | junk.recycle(); 147 | } 148 | } 149 | return super.onTransact(code, data, reply, flags); 150 | } 151 | } 152 | 153 | /* If you only want to receive a subset of the notifications just extend this 154 | * class and override the methods you care about. 155 | */ 156 | public static class DefaultReceiver extends PowerNotifications.Stub { 157 | public void noteSystemMediaCall(int uid) {} 158 | public void noteStartMedia(int uid, int id) {} 159 | public void noteStopMedia(int uid, int id) {} 160 | public void noteVideoSize(int uid, int id, int width, int height) {} 161 | public void noteStartWakelock(int uid, String name, int type) {} 162 | public void noteStopWakelock(int uid, String name, int type) {} 163 | public void noteStartSensor(int uid, int sensor) {} 164 | public void noteStopSensor(int uid, int sensor) {} 165 | public void noteStartGps(int uid) {} 166 | public void noteStopGps(int uid) {} 167 | public void noteScreenOn() {} 168 | public void noteScreenBrightness(int brightness) {} 169 | public void noteScreenOff() {} 170 | public void noteInputEvent() {} 171 | public void noteUserActivity(int uid, int event) {} 172 | public void notePhoneOn() {} 173 | public void notePhoneOff() {} 174 | public void notePhoneDataConnectionState(int dataType, boolean hasData) {} 175 | public void noteWifiOn(int uid) {} 176 | public void noteWifiOff(int uid) {} 177 | public void noteWifiRunning() {} 178 | public void noteWifiStopped() {} 179 | public void noteBluetoothOn() {} 180 | public void noteBluetoothOff() {} 181 | public void noteFullWifiLockAcquired(int uid) {} 182 | public void noteFullWifiLockReleased(int uid) {} 183 | public void noteScanWifiLockAcquired(int uid) {} 184 | public void noteScanWifiLockReleased(int uid) {} 185 | public void noteWifiMulticastEnabled(int uid) {} 186 | public void noteWifiMulticastDisabled(int uid) {} 187 | public void setOnBattery(boolean onBattery, int level) {} 188 | public void recordCurrentLevel(int level) {} 189 | public void noteVideoOn(int uid) {} 190 | public void noteVideoOff(int uid) {} 191 | public void noteAudioOn(int uid) {} 192 | public void noteAudioOff(int uid) {} 193 | } 194 | 195 | /* Useful for debugging purposes. */ 196 | public static class PrintNotifications extends PowerNotifications.Stub { 197 | public void noteSystemMediaCall(int uid) { 198 | System.out.println("System media call[uid=" + uid + "]"); 199 | } 200 | 201 | public void noteStartMedia(int uid, int id) { 202 | System.out.println("Start media[uid=" + uid + ", id=" + id + "]"); 203 | } 204 | 205 | public void noteStopMedia(int uid, int id) { 206 | System.out.println("Stop media[uid=" + uid + ", id=" + id + "]"); 207 | } 208 | 209 | public void noteVideoSize(int uid, int id, int width, int height) { 210 | System.out.println("Video size[uid=" + uid + ", id=" + id + 211 | ", width=" + width + ", height=" + height + "]"); 212 | } 213 | 214 | public void noteStartWakelock(int uid, String name, int type) { 215 | System.out.println("Start wakelock[uid=" + uid + ", name=" + name + 216 | ", type=" + type + "]"); 217 | } 218 | 219 | public void noteStopWakelock(int uid, String name, int type) { 220 | System.out.println("Stop wakelock[uid=" + uid + ", name=" + name + 221 | ", type=" + type + "]"); 222 | } 223 | 224 | public void noteStartSensor(int uid, int sensor) { 225 | System.out.println("noteStartSensor[uid=" + uid + ", sensor=" + sensor + 226 | "]"); 227 | } 228 | 229 | public void noteStopSensor(int uid, int sensor) { 230 | System.out.println("noteStopSensor[uid=" + uid + ", sensor=" + sensor + 231 | "]"); 232 | } 233 | 234 | public void noteStartGps(int uid) { 235 | System.out.println("noteStartGps[uid=" + uid + "]"); 236 | } 237 | 238 | public void noteStopGps(int uid) { 239 | System.out.println("noteStopGps[uid=" + uid + "]"); 240 | } 241 | 242 | public void noteScreenOn() { 243 | System.out.println("noteScreenOn"); 244 | } 245 | 246 | public void noteScreenBrightness(int brightness) { 247 | System.out.println("noteScreenBrightness[brightness=" + brightness + "]"); 248 | } 249 | 250 | public void noteScreenOff() { 251 | System.out.println("noteScreenOff"); 252 | } 253 | 254 | public void noteInputEvent() { 255 | System.out.println("noteInputEvent"); 256 | } 257 | 258 | public void noteUserActivity(int uid, int event) { 259 | System.out.println("noteUserActivity[uid=" + uid + ", event=" + event + 260 | "]"); 261 | } 262 | 263 | public void notePhoneOn() { 264 | System.out.println("notePhoneOn"); 265 | } 266 | 267 | public void notePhoneOff() { 268 | System.out.println("notePhoneOff"); 269 | } 270 | 271 | public void notePhoneDataConnectionState(int dataType, boolean hasData) { 272 | System.out.println("notePhoneDataConnectionState[dataType=" + dataType + 273 | ", hasData=" + hasData + "]"); 274 | } 275 | 276 | public void notePhoneState(int phoneState) { 277 | System.out.println("notePhoneState[phoneState=" + phoneState + "]"); 278 | } 279 | 280 | public void noteWifiOn(int uid) { 281 | System.out.println("noteWifiOn[uid=" + uid + "]"); 282 | } 283 | 284 | public void noteWifiOff(int uid) { 285 | System.out.println("noteWifiOff[uid=" + uid + "]"); 286 | } 287 | 288 | public void noteWifiRunning() { 289 | System.out.println("noteWifiRunning"); 290 | } 291 | 292 | public void noteWifiStopped() { 293 | System.out.println("noteWifiStopped"); 294 | } 295 | 296 | public void noteBluetoothOn() { 297 | System.out.println("noteBluetoothOn"); 298 | } 299 | 300 | public void noteBluetoothOff() { 301 | System.out.println("noteBluetoothOff"); 302 | } 303 | 304 | public void noteFullWifiLockAcquired(int uid) { 305 | System.out.println("noteFullWifiLockAcquired[uid=" + uid + "]"); 306 | } 307 | 308 | public void noteFullWifiLockReleased(int uid) { 309 | System.out.println("noteFullWifiLockReleased[uid=" + uid + "]"); 310 | } 311 | 312 | public void noteScanWifiLockAcquired(int uid) { 313 | System.out.println("noteScanWifiLockAcquired[uid=" + uid + "]"); 314 | } 315 | 316 | public void noteScanWifiLockReleased(int uid) { 317 | System.out.println("noteScanWifiLockReleased[uid=" + uid + "]"); 318 | } 319 | 320 | public void noteWifiMulticastEnabled(int uid) { 321 | System.out.println("noteWifiMulticastEnabled[uid=" + uid + "]"); 322 | } 323 | 324 | public void noteWifiMulticastDisabled(int uid) { 325 | System.out.println("noteWifiMulticastDisabled[uid=" + uid + "]"); 326 | 327 | } 328 | 329 | public void setOnBattery(boolean onBattery, int level) { 330 | System.out.println("setOnBattery[onBattery=" + onBattery + ", level=" + 331 | level + "]"); 332 | } 333 | 334 | public void recordCurrentLevel(int level) { 335 | System.out.println("recordCurrentLevel[level=" + level + "]"); 336 | } 337 | 338 | public void noteVideoOn(int uid) { 339 | System.out.println("noteVideoOn[uid=" + uid + "]"); 340 | } 341 | 342 | public void noteVideoOff(int uid) { 343 | System.out.println("noteVideoOff[uid=" + uid + "]"); 344 | } 345 | 346 | public void noteAudioOn(int uid) { 347 | System.out.println("noteAudioOn[uid=" + uid + "]"); 348 | } 349 | 350 | public void noteAudioOff(int uid) { 351 | System.out.println("noteAudioOff[uid=" + uid + "]"); 352 | } 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/edu/umich/PowerTutor/util/Recycler.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 The University of Michigan 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | Please send inquiries to powertutor@umich.edu 18 | */ 19 | 20 | package edu.umich.PowerTutor.util; 21 | 22 | import java.util.Vector; 23 | 24 | /* The aim of this class is to reduce the amount of objects that need to be 25 | * created and destroyed every iteration. If we can avoid having to allocate 26 | * objects on the heap we can ease the job of the garbage collector and be 27 | * more efficient. 28 | */ 29 | public class Recycler { 30 | private Vector list; 31 | private int avail; 32 | 33 | public Recycler() { 34 | list = new Vector(); 35 | avail = 0; 36 | } 37 | 38 | public synchronized T obtain() { 39 | if(avail == 0) { 40 | return null; 41 | } 42 | return list.get(--avail); 43 | } 44 | 45 | public synchronized void recycle(T a) { 46 | if(avail < list.size()) { 47 | list.set(avail++, a); 48 | } else { 49 | list.add(a); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/monet/experiment/DatasetSize.java: -------------------------------------------------------------------------------- 1 | package monet.experiment; 2 | 3 | import android.provider.ContactsContract; 4 | 5 | import com.happen.it.make.whatisit.MxNetGauge; 6 | import com.happen.it.make.whatisit.WhatsActivity; 7 | 8 | import java.io.File; 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | 12 | /** 13 | * Created by tianlins on 1/20/16. 14 | * In order to analyze the effect of dataset size on performance and energy. 15 | */ 16 | public class DatasetSize implements Experiment { 17 | public static String EXPERIMENT_ID = "datasize"; 18 | private static int[] repeats = {10, 20, 30, 40, 50, 60}; 19 | 20 | private WhatsActivity activity; 21 | private double[] energy, time; 22 | 23 | private FileWriter log; 24 | 25 | private MxNetGauge mxNetGauge; 26 | 27 | public DatasetSize(WhatsActivity activity, String modelName) { 28 | this.activity = activity; 29 | this.energy = new double[repeats.length]; 30 | this.time = new double[repeats.length]; 31 | 32 | 33 | File file = new File("/sdcard/" + activity.runId + "_" + EXPERIMENT_ID + "_" + modelName + ".txt"); 34 | file.delete(); 35 | try { 36 | this.log = new FileWriter(file, false); 37 | }catch(IOException e) { 38 | e.printStackTrace(); 39 | } 40 | 41 | System.out.println("[model] loading..."); 42 | mxNetGauge = new MxNetGauge(activity.getApplicationContext(), modelName); 43 | System.out.println("[model] loading complete."); 44 | } 45 | 46 | public void run() { 47 | for(int ri = 0; ri < repeats.length; ri++) { 48 | System.out.println("run #" + ri); 49 | int numRepeat = this.repeats[ri]; 50 | mxNetGauge.runTest(numRepeat); 51 | this.energy[ri] = activity.getTotalEnergy(mxNetGauge.testStartTime, mxNetGauge.testEndTime); 52 | this.time[ri] = (mxNetGauge.testEndTime - mxNetGauge.testStartTime) / 10e6; 53 | System.out.println("total energy = " + energy[ri]); 54 | System.out.println("total time = " + time[ri]); 55 | 56 | try { 57 | log.write("size " + mxNetGauge.getDatasetSize() * numRepeat 58 | + " time " + time[ri] + " energy " + energy[ri] + "\n"); 59 | log.flush(); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | System.out.println("experiment ended"); 65 | } 66 | 67 | public MxNetGauge getGauge() { 68 | return this.mxNetGauge; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/monet/experiment/Experiment.java: -------------------------------------------------------------------------------- 1 | package monet.experiment; 2 | 3 | import com.happen.it.make.whatisit.MxNetGauge; 4 | 5 | /** 6 | * Created by tianlins on 1/20/16. 7 | */ 8 | public interface Experiment { 9 | void run(); 10 | 11 | MxNetGauge getGauge(); 12 | } 13 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/monet/experiment/ProcessLevel.java: -------------------------------------------------------------------------------- 1 | package monet.experiment; 2 | 3 | import android.os.*; 4 | import android.os.Process; 5 | import android.util.Log; 6 | 7 | import com.happen.it.make.whatisit.MxNetGauge; 8 | import com.happen.it.make.whatisit.WhatsActivity; 9 | 10 | import java.io.File; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Created by tianlins on 1/22/16. 16 | */ 17 | public class ProcessLevel implements Experiment { 18 | public static String EXPERIMENT_ID = "process_level"; 19 | private static int[] priorities = { 20 | android.os.Process.THREAD_PRIORITY_LOWEST, 21 | android.os.Process.THREAD_PRIORITY_BACKGROUND, 22 | android.os.Process.THREAD_PRIORITY_AUDIO, 23 | android.os.Process.THREAD_PRIORITY_DEFAULT, 24 | android.os.Process.THREAD_PRIORITY_DISPLAY, 25 | Process.THREAD_PRIORITY_LESS_FAVORABLE 26 | }; 27 | 28 | private static int num_repeat = 100; 29 | 30 | private WhatsActivity activity; 31 | 32 | private FileWriter log; 33 | 34 | private MxNetGauge mxNetGauge; 35 | 36 | public ProcessLevel(WhatsActivity activity, String modelName) { 37 | this.activity = activity; 38 | File file = new File("/sdcard/" + activity.runId + "_" + EXPERIMENT_ID + "_" + modelName + ".txt"); 39 | file.delete(); 40 | try { 41 | this.log = new FileWriter(file, false); 42 | }catch(IOException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | System.out.println("[model] loading..."); 47 | mxNetGauge = new MxNetGauge(activity.getApplicationContext(), modelName); 48 | System.out.println("[model] loading complete."); 49 | } 50 | 51 | public void run() { 52 | for(int priority : this.priorities) { 53 | // set prioirty 54 | android.os.Process.setThreadPriority(priority); 55 | 56 | System.out.println("run with priority" + priority); 57 | mxNetGauge.runTest(num_repeat); 58 | 59 | double energy = activity.getTotalEnergy(mxNetGauge.testStartTime, mxNetGauge.testEndTime); 60 | double avgTime = mxNetGauge.statsForwardPass; 61 | 62 | System.out.println("total energy = " + energy); 63 | System.out.println("average time = " + avgTime); 64 | 65 | try { 66 | log.write("priority " + priority 67 | + " time " + avgTime + " energy " + energy + "\n"); 68 | log.flush(); 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | System.out.println("experiment ended"); 74 | } 75 | 76 | public MxNetGauge getGauge() { 77 | return this.mxNetGauge; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/org/dmlc/mxnet/ModelLoader.java: -------------------------------------------------------------------------------- 1 | package org.dmlc.mxnet; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.UnknownFormatConversionException; 10 | 11 | /** 12 | * Created by tianlins on 1/21/16. 13 | */ 14 | public class ModelLoader { 15 | protected Predictor predictor; 16 | protected List dict; 17 | 18 | public ModelLoader() { 19 | } 20 | 21 | public void load() throws UnsupportedOperationException { 22 | throw new UnsupportedOperationException("model load function not implemented."); 23 | } 24 | 25 | public Bitmap preprocess(final Bitmap origin) { 26 | return origin; // no preprocess. 27 | } 28 | 29 | public float[] toColor(final Bitmap bitmap) { 30 | throw new UnsupportedOperationException("model to color function not implemented."); 31 | } 32 | 33 | public Predictor getPredictor() { 34 | return predictor; 35 | } 36 | 37 | public List getSynsetDict() { 38 | return dict; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/org/dmlc/mxnet/MxnetException.java: -------------------------------------------------------------------------------- 1 | package org.dmlc.mxnet; 2 | 3 | public class MxnetException extends Exception { 4 | public MxnetException(){} 5 | public MxnetException(String txt) { 6 | super(txt); 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/java/org/dmlc/mxnet/Predictor.java: -------------------------------------------------------------------------------- 1 | package org.dmlc.mxnet; 2 | 3 | public class Predictor { 4 | static { 5 | System.loadLibrary("mxnet_predict"); 6 | } 7 | 8 | public static class InputNode { 9 | String key; 10 | int[] shape; 11 | public InputNode(String key, int[] shape) { 12 | this.key = key; 13 | this.shape = shape; 14 | } 15 | } 16 | 17 | public static class Device { 18 | public enum Type { 19 | CPU, GPU, CPU_PINNED 20 | } 21 | 22 | public Device(Type t, int i) { 23 | this.type = t; 24 | this.id = i; 25 | } 26 | 27 | Type type; 28 | int id; 29 | int ctype() { 30 | return this.type == Type.CPU? 1: this.type == Type.GPU? 2: 3; 31 | } 32 | } 33 | 34 | private long handle = 0; 35 | 36 | public Predictor(byte[] symbol, byte[] params, Device dev, InputNode[] input) { 37 | String[] keys = new String[input.length]; 38 | int[][] shapes = new int[input.length][]; 39 | for (int i=0; i 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /applications/Gauge/app/src/main/res/layout/activity_whats.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 |