142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor/*
242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * Copyright (C) 2009 The Android Open Source Project
342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor *
442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * Licensed under the Apache License, Version 2.0 (the "License");
542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * you may not use this file except in compliance with the License.
642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * You may obtain a copy of the License at
742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor *
842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor *      http://www.apache.org/licenses/LICENSE-2.0
942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor *
1042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * Unless required by applicable law or agreed to in writing, software
1142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * distributed under the License is distributed on an "AS IS" BASIS,
1242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * See the License for the specific language governing permissions and
1442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * limitations under the License.
1542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor */
1642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
1742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorpackage com.android.bugreportsender;
1842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
1942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.app.ListActivity;
2042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.content.Intent;
2142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.net.Uri;
2242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.os.Build;
2342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.os.Bundle;
2442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.os.FileObserver;
2542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.os.Handler;
2642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.util.Log;
2742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.view.ContextMenu;
2842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.view.MenuItem;
2942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.view.View;
3042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.widget.AdapterView;
3142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.widget.ArrayAdapter;
3242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport android.widget.ListView;
3342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
3442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport java.io.File;
3542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport java.util.ArrayList;
3642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport java.util.Arrays;
3742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport java.util.Collections;
3842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorimport java.util.HashMap;
3942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
4042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor/**
4142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor * Shows a list of bug reports currently in /sdcard/bugreports
4242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor */
4342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnorpublic class BugReportListActivity extends ListActivity {
4442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final String TAG = "BugReportListActivity";
4542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final File REPORT_DIR = new File("/sdcard/bugreports");
4642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final int SYSTEM_LOG_ID = 1;
4742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final int MEMORY_ID = 2;
4842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final int CPU_ID = 3;
4942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final int PROCRANK_ID = 4;
5042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private static final HashMap<Integer, String> ID_MAP = new HashMap<Integer, String>();
5142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
5242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    static {
5342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        ID_MAP.put(SYSTEM_LOG_ID, "SYSTEM LOG");
5442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        ID_MAP.put(MEMORY_ID, "MEMORY INFO");
5542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        ID_MAP.put(CPU_ID, "CPU INFO");
5642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        ID_MAP.put(PROCRANK_ID, "PROCRANK");
5742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
5842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
5942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private ArrayAdapter<String> mAdapter = null;
6042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private ArrayList<File> mFiles = null;
6142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private Handler mHandler = null;
6242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private FileObserver mObserver = null;
6342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
6442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
6542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    public void onCreate(Bundle savedInstanceState) {
6642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        super.onCreate(savedInstanceState);
6742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
6842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mFiles = new ArrayList<File>();
6942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mHandler = new Handler();
7042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
7142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        int flags = FileObserver.CREATE | FileObserver.MOVED_TO;
7242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mObserver = new FileObserver(REPORT_DIR.getPath(), flags) {
7342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            public void onEvent(int event, String path) {
7442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                mHandler.post(new Runnable() { public void run() { scanDirectory(); } });
7542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            }
7642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        };
7742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
7842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        setListAdapter(mAdapter);
7942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        registerForContextMenu(getListView());
8042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
8142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
8242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
8342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    public void onCreateContextMenu(ContextMenu menu, View v,
8442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                                    ContextMenu.ContextMenuInfo menuInfo) {
8542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        super.onCreateContextMenu(menu, v, menuInfo);
8642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        menu.add(0, SYSTEM_LOG_ID, 0, "System Log");
8742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        menu.add(0, CPU_ID, 0, "CPU Info");
8842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        menu.add(0, MEMORY_ID, 0, "Memory Info");
8942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        menu.add(0, PROCRANK_ID, 0, "Procrank");
9042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
9142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
9242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
9342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    public void onStart() {
9442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        super.onStart();
9542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mObserver.startWatching();
9642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        scanDirectory();
9742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
9842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
9942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
10042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    public void onStop() {
10142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        super.onStop();
10242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mObserver.stopWatching();
10342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
10442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
10542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
10642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    protected void onListItemClick(ListView l, View v, int position, long id) {
10742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        super.onListItemClick(l, v, position, id);
10842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        if (position < mFiles.size()) {
10942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            File file = mFiles.get(position);
11042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            Intent intent = new Intent(Intent.ACTION_SEND);
11142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            intent.putExtra("subject", file.getName());
11242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            intent.putExtra("body", "Build: " + Build.DISPLAY + "\n(Sent by BugReportSender)");
11342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
11442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            if (file.getName().endsWith(".gz")) {
11542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                intent.setType("application/x-gzip");
11642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            } else if (file.getName().endsWith(".txt")) {
11742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                intent.setType("text/plain");
11842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            } else {
11942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                intent.setType("application/octet-stream");
12042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            }
12142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            startActivity(intent);
12242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        }
12342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
12442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
12542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
12642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    @Override
12742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    public boolean onContextItemSelected(MenuItem item) {
12842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      AdapterView.AdapterContextMenuInfo info =
12942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor              (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
13042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      if (info.position >= mFiles.size()) {
13142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        return true;
13242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      }
13342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      int id = item.getItemId();
13442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      switch (id) {
13542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          case SYSTEM_LOG_ID: // drop down
13642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          case MEMORY_ID:     // drop down
13742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          case CPU_ID:        // drop down
13842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          case PROCRANK_ID:
13942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          File file = mFiles.get(info.position);
14042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          Intent intent = new Intent(Intent.ACTION_VIEW);
14142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          intent.setDataAndType(Uri.fromFile(file), "vnd.android/bugreport");
14242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          intent.putExtra("section", ID_MAP.get(id));
14342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          startActivity(intent);
14442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor          return true;
14542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      default:
14642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        return super.onContextItemSelected(item);
14742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor      }
14842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
14942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
15042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    private void scanDirectory() {
15142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mAdapter.clear();
15242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        mFiles.clear();
15342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
15442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        File[] files = REPORT_DIR.listFiles();
15542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        if (files == null) return;
15642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
15742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        // Sort in reverse order: newest bug reports first
15842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        Arrays.sort(files, Collections.reverseOrder());
15942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        for (int i = 0; i < files.length; i++) {
16042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            String name = files[i].getName();
16142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            if (name.endsWith(".gz")) name = name.substring(0, name.length() - 3);
16242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            if (!name.startsWith("bugreport-") || !name.endsWith(".txt")) {
16342d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                Log.w(TAG, "Ignoring non-bugreport: " + files[i]);
16442d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor                continue;
16542d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            }
16642d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor
16742d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            // Make sure to keep the parallel arrays in sync
16842d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            mAdapter.add(name.substring(10, name.length() - 4));
16942d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor            mFiles.add(files[i]);
17042d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor        }
17142d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor    }
17242d06bed6b57fba4dfc58400f34cbbb3fd274b42Dan Egnor}
173