PageRenderTime 38ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/net/androcom/dev/speakerproximity/log/SendLogActivity.java

http://speakerproximity.googlecode.com/
Java | 416 lines | 294 code | 53 blank | 69 comment | 51 complexity | 903ef6a45781aa2a6d921807ad3c0e49 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * Copyright (C) 2009 Xtralogic, Inc.
  18. *
  19. * Licensed under the Apache License, Version 2.0 (the "License");
  20. * you may not use this file except in compliance with the License.
  21. * You may obtain a copy of the License at
  22. *
  23. * http://www.apache.org/licenses/LICENSE-2.0
  24. *
  25. * Unless required by applicable law or agreed to in writing, software
  26. * distributed under the License is distributed on an "AS IS" BASIS,
  27. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  28. * See the License for the specific language governing permissions and
  29. * limitations under the License.
  30. */
  31. package net.androcom.dev.speakerproximity.log;
  32. import java.io.BufferedReader;
  33. import java.io.FileReader;
  34. import java.io.IOException;
  35. import java.io.InputStreamReader;
  36. import java.util.ArrayList;
  37. import java.util.regex.Matcher;
  38. import java.util.regex.Pattern;
  39. import net.androcom.dev.speakerproximity.R;
  40. import android.app.Activity;
  41. import android.app.AlertDialog;
  42. import android.app.ProgressDialog;
  43. import android.content.Context;
  44. import android.content.DialogInterface;
  45. import android.content.Intent;
  46. import android.content.pm.PackageInfo;
  47. import android.content.pm.PackageManager;
  48. import android.net.Uri;
  49. import android.os.AsyncTask;
  50. import android.os.Build;
  51. import android.os.Bundle;
  52. import android.util.Log;
  53. public class SendLogActivity extends Activity
  54. {
  55. public final static String TAG = "SpeakerProximityLog";//$NON-NLS-1$
  56. public static final String ACTION_SEND_LOG = "net.androcom.dev.speakerproximity.log.intent.action.SEND_LOG";//$NON-NLS-1$
  57. public static final String EXTRA_SEND_INTENT_ACTION = "net.androcom.dev.speakerproximity.log.intent.extra.SEND_INTENT_ACTION";//$NON-NLS-1$
  58. public static final String EXTRA_DATA = "net.androcom.dev.speakerproximity.log.intent.extra.DATA";//$NON-NLS-1$
  59. public static final String EXTRA_ADDITIONAL_INFO = "net.androcom.dev.speakerproximity.log.intent.extra.ADDITIONAL_INFO";//$NON-NLS-1$
  60. public static final String EXTRA_SHOW_UI = "net.androcom.dev.speakerproximity.log.intent.extra.SHOW_UI";//$NON-NLS-1$
  61. public static final String EXTRA_FILTER_SPECS = "net.androcom.dev.speakerproximity.log.intent.extra.FILTER_SPECS";//$NON-NLS-1$
  62. public static final String EXTRA_FORMAT = "net.androcom.dev.speakerproximity.log.intent.extra.FORMAT";//$NON-NLS-1$
  63. public static final String EXTRA_BUFFER = "net.androcom.dev.speakerproximity.log.intent.extra.BUFFER";//$NON-NLS-1$
  64. final int MAX_LOG_MESSAGE_LENGTH = 100000;
  65. private AlertDialog mMainDialog;
  66. private Intent mSendIntent;
  67. private CollectLogTask mCollectLogTask;
  68. private ProgressDialog mProgressDialog;
  69. private String mAdditonalInfo;
  70. private boolean mShowUi;
  71. private String[] mFilterSpecs;
  72. private String mFormat;
  73. private String mBuffer;
  74. @Override
  75. public void onCreate(Bundle savedInstanceState){
  76. super.onCreate(savedInstanceState);
  77. mSendIntent = null;
  78. Intent intent = getIntent();
  79. if (null != intent){
  80. String action = intent.getAction();
  81. if (ACTION_SEND_LOG.equals(action)){
  82. String extraSendAction = intent.getStringExtra(EXTRA_SEND_INTENT_ACTION);
  83. if (extraSendAction == null){
  84. Log.e(TAG, "Quiting, EXTRA_SEND_INTENT_ACTION is not supplied");//$NON-NLS-1$
  85. finish();
  86. return;
  87. }
  88. mSendIntent = new Intent(extraSendAction);
  89. Uri data = (Uri)intent.getParcelableExtra(EXTRA_DATA);
  90. if (data != null){
  91. mSendIntent.setData(data);
  92. }
  93. String[] emails = intent.getStringArrayExtra(Intent.EXTRA_EMAIL);
  94. if (emails != null){
  95. mSendIntent.putExtra(Intent.EXTRA_EMAIL, emails);
  96. }
  97. String[] ccs = intent.getStringArrayExtra(Intent.EXTRA_CC);
  98. if (ccs != null){
  99. mSendIntent.putExtra(Intent.EXTRA_CC, ccs);
  100. }
  101. String[] bccs = intent.getStringArrayExtra(Intent.EXTRA_BCC);
  102. if (bccs != null){
  103. mSendIntent.putExtra(Intent.EXTRA_BCC, bccs);
  104. }
  105. String subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
  106. if (subject != null){
  107. mSendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
  108. }
  109. mAdditonalInfo = intent.getStringExtra(EXTRA_ADDITIONAL_INFO);
  110. mShowUi = intent.getBooleanExtra(EXTRA_SHOW_UI, false);
  111. mFilterSpecs = intent.getStringArrayExtra(EXTRA_FILTER_SPECS);
  112. mFormat = intent.getStringExtra(EXTRA_FORMAT);
  113. mBuffer = intent.getStringExtra(EXTRA_BUFFER);
  114. }
  115. }
  116. if (null == mSendIntent){
  117. //standalone application
  118. mShowUi = true;
  119. mSendIntent = new Intent(Intent.ACTION_SEND);
  120. mSendIntent.putExtra(Intent.EXTRA_SUBJECT, "SpeakerProximity Android device log");
  121. mSendIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"rac2030+SpeakerProximity@gmail.com"});
  122. mSendIntent.setType("text/plain");//$NON-NLS-1$
  123. mAdditonalInfo = "SpeakerProximityVersion: " + getVersionNumber(this) + "\n"
  124. + "Device model: " + Build.MODEL + "\n"
  125. + "Firmware version: " + Build.VERSION.RELEASE + "\n"
  126. + "Kernel version: " + getFormattedKernelVersion() + "\n"
  127. + "Build number: " + Build.DISPLAY + "\n";
  128. mFormat = "time";
  129. }
  130. if (mShowUi){
  131. mMainDialog = new AlertDialog.Builder(this)
  132. .setTitle(getString(R.string.app_name))
  133. .setMessage("This will collect all logs related to SpeakerProximity")
  134. .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
  135. public void onClick(DialogInterface dialog, int whichButton){
  136. collectAndSendLog();
  137. }
  138. })
  139. .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener(){
  140. public void onClick(DialogInterface dialog, int whichButton){
  141. finish();
  142. }
  143. })
  144. .show();
  145. }
  146. else{
  147. collectAndSendLog();
  148. }
  149. }
  150. @SuppressWarnings("unchecked")
  151. void collectAndSendLog(){
  152. /*Usage: logcat [options] [filterspecs]
  153. options include:
  154. -s Set default filter to silent.
  155. Like specifying filterspec '*:s'
  156. -f <filename> Log to file. Default to stdout
  157. -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f
  158. -n <count> Sets max number of rotated logs to <count>, default 4
  159. -v <format> Sets the log print format, where <format> is one of:
  160. brief process tag thread raw time threadtime long
  161. -c clear (flush) the entire log and exit
  162. -d dump the log and then exit (don't block)
  163. -g get the size of the log's ring buffer and exit
  164. -b <buffer> request alternate ring buffer
  165. ('main' (default), 'radio', 'events')
  166. -B output the log in binary
  167. filterspecs are a series of
  168. <tag>[:priority]
  169. where <tag> is a log component tag (or * for all) and priority is:
  170. V Verbose
  171. D Debug
  172. I Info
  173. W Warn
  174. E Error
  175. F Fatal
  176. S Silent (supress all output)
  177. '*' means '*:d' and <tag> by itself means <tag>:v
  178. If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
  179. If no filterspec is found, filter defaults to '*:I'
  180. If not specified with -v, format is set from ANDROID_PRINTF_LOG
  181. or defaults to "brief"*/
  182. ArrayList<String> list = new ArrayList<String>();
  183. if (mFormat != null){
  184. list.add("-v");
  185. list.add(mFormat);
  186. }
  187. if (mBuffer != null){
  188. list.add("-b");
  189. list.add(mBuffer);
  190. }
  191. if (mFilterSpecs != null){
  192. for (String filterSpec : mFilterSpecs){
  193. list.add(filterSpec);
  194. }
  195. }
  196. mCollectLogTask = (CollectLogTask) new CollectLogTask().execute(list);
  197. }
  198. private class CollectLogTask extends AsyncTask<ArrayList<String>, Void, StringBuilder>{
  199. @Override
  200. protected void onPreExecute(){
  201. showProgressDialog("Acquiring log from the system...");
  202. }
  203. @Override
  204. protected StringBuilder doInBackground(ArrayList<String>... params){
  205. final StringBuilder log = new StringBuilder();
  206. try{
  207. ArrayList<String> commandLine = new ArrayList<String>();
  208. commandLine.add("logcat");//$NON-NLS-1$
  209. commandLine.add("-d");//$NON-NLS-1$
  210. ArrayList<String> arguments = ((params != null) && (params.length > 0)) ? params[0] : null;
  211. if (null != arguments){
  212. commandLine.addAll(arguments);
  213. }
  214. Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
  215. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
  216. String line;
  217. while ((line = bufferedReader.readLine()) != null){
  218. if(line.contains("SpeakerProximity")) {
  219. log.append(line);
  220. log.append(System.getProperty("line.separator"));
  221. }
  222. }
  223. }
  224. catch (IOException e){
  225. Log.e(TAG, "CollectLogTask.doInBackground failed", e);//$NON-NLS-1$
  226. }
  227. return log;
  228. }
  229. @Override
  230. protected void onPostExecute(StringBuilder log){
  231. if (null != log){
  232. //truncate if necessary
  233. int keepOffset = Math.max(log.length() - MAX_LOG_MESSAGE_LENGTH, 0);
  234. if (keepOffset > 0){
  235. log.delete(0, keepOffset);
  236. }
  237. if (mAdditonalInfo != null){
  238. log.insert(0, System.getProperty("line.separator"));
  239. log.insert(0, mAdditonalInfo);
  240. }
  241. mSendIntent.putExtra(Intent.EXTRA_TEXT, log.toString());
  242. startActivity(Intent.createChooser(mSendIntent, "Select an application to send the log"));
  243. dismissProgressDialog();
  244. dismissMainDialog();
  245. finish();
  246. }
  247. else{
  248. dismissProgressDialog();
  249. showErrorDialog("Failed to get the log from the system.");
  250. }
  251. }
  252. }
  253. void showErrorDialog(String errorMessage){
  254. new AlertDialog.Builder(this)
  255. .setTitle(getString(R.string.app_name))
  256. .setMessage(errorMessage)
  257. .setIcon(android.R.drawable.ic_dialog_alert)
  258. .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
  259. public void onClick(DialogInterface dialog, int whichButton){
  260. finish();
  261. }
  262. })
  263. .show();
  264. }
  265. void dismissMainDialog(){
  266. if (null != mMainDialog && mMainDialog.isShowing()){
  267. mMainDialog.dismiss();
  268. mMainDialog = null;
  269. }
  270. }
  271. void showProgressDialog(String message){
  272. mProgressDialog = new ProgressDialog(this);
  273. mProgressDialog.setIndeterminate(true);
  274. mProgressDialog.setMessage(message);
  275. mProgressDialog.setCancelable(true);
  276. mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){
  277. public void onCancel(DialogInterface dialog){
  278. cancellCollectTask();
  279. finish();
  280. }
  281. });
  282. mProgressDialog.show();
  283. }
  284. private void dismissProgressDialog(){
  285. if (null != mProgressDialog && mProgressDialog.isShowing())
  286. {
  287. mProgressDialog.dismiss();
  288. mProgressDialog = null;
  289. }
  290. }
  291. void cancellCollectTask(){
  292. if (mCollectLogTask != null && mCollectLogTask.getStatus() == AsyncTask.Status.RUNNING)
  293. {
  294. mCollectLogTask.cancel(true);
  295. mCollectLogTask = null;
  296. }
  297. }
  298. @Override
  299. protected void onPause(){
  300. cancellCollectTask();
  301. dismissProgressDialog();
  302. dismissMainDialog();
  303. super.onPause();
  304. }
  305. private static String getVersionNumber(Context context)
  306. {
  307. String version = "?";
  308. try
  309. {
  310. PackageInfo packagInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
  311. version = packagInfo.versionName;
  312. }
  313. catch (PackageManager.NameNotFoundException e){};
  314. return version;
  315. }
  316. private String getFormattedKernelVersion()
  317. {
  318. String procVersionStr;
  319. try {
  320. BufferedReader reader = new BufferedReader(new FileReader("/proc/version"), 256);
  321. try {
  322. procVersionStr = reader.readLine();
  323. } finally {
  324. reader.close();
  325. }
  326. final String PROC_VERSION_REGEX =
  327. "\\w+\\s+" + /* ignore: Linux */
  328. "\\w+\\s+" + /* ignore: version */
  329. "([^\\s]+)\\s+" + /* group 1: 2.6.22-omap1 */
  330. "\\(([^\\s@]+(?:@[^\\s.]+)?)[^)]*\\)\\s+" + /* group 2: (xxxxxx@xxxxx.constant) */
  331. "\\([^)]+\\)\\s+" + /* ignore: (gcc ..) */
  332. "([^\\s]+)\\s+" + /* group 3: #26 */
  333. "(?:PREEMPT\\s+)?" + /* ignore: PREEMPT (optional) */
  334. "(.+)"; /* group 4: date */
  335. Pattern p = Pattern.compile(PROC_VERSION_REGEX);
  336. Matcher m = p.matcher(procVersionStr);
  337. if (!m.matches()) {
  338. Log.e(TAG, "Regex did not match on /proc/version: " + procVersionStr);
  339. return "Unavailable";
  340. } else if (m.groupCount() < 4) {
  341. Log.e(TAG, "Regex match on /proc/version only returned " + m.groupCount()
  342. + " groups");
  343. return "Unavailable";
  344. } else {
  345. return (new StringBuilder(m.group(1)).append("\n").append(
  346. m.group(2)).append(" ").append(m.group(3)).append("\n")
  347. .append(m.group(4))).toString();
  348. }
  349. } catch (IOException e) {
  350. Log.e(TAG,
  351. "IO Exception when getting kernel version for Device Info screen",
  352. e);
  353. return "Unavailable";
  354. }
  355. }
  356. }