package com.aero.control.fragments; import android.app.Fragment; import android.content.Context; import android.graphics.Point; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import com.aero.control.AeroActivity; import com.aero.control.R; import com.aero.control.adapter.AeroAdapter; import com.aero.control.adapter.AeroData; import com.aero.control.helpers.FilePath; import com.github.amlcurran.showcaseview.ShowcaseView; import com.github.amlcurran.showcaseview.targets.Target; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import fr.nicolaspomepuy.discreetapprate.AppRate; /** * Created by Alexander Christ on 16.09.13. * Default Overview Fragment * */ public class AeroFragment extends Fragment { private ListView mOverView; private ViewGroup root; private AeroAdapter mAdapter; private List<AeroData> mOverviewData = new ArrayList<AeroData>(); private ShowcaseView mShowCase; private int mActionBarHeight = 0; private boolean mVisible = true; private boolean mExecuted = false; private final static String FILENAME = "firstrun"; private final static String NO_DATA_FOUND = "Unavailable"; private final static String SCALE_CUR_FILE = "/sys/devices/system/cpu/cpu"; private final static String SCALE_PATH_NAME = "/cpufreq/scaling_cur_freq"; private final static String SCALE_CPU_UTIL = "/cpufreq/cpu_utilization"; private String gpu_file; private AeroData mKernelData; private AeroData mGovernorData; private AeroData mIOSchedulerData; private AeroData mFrequencyData; private AeroData mGPUData; private AeroData mRAMData; private class RefreshThread extends Thread { private boolean mInterrupt = false; public void interrupt() { mInterrupt = true; } @Override public void run() { try { while (!mInterrupt) { sleep(1000); mRefreshHandler.sendEmptyMessage(1); } } catch (InterruptedException e) {} } } private RefreshThread mRefreshThread = new RefreshThread(); private Handler mRefreshHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what >= 1) { if (isVisible() && mVisible) { createList(); mVisible = true; } } } }; @Override public void onPause() { super.onPause(); mVisible = false; } @Override public void onResume() { super.onResume(); mVisible = true; // onPause we need to reset our adapter; mAdapter = null; } // Override for custom view; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { root = (ViewGroup) inflater.inflate(R.layout.overviewlist_item, null); /* * Start the refresh Thread at startup; */ mOverView = (ListView) root.findViewById(R.id.listView1); /* Find correct gpu path */ for (String a : FilePath.GPU_FILES_RATE) { if (AeroActivity.genHelper.doesExist(a)) { gpu_file = a; break; } } if (!mRefreshThread.isAlive()) { mRefreshThread.start(); mRefreshThread.setPriority(Thread.MIN_PRIORITY); } // Generate our main ListView; createList(); if (!mExecuted) setPermissions(); AppRate.with(getActivity()) .text(R.string.rateIt) .fromTop(false) .delay(2000) .autoHide(10000) .allowPlayLink(true) .checkAndShow(); return root; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Set up our file; int output = 0; if (AeroActivity.genHelper.doesExist(getActivity().getFilesDir().getAbsolutePath() + "/" + FILENAME)) { output = 1; } // Only show showcase once; if (output == 0) DrawFirstStart(R.string.showcase_aero_fragment, R.string.showcase_aero_fragment_sum); } // Get all frequencies for all cores; public final String getFreqPerCore() { String complete_path; String freq_string = ""; String cpu_util = ""; final int i = Runtime.getRuntime().availableProcessors(); // Get the cpu frequency for each cpu; for (int k = 0; k < i; k++) { complete_path = SCALE_CUR_FILE + k + SCALE_PATH_NAME; freq_string = freq_string + " " + AeroActivity.shell.toMHz(AeroActivity.shell.getInfo(complete_path)); } freq_string = freq_string.replace(NO_DATA_FOUND, " Offline "); // There is no point in wasting cpu cycles if no file exists; if (!(AeroActivity.genHelper.doesExist(SCALE_CUR_FILE + 0 + SCALE_CPU_UTIL))) return freq_string; // Get the last reported load for each cpu (if available); for (int j = 0; j < i; j++) { complete_path = SCALE_CUR_FILE + j + SCALE_CPU_UTIL; String tmp = AeroActivity.shell.getInfo(complete_path); if (!tmp.equals(NO_DATA_FOUND)) { try { if (Integer.parseInt(tmp.trim()) < 10) { tmp = " " + tmp; } } catch (NumberFormatException e) { // If we encounter a NFE, we assume its 0. // Its not clean, but this case should never happen. tmp = "0"; } } cpu_util = cpu_util + "\t\t\t" + tmp + "%"; } cpu_util = cpu_util.replace(NO_DATA_FOUND + "%", "--"); freq_string = freq_string + "\n" + cpu_util; return freq_string; } private String getCPUTemp() { String tmp; if (AeroActivity.genHelper.doesExist(FilePath.CPU_TEMP_FILE)) { tmp = AeroActivity.shell.getInfo(FilePath.CPU_TEMP_FILE); if (tmp.length() > 2) { tmp = tmp.substring(0, 2); } return tmp + " °C"; } else { return null; } } private void fillData(String gpu_freq) { if (mKernelData == null) mKernelData = new AeroData(getString(R.string.kernel_version), AeroActivity.shell.getKernel(), null); else { mKernelData.content = AeroActivity.shell.getKernel(); } if (mGovernorData == null) mGovernorData = new AeroData(getString(R.string.current_governor), AeroActivity.shell.getInfo(FilePath.GOV_FILE), null); else { mGovernorData.content = AeroActivity.shell.getInfo(FilePath.GOV_FILE); } if (mIOSchedulerData == null) mIOSchedulerData = new AeroData(getString(R.string.current_io_governor), AeroActivity.shell.getInfo(FilePath.GOV_IO_FILE), null); else { mIOSchedulerData.content = AeroActivity.shell.getInfo(FilePath.GOV_IO_FILE); } if (mFrequencyData == null) mFrequencyData = new AeroData(getString(R.string.current_cpu_speed), getFreqPerCore(), getCPUTemp()); else { mFrequencyData.content = getFreqPerCore(); mFrequencyData.right_name = getCPUTemp(); } if (mGPUData == null) mGPUData = new AeroData(getString(R.string.current_gpu_speed), AeroActivity.shell.toMHz((gpu_freq.substring(0, gpu_freq.length() - 3))), null); else { mGPUData.content = AeroActivity.shell.toMHz((gpu_freq.substring(0, gpu_freq.length() - 3))); } if (mRAMData == null) mRAMData = new AeroData(getString(R.string.available_memory), AeroActivity.shell.getMemory(FilePath.FILENAME_PROC_MEMINFO), null); else { mRAMData.content = AeroActivity.shell.getMemory(FilePath.FILENAME_PROC_MEMINFO); } } public void createList() { String gpu_freq; /* * Cleanup all data, if there are any; */ if (mOverviewData != null) { mOverviewData.clear(); } if (mAdapter != null) { mAdapter.clear(); mAdapter.notifyDataSetChanged(); } gpu_freq = AeroActivity.shell.getInfo(gpu_file); if (gpu_freq.length() <= 3) gpu_freq = NO_DATA_FOUND; fillData(gpu_freq); // Default Overview Menu mOverviewData.add(mKernelData); mOverviewData.add(mGovernorData); mOverviewData.add(mIOSchedulerData); mOverviewData.add(mFrequencyData); mOverviewData.add(mGPUData); mOverviewData.add(mRAMData); if (mAdapter == null) { /* * Create our ArrayAdapter and bound it to our listview. * Notice; we can only set our Adapter if it is freshly new, * otherwise we can just fall through and execute a * notifyDataSetChange() of our Adapter in the main UI Thread. */ mAdapter = new AeroAdapter(getActivity(), R.layout.overviewlist_item, mOverviewData); mOverView.setAdapter(mAdapter); } else { getActivity().runOnUiThread(new Runnable() { @Override public void run() { mAdapter.notifyDataSetChanged(); } }); } } public void DrawFirstStart(int header, int content) { try { final FileOutputStream fos = getActivity().openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write("1".getBytes()); fos.close(); } catch (IOException e) { Log.e("Aero", "Could not save file. ", e); } TypedValue tv = new TypedValue(); if (getActivity().getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) { mActionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics()); } Target homeTarget = new Target() { @Override public Point getPoint() { return new Point(100, mActionBarHeight); } }; mShowCase = new ShowcaseView.Builder(getActivity()) .setContentTitle(header) .setContentText(content) .setTarget(homeTarget) .build(); } public void setPermissions() { final String[] commands = new String[] { "chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", }; AeroActivity.shell.setRootInfo(commands); mExecuted = true; } }