/* ** Copyright 2007, 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 static com.android.internal.util.CharSequences.forAsciiBytes; import java.io.DataInputStream; import java.io.IOException; import java.io.FileOutputStream; import java.net.Socket; import android.app.Activity; import android.os.Handler; import android.os.Bundle; import android.util.Log; import android.graphics.Typeface; import android.view.Gravity; /** * Views the device log. */ public class LogViewer extends Activity { static final String TAG = LogViewer.class.getSimpleName(); FileOutputStream logger; volatile boolean active = true; Handler handler; LogTextBox text; @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.log_viewer); this.handler = new Handler(); text = (LogTextBox) findViewById(R.id.text); text.setTextSize(10); text.setHorizontallyScrolling(true); text.setTypeface(Typeface.MONOSPACE); text.setGravity(Gravity.BOTTOM | Gravity.LEFT); this.active = true; try { logger = new FileOutputStream("/tmp/logviewer.txt"); new Thread(new LogReader()).start(); } catch (IOException e) { appendThrowable(e); } } private void appendThrowable(Throwable t) { StringBuilder builder = new StringBuilder(); builder.append("Error reading log: "); builder.append(Log.getStackTraceString(t)); text.getText().append(builder); } private class LogReader implements Runnable { final Socket socket; final DataInputStream in; StringBuilder builder = new StringBuilder(); long lastTime = System.currentTimeMillis(); private static final int HEADER_SIZE = 24; public LogReader() throws IOException { this.socket = new Socket("127.0.0.1", 5040); this.in = new DataInputStream(this.socket.getInputStream()); // Write two newlines to indicate "no reader args" this.socket.getOutputStream().write('\n'); this.socket.getOutputStream().write('\n'); } public void run() { while (active) { try { while (in.available() > 0) { logger.write("Reading message.\n".getBytes()); int length = in.readInt(); byte[] bytes = new byte[length]; in.readFully(bytes); int tagEnd = next0(bytes, HEADER_SIZE); int fileEnd = next0(bytes, tagEnd + 1); int messageEnd = next0(bytes, fileEnd + 1); CharSequence tag = forAsciiBytes(bytes, HEADER_SIZE, tagEnd); CharSequence message = forAsciiBytes(bytes, fileEnd + 1, messageEnd); builder.append(tag) .append(": ") .append(message) .append("\n"); } logger.write("Updating UI.\n".getBytes()); handler.post(new AppendCharacters(builder)); builder = new StringBuilder(); try { Thread.sleep(1000); } catch (InterruptedException e) {} } catch (final IOException e) { handler.post(new AppendThrowable(e)); } } } } static int next0(byte[] bytes, int start) { for (int current = start; current < bytes.length; current++) { if (bytes[current] == 0) return current; } return bytes.length; } private class AppendThrowable implements Runnable { private final Throwable t; public AppendThrowable(Throwable t) { this.t = t; } public void run() { appendThrowable(t); } } private class AppendCharacters implements Runnable { private final CharSequence message; public AppendCharacters(CharSequence message) { this.message = message; } public void run() { text.getText().append(message); // try { // logger.write(builder.toString().getBytes()); // } catch (IOException e) { // appendThrowable(e); // } } } }