FileDocCategorySizeDatePackage
RadioIssueReport.javaAPI DocAndroid 1.5 API6260Wed May 06 22:41:08 BST 2009com.android.development

RadioIssueReport.java

/*
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

package com.android.development;

import android.app.Activity;
import android.os.Bundle;
import android.os.SystemProperties;
import android.provider.Checkin;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import android.telephony.ServiceState;
import android.text.format.DateFormat;
import static com.android.internal.util.CharSequences.forAsciiBytes;
import android.util.Log;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.google.android.collect.Maps;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Map;

/**
 * Report radio issues to the StatisticsService.
 */
public class RadioIssueReport extends Activity
{
    private static final String TAG = "RadioIssue";
    private static final int HEADER_SIZE = 24;
    private static final String RADIO_BUFFER_OPTIONS = "-b radio\n-d\n";

    /** List of system properties to snapshot. */
    private static String[] SYSTEM_PROPERTIES = {
        "net.gsm.radio-reset",
        "net.gsm.attempt-gprs",
        "net.gsm.succeed-gprs",
        "net.gsm.disconnect",
        "net.ppp.sent",
        "net.ppp.received",
        "gsm.version.baseband",
        "gsm.version.ril-impl",
    };

    private Button          mSubmitButton;
    private EditText        mReportText;
    private ServiceState mServiceState;
    private Phone.State     mPhoneState;
    private int             mSignalStrength;
    private Phone.DataState mDataState;
    private String          mRadioLog;

    /** Snapshot of interesting variables relevant to the radio. */
    private Map<String, String> mRadioState;

    @Override
    public void
    onCreate(Bundle icicle) {
        super.onCreate(icicle);

        setContentView(R.layout.radio_issue);

        initSubmitButton();
        initReportText();

        mRadioState = snapState();
    }

    /**
     * @return a snapshot of phone state variables to report.
     */
    private static Map<String, String> snapState() {
        Map<String, String> state = Maps.newHashMap();

        // Capture a bunch of system properties
        for (String property: SYSTEM_PROPERTIES) {
            String value = SystemProperties.get(property);
            state.put(property, SystemProperties.get(property));
        }

        Phone phone = PhoneFactory.getDefaultPhone();
        state.put("phone-data", phone.getDataConnectionState().toString());
        state.put("phone-service", phone.getServiceState().toString());
        state.put("phone-signal", String.valueOf(phone.getSignalStrengthASU()));
        state.put("phone-state", phone.getState().toString());

        try {
            state.put("radio-log", getRadioLog());
        } catch (IOException e) {
            Log.e(TAG, "Error reading radio log", e);
        }

        return state;
    }

    private void initSubmitButton() {
        mSubmitButton = (Button) findViewById(R.id.submit);
        mSubmitButton.setOnClickListener(mSubmitButtonHandler);
    }

    private void initReportText() {
        mReportText = (EditText) findViewById(R.id.report_text);
        mReportText.requestFocus();
    }

    OnClickListener mSubmitButtonHandler = new OnClickListener() {
        public void onClick(View v) {
            // Include the user-supplied report text.
            mRadioState.put("user-report", mReportText.getText().toString());

            // Dump the state variables directly into the report.
            Checkin.logEvent(getContentResolver(),
                    Checkin.Events.Tag.RADIO_BUG_REPORT,
                    mRadioState.toString());

            finish();
        }
    };

    // Largely stolen from LogViewer.java
    private static String getRadioLog() throws IOException {
        Socket sock = new Socket("127.0.0.1", 5040);
        DataInputStream in = new DataInputStream(sock.getInputStream());
        StringBuilder log = new StringBuilder();

        // Set options
        sock.getOutputStream().write(RADIO_BUFFER_OPTIONS.getBytes());
        sock.getOutputStream().write('\n');
        sock.getOutputStream().write('\n');

        // Read in the log
        try {
            Calendar cal = new GregorianCalendar();

            while (true) {
                int length = in.readInt();
                long when = (long)in.readInt();
                byte[] bytes = new byte[length-4];
                in.readFully(bytes);

                int tagEnd = next0(bytes, HEADER_SIZE-4);
                int fileEnd = next0(bytes, tagEnd + 1);
                int messageEnd = next0(bytes, fileEnd + 1);

                CharSequence tag
                        = forAsciiBytes(bytes, HEADER_SIZE-4, tagEnd);
                CharSequence message
                        = forAsciiBytes(bytes, fileEnd + 1, messageEnd);

                cal.setTimeInMillis(when*1000);
                log.append(DateFormat.format("MM-dd kk:mm:ss ", cal));
                log.append(tag)
                   .append(": ")
                   .append(message)
                   .append("\n");
            }
        } catch (EOFException e) {
            Log.d(TAG, "reached end of stream");
        }

        return log.toString();
    }

    private static int next0(byte[] bytes, int start) {
        for (int current = start; current < bytes.length; current++) {
            if (bytes[current] == 0)
                return current;
        }
        return bytes.length;
    }
}