Skip to content

Commit

Permalink
Added: add setting options: collect heap data, require root permission
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewleo committed Feb 12, 2015
1 parent fd1ebf2 commit d815347
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 33 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
##Emmagee - a practical, handy performance test tool for specified Android App

Emmagee is a practical, handy performance test tool for specified Android App, which can monitor CPU, memory,
network traffic, battery current and status([Some devices are not supported](https://github.com/NetEase/Emmagee/wiki/Some-devices-are-not-supported)). Additionally, it also provides several cool features such as customizing interval of collecting data,
network traffic, battery current and status([Some devices are not supported](https://github.com/NetEase/Emmagee/wiki/Some-devices-are-not-supported)), new features such as top activity and heap size if rooted([Root Toast may continously show](https://github.com/NetEase/Emmagee/wiki/FAQ)), are also supported in the [latest version](https://github.com/NetEase/Emmagee/releases). Additionally, it also provides several cool features such as customizing interval of collecting data,
rendering real-time process status in a floating window, and much more.

* Homepage: https://github.com/NetEase/Emmagee
* Wiki: https://github.com/NetEase/Emmagee/wiki
* Issues: https://github.com/NetEase/Emmagee/issues
* FAQ: https://github.com/NetEase/Emmagee/wiki/FAQ
* Tags: Android, Java

<img src="https://github.com/andrewleo/pictures/blob/master/Emmagee/V2.0/homepage.png" width="180px" />
Expand Down
51 changes: 45 additions & 6 deletions res/layout/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@
android:layout_width="50sp"
android:layout_height="wrap_content"
android:gravity="center_vertical|right"
android:textSize="@dimen/text_size"
android:textColor="@color/black" >
android:textColor="@color/black"
android:textSize="@dimen/text_size" >
</TextView>
</LinearLayout>
</LinearLayout>
Expand All @@ -72,9 +72,9 @@
android:max="59"
android:maxHeight="4.0dip"
android:minHeight="4.0dip"
android:paddingBottom="@dimen/layout_vertical_margin_small"
android:paddingLeft="16.0dip"
android:paddingRight="16.0dip"
android:paddingBottom="@dimen/layout_vertical_margin_small"
android:progress="5"
android:progressDrawable="@drawable/custom_seekbar"
android:thumb="@drawable/seekbar_thumb" />
Expand Down Expand Up @@ -107,10 +107,49 @@
android:background="@drawable/custom_checkbox"
android:button="@null"
android:checked="true"
android:paddingRight="@dimen/image_padding"
android:paddingLeft="@dimen/image_padding" />

android:paddingLeft="@dimen/image_padding"
android:paddingRight="@dimen/image_padding" />
</RelativeLayout>

<LinearLayout
android:id="@+id/heap_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/layout_vertical_margin_small" >

<TextView
android:id="@+id/collect_heap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/collect_heap"
android:textColor="@color/black"
android:textSize="@dimen/text_size" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/root_notification"
android:textColor="@color/gray"
android:textSize="@dimen/text_size" />

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right" >

<CheckBox
android:id="@+id/is_root"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@drawable/custom_checkbox"
android:button="@null"
android:checked="false"
android:gravity="right"
android:paddingLeft="@dimen/image_padding"
android:paddingRight="@dimen/image_padding" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

<LinearLayout
Expand Down
8 changes: 8 additions & 0 deletions res/values-zh-rCN/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,12 @@

<string name="top_activity">栈顶Activity名称</string>
<string name="csv_encoding">GBK</string>

<string name="dalvik_heap">Dalvik heap alloc/size(KB)</string>
<string name="native_heap">Native heap alloc/size(KB)</string>

<string name="collect_heap">统计Heap数据</string>
<string name="root_notification">(需要root)</string>

<string name="root_failed_notification">无法获取root权限,请确认手机是否已经root过</string>
</resources>
6 changes: 6 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,10 @@

<string name="top_activity">Top Activity Name</string>
<string name="csv_encoding">UTF-8</string>
<string name="dalvik_heap">Dalvik heap alloc/size(KB)</string>
<string name="native_heap">Native heap alloc/size(KB)</string>

<string name="collect_heap">Collect Heap</string>
<string name="root_notification">(root is necessary)</string>
<string name="root_failed_notification">Fail to get root permission, please check if this phone is rooted</string>
</resources>
15 changes: 13 additions & 2 deletions src/com/netease/qa/emmagee/activity/MainPageActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package com.netease.qa.emmagee.activity;

import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;

Expand All @@ -31,13 +32,22 @@
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.*;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;

import com.netease.qa.emmagee.R;
import com.netease.qa.emmagee.service.EmmageeService;
import com.netease.qa.emmagee.utils.ProcessInfo;
import com.netease.qa.emmagee.utils.Programe;
import com.netease.qa.emmagee.R;

/**
* Main Page of Emmagee
Expand Down Expand Up @@ -71,6 +81,7 @@ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.mainpage);

initTitleLayout();
processInfo = new ProcessInfo();
btnTest.setOnClickListener(new OnClickListener() {
Expand Down
83 changes: 78 additions & 5 deletions src/com/netease/qa/emmagee/activity/SettingsActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
*/
package com.netease.qa.emmagee.activity;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
Expand All @@ -31,6 +36,7 @@
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.netease.qa.emmagee.R;
import com.netease.qa.emmagee.utils.Settings;
Expand All @@ -42,14 +48,15 @@
*/
public class SettingsActivity extends Activity {

private static final String LOG_TAG = "Emmagee-" + SettingsActivity.class.getSimpleName();
private static final String LOG_TAG = "Emmagee-" + SettingsActivity.class.getSimpleName();

private CheckBox chkFloat;
private CheckBox chkRoot;
private TextView tvTime;
private LinearLayout about;
private LinearLayout mailSettings;

private SharedPreferences preferences;
private SharedPreferences preferences;

@Override
public void onCreate(Bundle savedInstanceState) {
Expand All @@ -59,21 +66,27 @@ public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.settings);

chkFloat = (CheckBox) findViewById(R.id.floating);
chkRoot = (CheckBox) findViewById(R.id.is_root);
tvTime = (TextView) findViewById(R.id.time);
about = (LinearLayout) findViewById(R.id.about);
mailSettings = (LinearLayout) findViewById(R.id.mail_settings);
SeekBar timeBar = (SeekBar) findViewById(R.id.timeline);
ImageView btnSave = (ImageView) findViewById(R.id.btn_set);
RelativeLayout floatingItem = (RelativeLayout) findViewById(R.id.floating_item);
LinearLayout layGoBack = (LinearLayout) findViewById(R.id.lay_go_back);
LinearLayout layHeapItem = (LinearLayout) findViewById(R.id.heap_item);

btnSave.setVisibility(ImageView.INVISIBLE);

preferences = Settings.getDefaultSharedPreferences(getApplicationContext());
int interval = preferences.getInt(Settings.KEY_INTERVAL, 5);
boolean isfloat = preferences.getBoolean(Settings.KEY_ISFLOAT, true);

boolean isRoot = preferences.getBoolean(Settings.KEY_ROOT, false);

tvTime.setText(String.valueOf(interval));
chkFloat.setChecked(isfloat);
chkRoot.setChecked(isRoot);

timeBar.setProgress(interval);
timeBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
Expand Down Expand Up @@ -124,8 +137,34 @@ public void onClick(View arg0) {
floatingItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
chkFloat.setChecked(!chkFloat.isChecked());
preferences.edit().putBoolean(Settings.KEY_ISFLOAT, chkFloat.isChecked()).commit();
boolean isChecked = chkFloat.isChecked();
chkFloat.setChecked(!isChecked);
preferences.edit().putBoolean(Settings.KEY_ISFLOAT, !isChecked).commit();
}
});

// get root permission
layHeapItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// if root checkbox is checked, change status to
// opposite;otherwise, try to upgrade app to root
boolean isChecked = chkRoot.isChecked();
if (isChecked) {
chkRoot.setChecked(!isChecked);
preferences.edit().putBoolean(Settings.KEY_ROOT, !isChecked).commit();
} else {
boolean root = upgradeRootPermission(getPackageCodePath());
if (root) {
Log.d(LOG_TAG, "root succeed");
chkRoot.setChecked(!isChecked);
preferences.edit().putBoolean(Settings.KEY_ROOT, !isChecked).commit();
} else {
// if root failed, tell user to check if phone is rooted
Toast.makeText(getBaseContext(), getString(R.string.root_failed_notification), Toast.LENGTH_LONG).show();
}
}

}
});
}
Expand All @@ -140,4 +179,38 @@ protected void onDestroy() {
super.onDestroy();
}

