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