/** Copyright (C) 2013 Louis Teboul (a.k.a Androguide)
*
* admin@pimpmyrom.org || louisteboul@gmail.com
* http://pimpmyrom.org || http://androguide.fr
* 71 quai Clémenceau, 69300 Caluire-et-Cuire, FRANCE.
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
**/
package com.androguide.honamicontrol.kernel.gpucontrol;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import com.androguide.honamicontrol.MainActivity;
import com.androguide.honamicontrol.R;
import com.androguide.honamicontrol.helpers.CPUHelper;
import com.androguide.honamicontrol.helpers.Helpers;
import com.echo.holographlibrary.Line;
import com.echo.holographlibrary.LineGraph;
import com.echo.holographlibrary.LinePoint;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class GPUActivity extends ActionBarActivity {
private static SharedPreferences preferences, bootPrefs;
private static LineGraph graph;
private static Line line;
private static int currX = 0;
private static int counter = 0;
private static TextView mCurFreq;
private SeekBar mMaxSlider;
private SeekBar mMinSlider;
private TextView mMaxSpeedText;
private TextView mMinSpeedText;
private String[] availableFrequencies;
private String mMaxFreqSetting;
private String mMinFreqSetting;
private CurCPUThread mCurCPUThread;
private int spinnerCounter = 0;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent back = new Intent(this, MainActivity.class);
back.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(back);
default:
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_gpu_control));
setContentView(R.layout.card_gpu_control);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
bootPrefs = getSharedPreferences("BOOT_PREFS", 0);
graph = (LineGraph) findViewById(R.id.graph);
line = new Line();
LinePoint point = new LinePoint();
point.setX(currX);
point.setY(1);
line.addPoint(point);
line.setColor(Color.parseColor("#FFBB33"));
graph.addLine(line);
graph.setLineToFill(0);
availableFrequencies = new String[0];
String availableFrequenciesLine = "";
if (Helpers.doesFileExist(GPUInterface.availableFreqs)) {
availableFrequenciesLine = CPUHelper.readOneLineNotRoot(GPUInterface.availableFreqs);
if (availableFrequenciesLine != null) {
availableFrequencies = availableFrequenciesLine.split(" ");
Arrays.sort(availableFrequencies, new Comparator<String>() {
@Override
public int compare(String object1, String object2) {
return Integer.valueOf(object1).compareTo(
Integer.valueOf(object2));
}
});
}
}
int frequenciesNum = availableFrequencies.length - 1;
String currentGovernor = "";
if (Helpers.doesFileExist(GPUInterface.currGovernor))
currentGovernor = CPUHelper.readOneLineNotRoot(GPUInterface.currGovernor);
String curMaxSpeed = "";
if (Helpers.doesFileExist(GPUInterface.maxFreq))
curMaxSpeed = CPUHelper.readOneLineNotRoot(GPUInterface.maxFreq);
String curMinSpeed = "";
if (Helpers.doesFileExist(GPUInterface.minFreq))
curMinSpeed = CPUHelper.readOneLineNotRoot(GPUInterface.minFreq);
mCurFreq = (TextView) findViewById(R.id.currspeed);
mMaxSlider = (SeekBar) findViewById(R.id.max_slider);
mMaxSlider.setMax(frequenciesNum);
mMaxSpeedText = (TextView) findViewById(R.id.max_speed_text);
mMaxSpeedText.setText(toMHz(curMaxSpeed));
mMaxSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
curMaxSpeed));
mMaxSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser)
setMaxSpeed(seekBar, progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mMaxFreqSetting != null && !mMaxFreqSetting.isEmpty()) {
Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > "
+ GPUInterface.maxFreq);
bootPrefs.edit().putString("GPU_MAX_FREQ", mMaxFreqSetting).commit();
}
}
});
mMinSlider = (SeekBar) findViewById(R.id.min_slider);
mMinSlider.setMax(frequenciesNum);
mMinSpeedText = (TextView) findViewById(R.id.min_speed_text);
mMinSpeedText.setText(toMHz(curMinSpeed));
mMinSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
curMinSpeed));
mMinSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser)
setMinSpeed(seekBar, progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mMinFreqSetting != null && !mMinFreqSetting.isEmpty()) {
Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMinFreqSetting + " > "
+ GPUInterface.minFreq);
bootPrefs.edit().putString("GPU_MIN_FREQ", mMinFreqSetting).commit();
}
}
});
Spinner mGovernor = (Spinner) findViewById(R.id.governor);
String[] availableGovernors = new String[]{"No GPU Governors Found!"};
if (Helpers.doesFileExist(GPUInterface.availableGovernors))
availableGovernors = CPUHelper.readOneLineNotRoot(GPUInterface.availableGovernors)
.split(" ");
ArrayAdapter<CharSequence> governorAdapter = new ArrayAdapter<CharSequence>(
this, R.layout.spinner_row);
governorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
for (int i = 0; i < availableGovernors.length; i++) {
governorAdapter.add(availableGovernors[i]);
}
mGovernor.setAdapter(governorAdapter);
mGovernor.setSelection(Arrays.asList(availableGovernors).indexOf(
currentGovernor));
mGovernor.setOnItemSelectedListener(new GovListener());
}
public class GovListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos,
long id) {
if (spinnerCounter > 0) {
String selected = parent.getItemAtPosition(pos).toString();
Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > "
+ GPUInterface.currGovernor);
bootPrefs.edit().putString("GPU_GOVERNOR", selected).commit();
final SharedPreferences.Editor editor = preferences.edit();
editor.putString("GPU_GOVERNOR", selected);
editor.commit();
} else {
spinnerCounter++;
}
}
public void onNothingSelected(AdapterView<?> parent) {
}
}
@Override
public void onResume() {
super.onResume();
if (mCurCPUThread == null) {
mCurCPUThread = new CurCPUThread();
mCurCPUThread.start();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mCurCPUThread.isAlive()) {
mCurCPUThread.interrupt();
try {
mCurCPUThread.join();
} catch (InterruptedException e) {
}
}
}
public void setMaxSpeed(SeekBar seekBar, int progress) {
String current;
current = availableFrequencies[progress];
int minSliderProgress = mMinSlider.getProgress();
if (progress <= minSliderProgress && !current.isEmpty()) {
mMinSlider.setProgress(progress);
mMinSpeedText.setText(toMHz(current));
mMinFreqSetting = current;
}
mMaxSpeedText.setText(toMHz(current));
mMaxFreqSetting = current;
final SharedPreferences.Editor editor = preferences.edit();
editor.putString(GPUInterface.maxFreq, current);
editor.commit();
}
public void setMinSpeed(SeekBar seekBar, int progress) {
String current;
current = availableFrequencies[progress];
int maxSliderProgress = mMaxSlider.getProgress();
if (progress >= maxSliderProgress) {
mMaxSlider.setProgress(progress);
mMaxSpeedText.setText(toMHz(current));
mMaxFreqSetting = current;
}
mMinSpeedText.setText(toMHz(current));
mMinFreqSetting = current;
final SharedPreferences.Editor editor = preferences.edit();
editor.putString(GPUInterface.minFreq, current);
editor.commit();
}
// Convert raw collected values to formatted MhZ
private static String toMHz(String mhzString) {
try {
if (Integer.valueOf(mhzString) != null) {
int val = 0;
try {
val = Integer.valueOf(mhzString);
} catch (NumberFormatException e) {
Log.e("ToMHZ", e.getMessage());
}
return String.valueOf(val / 1000000) + " MHz";
} else
return "NaN";
} catch (NumberFormatException e) {
Log.e("CPU-toMHz", e.getMessage());
return "NaN";
}
}
// Read current frequency from /sys in a separate thread
protected class CurCPUThread extends Thread {
private boolean mInterrupt = false;
public void interrupt() {
mInterrupt = true;
}
@Override
public void run() {
try {
while (!mInterrupt) {
sleep(1000);
final String curFreq = CPUHelper.readOneLineNotRoot(GPUInterface.currFreq);
mCurCPUHandler.sendMessage(mCurCPUHandler.obtainMessage(0,
curFreq));
}
} catch (InterruptedException e) {
Log.e("GPU Thread", e.getMessage());
}
}
}
// Update real-time current frequency & stats in a separate thread
protected static Handler mCurCPUHandler = new Handler() {
public void handleMessage(Message msg) {
try {
mCurFreq.setText(toMHz((String) msg.obj));
currX += 1;
final int p = Integer.parseInt((String) msg.obj);
new Thread(new Runnable() {
public void run() {
counter++;
addStatPoint(currX, p, line, graph);
ArrayList<LinePoint> array = line.getPoints();
if (line.getSize() > 10)
array.remove(0);
line.setPoints(array);
// Reset the line every 50 updates of the current frequency
// to make-up for the lack of garbage collection in the
// HoloGraph pluggable
if (counter == 50) {
graph.removeAllLines();
line = new Line();
LinePoint point = new LinePoint();
point.setX(currX);
point.setY(1);
line.addPoint(point);
line.setColor(Color.parseColor("#FFBB33"));
graph.addLine(line);
counter = 0;
}
}
}).start();
} catch (NumberFormatException e) {
Log.e("GPUHandler", e.getMessage());
}
}
};
// Static method to add new point to the graph
public static void addStatPoint(int X, int Y, Line line, LineGraph graph) {
LinePoint point = new LinePoint();
point.setX(X);
point.setY(Y);
line.addPoint(point);
graph.addLine(line);
}
}