/**
* upgrade app to get root permission
*
* @return is root successfully
*/
public static boolean upgradeRootPermission(String pkgCodePath) {
Process process = null;
DataOutputStream os = null;
try {
String cmd = "chmod 777 " + pkgCodePath;
process = Runtime.getRuntime().exec("su"); // 切换到root帐号
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(cmd + "\n");
os.writeBytes("exit\n");
os.flush();
int existValue = process.waitFor();
if (existValue == 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
Log.w(LOG_TAG, "upgradeRootPermission exception=" + e.getMessage());
return false;
} finally {
try {
if (os != null) {
os.close();
}
process.destroy();
} catch (Exception e) {
}
}
}
}
24 changes: 14 additions & 10 deletions src/com/netease/qa/emmagee/service/EmmageeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public class EmmageeService extends Service {
private Handler handler = new Handler();
private CpuInfo cpuInfo;
private boolean isFloating;
private boolean isRoot;
private String processName, packageName, startActivity;
private int pid, uid;
private boolean isServiceStop = false;
Expand Down Expand Up @@ -231,6 +232,7 @@ private void readSettingInfo() {
recipients = preferences.getString(Settings.KEY_RECIPIENTS, BLANK_STRING);
receivers = recipients.split("\\s+");
smtp = preferences.getString(Settings.KEY_SMTP, BLANK_STRING);
isRoot = preferences.getBoolean(Settings.KEY_ROOT, false);
}

/**
Expand All @@ -240,6 +242,7 @@ private void createResultCsv() {
Calendar cal = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
String mDateTime;
String heapData = "";
if ((Build.MODEL.equals("sdk")) || (Build.MODEL.equals("google_sdk")))
mDateTime = formatter.format(cal.getTime().getTime() + 8 * 60 * 60 * 1000);
else
Expand All @@ -257,7 +260,7 @@ private void createResultCsv() {
File resultFile = new File(resultFilePath);
resultFile.createNewFile();
out = new FileOutputStream(resultFile);
osw = new OutputStreamWriter(out, getString(R.string.csv_encoding));
osw = new OutputStreamWriter(out);
bw = new BufferedWriter(osw);
long totalMemorySize = memoryInfo.getTotalMemory();
String totalMemory = fomart.format((double) totalMemorySize / 1024);
Expand All @@ -277,7 +280,10 @@ private void createResultCsv() {
if (isGrantedReadLogsPermission()) {
bw.write(START_TIME);
}
bw.write(getString(R.string.timestamp) + Constants.COMMA + getString(R.string.top_activity) + Constants.COMMA
if(isRoot){
heapData = getString(R.string.native_heap) + Constants.COMMA+getString(R.string.dalvik_heap) + Constants.COMMA;
}
bw.write(getString(R.string.timestamp) + Constants.COMMA + getString(R.string.top_activity) + Constants.COMMA+heapData
+ getString(R.string.used_mem_PSS) + Constants.COMMA + getString(R.string.used_mem_ratio) + Constants.COMMA
+ getString(R.string.mobile_free_mem) + Constants.COMMA + getString(R.string.app_used_cpu_ratio) + Constants.COMMA
+ getString(R.string.total_used_cpu_ratio) + multiCpuTitle + Constants.COMMA + getString(R.string.traffic) + Constants.COMMA
Expand Down Expand Up @@ -439,7 +445,7 @@ private void dataRefresh() {
} catch (Exception e) {
currentBatt = Constants.NA;
}
ArrayList<String> processInfo = cpuInfo.getCpuRatioInfo(totalBatt, currentBatt, temperature, voltage);
ArrayList<String> processInfo = cpuInfo.getCpuRatioInfo(totalBatt, currentBatt, temperature, voltage,isRoot);
if (isFloating) {
String processCpuRatio = "0.00";
String totalCpuRatio = "0.00";
Expand Down Expand Up @@ -521,12 +527,10 @@ public void onDestroy() {
handler.removeCallbacks(task);
closeOpenedStream();
// replace the start time in file
if (isGrantedReadLogsPermission()) {
if (!BLANK_STRING.equals(startTime)) {
replaceFileString(resultFilePath, START_TIME, getString(R.string.start_time) + startTime + Constants.LINE_END);
} else {
replaceFileString(resultFilePath, START_TIME, BLANK_STRING);
}
if (!BLANK_STRING.equals(startTime)) {
replaceFileString(resultFilePath, START_TIME, getString(R.string.start_time) + startTime + Constants.LINE_END);
} else {
replaceFileString(resultFilePath, START_TIME, BLANK_STRING);
}
isStop = true;
unregisterReceiver(batteryBroadcast);
Expand Down Expand Up @@ -566,7 +570,7 @@ private void replaceFileString(String filePath, String replaceType, String repla
reader.close();
// replace a word in a file
String newtext = oldtext.replaceAll(replaceType, replaceString);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), "UTF-8"));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath), getString(R.string.csv_encoding)));
writer.write(newtext);
writer.close();
} catch (IOException e) {
Expand Down
Loading

0 comments on commit d815347

Please sign in to comment.