Java tutorial
/* Copyright (C) 2011 The University of Michigan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Please send inquiries to powertutor@umich.edu */ package edu.cnu.PowerTutor.ui; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.Vector; import org.achartengine.GraphicalView; import org.achartengine.chart.CubicLineChart; import org.achartengine.model.XYMultipleSeriesDataset; import org.achartengine.model.XYSeries; import org.achartengine.renderer.XYMultipleSeriesRenderer; import org.achartengine.renderer.XYSeriesRenderer; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.Log; import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager.BadTokenException; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import edu.cnu.PowerTutor.R; import edu.cnu.PowerTutor.service.ICounterService; import edu.cnu.PowerTutor.service.PowerEstimator; import edu.cnu.PowerTutor.service.UMLoggerService; import edu.umich.PowerTutor.util.SystemInfo; public class PowerViewer extends Activity { private static final String TAG = "PowerViewer"; private static final int HTTP_STATUS_OK = 200; // Dialog ? ?. public static final int DIALOG_PROBABILITY_PROGRESS = 1; private int PROGRESS_MAX = 300; // 300? ?? // ? ?. public final static int PROCESSRESULT = 1; private SharedPreferences prefs; private int uid; private int components; private String[] componentNames; private int[] componentsMaxPower; private int noUidMask; private boolean collecting; private ValueCollector[] collectors; private Intent serviceIntent; private CounterServiceConnection conn; private ICounterService counterService; // ? . ? : ? . ANR ? ? . private Handler handler; private LinearLayout chartLayout; // ? . private int SeletedUid; private String SeletedPackageName; // ?. private ProgressDialog mWriteProgressDialog; public void refreshView() { if (counterService == null) { TextView loadingText = new TextView(this); loadingText.setText("Waiting for profiler service..."); loadingText.setGravity(Gravity.CENTER); setContentView(loadingText); return; } chartLayout = new LinearLayout(this); chartLayout.setOrientation(LinearLayout.VERTICAL); if (uid == SystemInfo.AID_ALL) { /* * If we are reporting global power usage then just set noUidMask to * 0 so that all components get displayed. */ noUidMask = 0; } components = 0; for (int i = 0; i < componentNames.length; i++) { if ((noUidMask & 1 << i) == 0) { components++; } } boolean showTotal = prefs.getBoolean("showTotalPower", false); collectors = new ValueCollector[(showTotal ? 1 : 0) + components]; int pos = 0; for (int i = showTotal ? -1 : 0; i < componentNames.length; i++) { if (i != -1 && (noUidMask & 1 << i) != 0) { continue; } String name = i == -1 ? "Total" : componentNames[i]; double mxPower = (i == -1 ? 2100.0 : componentsMaxPower[i]) * 1.05; XYSeries series = new XYSeries(name); XYMultipleSeriesDataset mseries = new XYMultipleSeriesDataset(); mseries.addSeries(series); XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(); XYSeriesRenderer srenderer = new XYSeriesRenderer(); renderer.setYAxisMin(0.0); renderer.setYAxisMax(mxPower); renderer.setYTitle(name + "(mW)"); int clr = PowerPie.COLORS[(PowerPie.COLORS.length + i) % PowerPie.COLORS.length]; srenderer.setColor(clr); srenderer.setFillBelowLine(true); srenderer.setFillBelowLineColor(((clr >> 1) & 0x7F7F7F) | (clr & 0xFF000000)); renderer.addSeriesRenderer(srenderer); View chartView = new GraphicalView(this, new CubicLineChart(mseries, renderer, 0.5f)); chartView.setMinimumHeight(100); chartLayout.addView(chartView); collectors[pos] = new ValueCollector(series, renderer, chartView, i); if (handler != null) { // Main Handler? . (debug) handler.post(collectors[pos]); } pos++; } /* * We're giving 100 pixels per graph of vertical space for the chart * view. If we don't specify a minimum height the chart view ends up * having a height of 0 so this is important. */ chartLayout.setMinimumHeight(100 * components); ScrollView scrollView = new ScrollView(this); scrollView.addView(chartLayout); setContentView(scrollView); } private class CounterServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName className, IBinder boundService) { counterService = ICounterService.Stub.asInterface((IBinder) boundService); try { componentNames = counterService.getComponents(); componentsMaxPower = counterService.getComponentsMaxPower(); noUidMask = counterService.getNoUidMask(); refreshView(); } catch (RemoteException e) { counterService = null; } } public void onServiceDisconnected(ComponentName className) { counterService = null; getApplicationContext().unbindService(conn); getApplicationContext().bindService(serviceIntent, conn, 0); Log.w(TAG, "Unexpectedly lost connection to service"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prefs = PreferenceManager.getDefaultSharedPreferences(this); uid = getIntent().getIntExtra("uid", SystemInfo.AID_ALL); collecting = true; if (savedInstanceState != null) { collecting = savedInstanceState.getBoolean("collecting", true); componentNames = savedInstanceState.getStringArray("componentNames"); noUidMask = savedInstanceState.getInt("noUidMask"); } serviceIntent = new Intent(this, UMLoggerService.class); conn = new CounterServiceConnection(); } @Override protected void onResume() { super.onResume(); handler = new Handler(); getApplicationContext().bindService(serviceIntent, conn, 0); refreshView(); } @Override protected void onPause() { super.onPause(); getApplicationContext().unbindService(conn); if (collectors != null) for (int i = 0; i < components; i++) { handler.removeCallbacks(collectors[i]); } counterService = null; handler = null; collecting = true; } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean("collecting", collecting); outState.putStringArray("componentNames", componentNames); outState.putInt("noUidMask", noUidMask); } /* Let all of the UI graphs lay themselves out again. */ private void stateChanged() { for (int i = 0; i < components; i++) { collectors[i].layout(); } } private static final int MENU_OPTIONS = 0; private static final int MENU_TOGGLE_COLLECTING = 1; private static final int MENU_APP_RATING = 2; @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_OPTIONS, 0, "Options"); menu.add(0, MENU_TOGGLE_COLLECTING, 0, ""); menu.add(0, MENU_APP_RATING, 0, "App Rating"); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(MENU_TOGGLE_COLLECTING).setTitle(collecting ? "Pause" : "Resume"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_OPTIONS: startActivity(new Intent(this, ViewerPreferences.class)); return true; case MENU_TOGGLE_COLLECTING: collecting = !collecting; if (handler != null) { if (collecting) for (int i = 0; i < components; i++) { collectors[i].reset(); handler.post(collectors[i]); } else for (int i = 0; i < components; i++) { handler.removeCallbacks(collectors[i]); } } break; // Power consumption data send to my server #justin case MENU_APP_RATING: Intent intent = new Intent(this, AppChoiceView.class); startActivityForResult(intent, 0); /* * new Thread() { public void start() { int[] valuesServer = new * int[300]; try { * * valuesServer = counterService.getComponentHistory(300, * -1,SystemInfo.AID_ALL); } catch (RemoteException e1) { // TODO * Auto-generated catch block e1.printStackTrace(); } * * for(int i=0; i<300; i++){ //?? ? . try { * sendData("a",""+valuesServer[i], "123" ); } catch * (ClientProtocolException e) { // TODO Auto-generated catch block * e.printStackTrace(); } catch (IOException e) { // TODO * Auto-generated catch block e.printStackTrace(); } } } }.start(); */ break; } return false; } /** * ? ? ? ? ?. ? ? ? ? ? ? . */ @Override protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_PROBABILITY_PROGRESS: mWriteProgressDialog = new ProgressDialog(this); mWriteProgressDialog.setIcon(android.R.drawable.ic_dialog_info); mWriteProgressDialog.setTitle(getString(R.string.progress_title)); mWriteProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mWriteProgressDialog.setCancelable(false); mWriteProgressDialog.setMessage(getString(R.string.write_progress_message)); // progress bar ? . mWriteProgressDialog.setMax(PROGRESS_MAX); Log.d(TAG, "onCreateDialog pass"); return mWriteProgressDialog; } return null; } /** * Dialog . */ public void dismissDialogSafely(final int id) { runOnUiThread(new Runnable() { public void run() { try { dismissDialog(id); } catch (IllegalArgumentException e) { // ? ? . Log.w(TAG, "Could not dismiss dialog with id " + id, e); } } }); } /** * Dialog ? Main UI? ? ? . */ public void showDialogSafely(final int id) { // ? UI Thread ? ?. // ? ? . runOnUiThread(new Runnable() { public void run() { try { // ? ? ? ? ? . // ? onCreateDialog ? . showDialog(id); } catch (BadTokenException e) { Log.w(TAG, "Could not display dialog with id " + id, e); } catch (IllegalStateException e) { Log.w(TAG, "Could not display dialog with id " + id, e); } } }); } // ? ? UI Thread?. public void saveProgress(int arTime) { showDialogSafely(DIALOG_PROBABILITY_PROGRESS); Log.d(TAG, "saveProgress pass"); // dismissDialogSafely(DIALOG_PROBABILITY_PROGRESS); // . .. // showMessageDialog(0, true); } // ? ? . @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub switch (requestCode) { case 0: if (resultCode == RESULT_OK) { SeletedUid = data.getIntExtra("uid", 0); SeletedPackageName = data.getStringExtra("package_name"); Toast.makeText(PowerViewer.this, "Extra Data: " + SeletedUid + " " + SeletedPackageName, Toast.LENGTH_SHORT).show(); // ? ? ?? ? ?? . // ? ?? ? ? . saveProgress(PROGRESS_MAX); // ? . // Thread?? ?? Server Thread?. processResultThread mProcessResultThread = new processResultThread(); // Thread . mProcessResultThread.start(); Log.d(TAG, "Thread start pass"); } break; } } class processResultThread extends Thread { int mValue = 0; /* ?. */ int[] TotalPower = new int[PROGRESS_MAX]; int[] LedPower = new int[PROGRESS_MAX]; int[] CpuPower = new int[PROGRESS_MAX]; int[] WiFiPower = new int[PROGRESS_MAX]; int[] ThreegPower = new int[PROGRESS_MAX]; int[] GpsPower = new int[PROGRESS_MAX]; int[] AudioPower = new int[PROGRESS_MAX]; public void run() { /* * ? ? ?? ? */ // Race Condition? . ex : IBinder ? ?? // NullPointerException? // ? . while (counterService == null) { try { Thread.sleep(1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } ; try { TotalPower = counterService.getComponentHistory(PROGRESS_MAX, -1, SystemInfo.AID_ALL); LedPower = counterService.getComponentHistory(PROGRESS_MAX, 0, SystemInfo.AID_ALL); CpuPower = counterService.getComponentHistory(PROGRESS_MAX, 1, SystemInfo.AID_ALL); WiFiPower = counterService.getComponentHistory(PROGRESS_MAX, 2, SystemInfo.AID_ALL); ThreegPower = counterService.getComponentHistory(PROGRESS_MAX, 3, SystemInfo.AID_ALL); GpsPower = counterService.getComponentHistory(PROGRESS_MAX, 4, SystemInfo.AID_ALL); AudioPower = counterService.getComponentHistory(PROGRESS_MAX, 5, SystemInfo.AID_ALL); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.d(TAG, "processResult information 6 pass"); while (mValue < PROGRESS_MAX) { mValue++; // ?? ? ? . Message msg = mTimerHandler.obtainMessage(); msg.what = PROCESSRESULT; msg.arg1 = mValue; try { sendData(mValue, SeletedPackageName, TotalPower[mValue - 1], LedPower[mValue - 1], CpuPower[mValue - 1], WiFiPower[mValue - 1], ThreegPower[mValue - 1], GpsPower[mValue - 1], AudioPower[mValue - 1]); } catch (ClientProtocolException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } mTimerHandler.sendMessage(msg); } } } // Main Handler ? ? ? ? . Handler mTimerHandler = new Handler() { public void handleMessage(Message msg) { String mDialogMessage = ""; // ? ? ?. if (msg.what == PROCESSRESULT) { mWriteProgressDialog.setProgress(msg.arg1); // main UI? ? . if (msg.arg1 >= PROGRESS_MAX) { dismissDialogSafely(DIALOG_PROBABILITY_PROGRESS); } return; } } }; // ? ? . . // ?. private Handler mHandler = new Handler() { public void handleMessage(Message msg) { String mDialogMessage = ""; // ? ? ?. if (msg.what == PROCESSRESULT) { mWriteProgressDialog.setProgress(msg.arg1); // main UI? ? . if (msg.arg1 >= PROGRESS_MAX) { dismissDialogSafely(DIALOG_PROBABILITY_PROGRESS); } return; } } }; private String sendData(int time, String PackageName, int total, int led, int cpu, int wifi, int threeg, int gps, int audio) throws ClientProtocolException, IOException { // TODO Auto-generated method stub String result = null; String url = "http://192.168.10.5:8880/powerScanner/input.jsp"; // Server Page IP address HttpPost request = makeHttpPost(time, PackageName, total, led, cpu, wifi, threeg, gps, audio, url); // this method create HttpClient instance -package name : // org.apache.http.impl.client - HttpClient client = new DefaultHttpClient(); // ResponseHandler<String> reshandler = new BasicResponseHandler() ; HttpResponse response = client.execute(request); // detection true, as response message StatusLine status = response.getStatusLine(); if (status.getStatusCode() != HTTP_STATUS_OK) { result = "Invalid response from server : " + status.toString(); return result; } // if ture status is gotten form responding object . HttpEntity entity = response.getEntity(); InputStream is = entity.getContent(); // Entity change for string BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } is.close(); result = sb.toString(); return result; } private HttpPost makeHttpPost(int time, String PackageName, int total, int led, int cpu, int wifi, int threeg, int gps, int audio, String url) { // TODO Auto-generated method stub HttpPost request = new HttpPost(url); // HttpPost instance create Vector<NameValuePair> nameValue = new Vector<NameValuePair>(); // ?? ? ? ?. nameValue.add(new BasicNameValuePair("packagename", PackageName)); nameValue.add(new BasicNameValuePair("total", Integer.toString(total))); nameValue.add(new BasicNameValuePair("led", Integer.toString(led))); nameValue.add(new BasicNameValuePair("cpu", Integer.toString(cpu))); nameValue.add(new BasicNameValuePair("wifi", Integer.toString(wifi))); nameValue.add(new BasicNameValuePair("threeg", Integer.toString(threeg))); nameValue.add(new BasicNameValuePair("gps", Integer.toString(gps))); nameValue.add(new BasicNameValuePair("audio", Integer.toString(audio))); nameValue.add(new BasicNameValuePair("time", Integer.toString(time))); request.setEntity(makeEntity(nameValue)); return request; } private HttpEntity makeEntity(Vector<NameValuePair> nameValue) { HttpEntity result = null; try { result = new UrlEncodedFormEntity(nameValue, "UTF-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } public class ValueCollector implements Runnable { private XYSeries series; private XYMultipleSeriesRenderer renderer; private View chartView; private int componentId; private long lastTime; int[] values; private boolean readHistory; public ValueCollector(XYSeries series, XYMultipleSeriesRenderer renderer, View chartView, int componentId) { this.series = series; this.renderer = renderer; this.chartView = chartView; this.componentId = componentId; lastTime = SystemClock.elapsedRealtime(); layout(); } public void layout() { int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", "60")); values = new int[numVals]; renderer.clearXTextLabels(); renderer.setXAxisMin(0); renderer.setXAxisMax(numVals - 1); renderer.addXTextLabel(numVals - 1, "" + numVals); renderer.setXLabels(0); for (int j = 0; j < 10; j++) { renderer.addXTextLabel(numVals * j / 10, "" + (1 + numVals * j / 10)); } reset(); } /** Restart points collecting from zero. */ public void reset() { series.clear(); readHistory = true; } // - ? ?? ?. - // ? Thread ? ? . for example : LED or CPU public void run() { int numVals = Integer.parseInt(prefs.getString("viewNumValues_s", "60")); if (counterService != null) try { if (readHistory) { values = counterService.getComponentHistory(numVals, componentId, uid); readHistory = false; } else { for (int i = numVals - 1; i > 0; i--) { values[i] = values[i - 1]; } values[0] = counterService.getComponentHistory(1, componentId, uid)[0]; } } catch (RemoteException e) { Log.w(TAG, "Failed to get data from service"); for (int i = 0; i < numVals; i++) { values[i] = 0; } } series.clear(); for (int i = 0; i < numVals; i++) { series.add(i, values[i]); } long curTime = SystemClock.elapsedRealtime(); long tryTime = lastTime + PowerEstimator.ITERATION_INTERVAL * (long) Math.max(1, 1 + (curTime - lastTime) / PowerEstimator.ITERATION_INTERVAL); if (handler != null) { handler.postDelayed(this, tryTime - curTime); } chartView.invalidate(); } } }