└── 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 |
7 |
8 |
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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
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 |
25 |
26 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/menu/menu_whats.xml:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/raw/inception_bn_mean:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/raw/inception_bn_mean
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/raw/inception_bn_params:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/raw/inception_bn_params
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/raw/mean.json:
--------------------------------------------------------------------------------
1 | {
2 | "r":"117.0f",
3 | "g":"117.0f",
4 | "b":"117.0f"
5 | }
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/raw/params:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/app/src/main/res/raw/params
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/raw/symbol.json:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": [
3 | {
4 | "op": "null",
5 | "param": {},
6 | "name": "data",
7 | "inputs": [],
8 | "backward_source_id": -1
9 | },
10 | {
11 | "op": "null",
12 | "param": {},
13 | "name": "convolution0_weight",
14 | "inputs": [],
15 | "backward_source_id": -1
16 | },
17 | {
18 | "op": "null",
19 | "param": {},
20 | "name": "convolution0_bias",
21 | "inputs": [],
22 | "backward_source_id": -1
23 | },
24 | {
25 | "op": "Convolution",
26 | "param": {
27 | "kernel": "(11, 11)",
28 | "no_bias": "False",
29 | "num_filter": "64",
30 | "num_group": "1",
31 | "pad": "(0, 0)",
32 | "stride": "(4, 4)",
33 | "workspace": "512"
34 | },
35 | "name": "convolution0",
36 | "inputs": [[0, 0], [1, 0], [2, 0]],
37 | "backward_source_id": -1
38 | },
39 | {
40 | "op": "null",
41 | "param": {},
42 | "name": "batchnorm0_gamma",
43 | "inputs": [],
44 | "backward_source_id": -1
45 | },
46 | {
47 | "op": "null",
48 | "param": {},
49 | "name": "batchnorm0_beta",
50 | "inputs": [],
51 | "backward_source_id": -1
52 | },
53 | {
54 | "op": "BatchNorm",
55 | "param": {
56 | "eps": "1e-10",
57 | "momentum": "0.1"
58 | },
59 | "name": "batchnorm0",
60 | "inputs": [[3, 0], [4, 0], [5, 0]],
61 | "backward_source_id": -1
62 | },
63 | {
64 | "op": "Activation",
65 | "param": {"act_type": "relu"},
66 | "name": "activation0",
67 | "inputs": [[6, 0]],
68 | "backward_source_id": -1
69 | },
70 | {
71 | "op": "Pooling",
72 | "param": {
73 | "kernel": "(3, 3)",
74 | "pad": "(0, 0)",
75 | "pool_type": "max",
76 | "stride": "(1, 1)"
77 | },
78 | "name": "pooling0",
79 | "inputs": [[7, 0]],
80 | "backward_source_id": -1
81 | },
82 | {
83 | "op": "null",
84 | "param": {},
85 | "name": "convolution1_weight",
86 | "inputs": [],
87 | "backward_source_id": -1
88 | },
89 | {
90 | "op": "null",
91 | "param": {},
92 | "name": "convolution1_bias",
93 | "inputs": [],
94 | "backward_source_id": -1
95 | },
96 | {
97 | "op": "Convolution",
98 | "param": {
99 | "kernel": "(3, 3)",
100 | "no_bias": "False",
101 | "num_filter": "192",
102 | "num_group": "1",
103 | "pad": "(0, 0)",
104 | "stride": "(2, 2)",
105 | "workspace": "512"
106 | },
107 | "name": "convolution1",
108 | "inputs": [[8, 0], [9, 0], [10, 0]],
109 | "backward_source_id": -1
110 | },
111 | {
112 | "op": "Activation",
113 | "param": {"act_type": "relu"},
114 | "name": "activation1",
115 | "inputs": [[11, 0]],
116 | "backward_source_id": -1
117 | },
118 | {
119 | "op": "Pooling",
120 | "param": {
121 | "kernel": "(3, 3)",
122 | "pad": "(0, 0)",
123 | "pool_type": "max",
124 | "stride": "(2, 2)"
125 | },
126 | "name": "pooling1",
127 | "inputs": [[12, 0]],
128 | "backward_source_id": -1
129 | },
130 | {
131 | "op": "null",
132 | "param": {},
133 | "name": "convolution2_weight",
134 | "inputs": [],
135 | "backward_source_id": -1
136 | },
137 | {
138 | "op": "null",
139 | "param": {},
140 | "name": "convolution2_bias",
141 | "inputs": [],
142 | "backward_source_id": -1
143 | },
144 | {
145 | "op": "Convolution",
146 | "param": {
147 | "kernel": "(3, 3)",
148 | "no_bias": "False",
149 | "num_filter": "96",
150 | "num_group": "1",
151 | "pad": "(1, 1)",
152 | "stride": "(1, 1)",
153 | "workspace": "512"
154 | },
155 | "name": "convolution2",
156 | "inputs": [[13, 0], [14, 0], [15, 0]],
157 | "backward_source_id": -1
158 | },
159 | {
160 | "op": "Activation",
161 | "param": {"act_type": "relu"},
162 | "name": "activation2",
163 | "inputs": [[16, 0]],
164 | "backward_source_id": -1
165 | },
166 | {
167 | "op": "null",
168 | "param": {},
169 | "name": "convolution3_weight",
170 | "inputs": [],
171 | "backward_source_id": -1
172 | },
173 | {
174 | "op": "null",
175 | "param": {},
176 | "name": "convolution3_bias",
177 | "inputs": [],
178 | "backward_source_id": -1
179 | },
180 | {
181 | "op": "Convolution",
182 | "param": {
183 | "kernel": "(3, 3)",
184 | "no_bias": "False",
185 | "num_filter": "160",
186 | "num_group": "1",
187 | "pad": "(1, 1)",
188 | "stride": "(1, 1)",
189 | "workspace": "512"
190 | },
191 | "name": "convolution3",
192 | "inputs": [[17, 0], [18, 0], [19, 0]],
193 | "backward_source_id": -1
194 | },
195 | {
196 | "op": "Activation",
197 | "param": {"act_type": "relu"},
198 | "name": "activation3",
199 | "inputs": [[20, 0]],
200 | "backward_source_id": -1
201 | },
202 | {
203 | "op": "null",
204 | "param": {},
205 | "name": "convolution4_weight",
206 | "inputs": [],
207 | "backward_source_id": -1
208 | },
209 | {
210 | "op": "null",
211 | "param": {},
212 | "name": "convolution4_bias",
213 | "inputs": [],
214 | "backward_source_id": -1
215 | },
216 | {
217 | "op": "Convolution",
218 | "param": {
219 | "kernel": "(3, 3)",
220 | "no_bias": "False",
221 | "num_filter": "144",
222 | "num_group": "1",
223 | "pad": "(1, 1)",
224 | "stride": "(1, 1)",
225 | "workspace": "512"
226 | },
227 | "name": "convolution4",
228 | "inputs": [[21, 0], [22, 0], [23, 0]],
229 | "backward_source_id": -1
230 | },
231 | {
232 | "op": "Activation",
233 | "param": {"act_type": "relu"},
234 | "name": "activation4",
235 | "inputs": [[24, 0]],
236 | "backward_source_id": -1
237 | },
238 | {
239 | "op": "null",
240 | "param": {},
241 | "name": "convolution5_weight",
242 | "inputs": [],
243 | "backward_source_id": -1
244 | },
245 | {
246 | "op": "null",
247 | "param": {},
248 | "name": "convolution5_bias",
249 | "inputs": [],
250 | "backward_source_id": -1
251 | },
252 | {
253 | "op": "Convolution",
254 | "param": {
255 | "kernel": "(3, 3)",
256 | "no_bias": "False",
257 | "num_filter": "160",
258 | "num_group": "1",
259 | "pad": "(1, 1)",
260 | "stride": "(1, 1)",
261 | "workspace": "512"
262 | },
263 | "name": "convolution5",
264 | "inputs": [[25, 0], [26, 0], [27, 0]],
265 | "backward_source_id": -1
266 | },
267 | {
268 | "op": "Activation",
269 | "param": {"act_type": "relu"},
270 | "name": "activation5",
271 | "inputs": [[28, 0]],
272 | "backward_source_id": -1
273 | },
274 | {
275 | "op": "null",
276 | "param": {},
277 | "name": "batchnorm1_gamma",
278 | "inputs": [],
279 | "backward_source_id": -1
280 | },
281 | {
282 | "op": "null",
283 | "param": {},
284 | "name": "batchnorm1_beta",
285 | "inputs": [],
286 | "backward_source_id": -1
287 | },
288 | {
289 | "op": "BatchNorm",
290 | "param": {
291 | "eps": "1e-10",
292 | "momentum": "0.1"
293 | },
294 | "name": "batchnorm1",
295 | "inputs": [[29, 0], [30, 0], [31, 0]],
296 | "backward_source_id": -1
297 | },
298 | {
299 | "op": "null",
300 | "param": {},
301 | "name": "convolution6_weight",
302 | "inputs": [],
303 | "backward_source_id": -1
304 | },
305 | {
306 | "op": "null",
307 | "param": {},
308 | "name": "convolution6_bias",
309 | "inputs": [],
310 | "backward_source_id": -1
311 | },
312 | {
313 | "op": "Convolution",
314 | "param": {
315 | "kernel": "(3, 3)",
316 | "no_bias": "False",
317 | "num_filter": "256",
318 | "num_group": "1",
319 | "pad": "(1, 1)",
320 | "stride": "(1, 1)",
321 | "workspace": "512"
322 | },
323 | "name": "convolution6",
324 | "inputs": [[32, 0], [33, 0], [34, 0]],
325 | "backward_source_id": -1
326 | },
327 | {
328 | "op": "Activation",
329 | "param": {"act_type": "relu"},
330 | "name": "activation6",
331 | "inputs": [[35, 0]],
332 | "backward_source_id": -1
333 | },
334 | {
335 | "op": "Pooling",
336 | "param": {
337 | "kernel": "(12, 12)",
338 | "pad": "(0, 0)",
339 | "pool_type": "avg",
340 | "stride": "(1, 1)"
341 | },
342 | "name": "pooling2",
343 | "inputs": [[36, 0]],
344 | "backward_source_id": -1
345 | },
346 | {
347 | "op": "Flatten",
348 | "param": {},
349 | "name": "feature",
350 | "inputs": [[37, 0]],
351 | "backward_source_id": -1
352 | },
353 | {
354 | "op": "Dropout",
355 | "param": {"p": "0.5"},
356 | "name": "dropout0",
357 | "inputs": [[38, 0]],
358 | "backward_source_id": -1
359 | },
360 | {
361 | "op": "null",
362 | "param": {},
363 | "name": "fullyconnected0_weight",
364 | "inputs": [],
365 | "backward_source_id": -1
366 | },
367 | {
368 | "op": "null",
369 | "param": {},
370 | "name": "fullyconnected0_bias",
371 | "inputs": [],
372 | "backward_source_id": -1
373 | },
374 | {
375 | "op": "FullyConnected",
376 | "param": {
377 | "no_bias": "False",
378 | "num_hidden": "1000"
379 | },
380 | "name": "fullyconnected0",
381 | "inputs": [[39, 0], [40, 0], [41, 0]],
382 | "backward_source_id": -1
383 | },
384 | {
385 | "op": "null",
386 | "param": {},
387 | "name": "softmax0_label",
388 | "inputs": [],
389 | "backward_source_id": -1
390 | },
391 | {
392 | "op": "Softmax",
393 | "param": {
394 | "grad_scale": "1",
395 | "multi_output": "False"
396 | },
397 | "name": "softmax0",
398 | "inputs": [[42, 0], [43, 0]],
399 | "backward_source_id": -1
400 | }
401 | ],
402 | "arg_nodes": [
403 | 0,
404 | 1,
405 | 2,
406 | 4,
407 | 5,
408 | 9,
409 | 10,
410 | 14,
411 | 15,
412 | 18,
413 | 19,
414 | 22,
415 | 23,
416 | 26,
417 | 27,
418 | 30,
419 | 31,
420 | 33,
421 | 34,
422 | 40,
423 | 41,
424 | 43
425 | ],
426 | "heads": [[44, 0]]
427 | }
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | WhatsThis
3 |
4 | Nothing
5 | Settings
6 | What is this?
7 | Use Gallery
8 | Use Camera
9 |
10 |
--------------------------------------------------------------------------------
/applications/Gauge/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/applications/Gauge/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/applications/Gauge/data/cat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/cat.jpg
--------------------------------------------------------------------------------
/applications/Gauge/data/keyboard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/keyboard.jpg
--------------------------------------------------------------------------------
/applications/Gauge/data/night.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/night.jpg
--------------------------------------------------------------------------------
/applications/Gauge/data/red-car.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/red-car.jpg
--------------------------------------------------------------------------------
/applications/Gauge/data/sea.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/sea.jpg
--------------------------------------------------------------------------------
/applications/Gauge/data/sky.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/data/sky.jpg
--------------------------------------------------------------------------------
/applications/Gauge/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.useDeprecatedNdk=true
20 |
--------------------------------------------------------------------------------
/applications/Gauge/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/strin/monet/f48d8d4adbe0c1e3df9ff75d5626ec66be5fd44f/applications/Gauge/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/applications/Gauge/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Nov 10 06:37:44 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/applications/Gauge/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/applications/Gauge/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/applications/Gauge/notebook/utils.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import plotly.plotly as py
3 | import plotly.graph_objs as go
4 | import re
5 |
6 | device_id = '03157df3929b6037'
7 |
8 | def run_cmd(cmd):
9 | p = subprocess.Popen(cmd.split(' '),
10 | stdout=subprocess.PIPE, stderr=subprocess.PIPE)
11 | out, err = p.communicate()
12 | return out
13 |
14 | def parse_table(out, split_ch=' '):
15 | vs = dict()
16 |
17 | lines = out.split('\n')
18 | for line in lines:
19 | items = line.strip().split(split_ch)
20 | if len(items) % 2 != 0:
21 | continue
22 | for i in range(0, len(items), 2):
23 | name = items[i]
24 | val = float(items[i+1])
25 | if name not in vs:
26 | vs[name] = []
27 | vs[name].append(val)
28 |
29 | return vs
30 |
31 | def get_runs():
32 | out = run_cmd('adb -s %s shell ls -l /sdcard/*.txt' % device_id)
33 | print 'output', out
34 | run_ids = set(re.findall('.*/([0-9]*)\.txt[\r]?\n', out))
35 | return list(run_ids)
36 |
37 | def get_vs(run_id, experiment_id):
38 | out = run_cmd('adb -s %s shell cat /sdcard/%s_%s.txt' % (device_id, run_id, experiment_id))
39 | vs = parse_table(out)
40 | return vs
41 |
42 | def plot_xy(x, y, names=None, xlabel='x', ylabel='y', title=''):
43 |
44 | layout = go.Layout(
45 | title=title,
46 | xaxis=dict(
47 | title=xlabel,
48 | titlefont=dict(
49 | family='Courier New, monospace',
50 | size=18,
51 | color='#7f7f7f'
52 | )
53 | ),
54 | yaxis=dict(
55 | title=ylabel,
56 | titlefont=dict(
57 | family='Courier New, monospace',
58 | size=18,
59 | color='#7f7f7f'
60 | )
61 | )
62 | )
63 |
64 | if type(x) == list:
65 | xs = x
66 | ys = y
67 | if not names:
68 | names = ['line-' + i for i in range(len(xs))]
69 | else:
70 | xs = [x]
71 | ys = [y]
72 | names = ['line']
73 |
74 | traces = []
75 |
76 | for (x, y, name) in zip(xs, ys, names):
77 | trace = go.Scatter(
78 | x = x,
79 | y = y,
80 | name = name
81 | )
82 | traces.append(trace)
83 |
84 | data = traces
85 | fig = go.Figure(data=data, layout=layout)
86 | disp = py.iplot(fig, filename='basic-line')
87 | return disp.data
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/applications/Gauge/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------