1/* 2** Copyright 2007, 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 17package com.android.development; 18 19import static com.android.internal.util.CharSequences.forAsciiBytes; 20 21import java.io.DataInputStream; 22import java.io.IOException; 23import java.io.FileOutputStream; 24import java.net.Socket; 25 26import android.app.Activity; 27import android.os.Handler; 28import android.os.Bundle; 29import android.util.Log; 30import android.graphics.Typeface; 31import android.view.Gravity; 32 33/** 34 * Views the device log. 35 */ 36public class LogViewer extends Activity { 37 38 static final String TAG = LogViewer.class.getSimpleName(); 39 40 FileOutputStream logger; 41 42 volatile boolean active = true; 43 Handler handler; 44 LogTextBox text; 45 46 @Override 47 protected void onCreate(Bundle icicle) { 48 super.onCreate(icicle); 49 setContentView(R.layout.log_viewer); 50 this.handler = new Handler(); 51 52 text = (LogTextBox) findViewById(R.id.text); 53 54 text.setTextSize(10); 55 text.setHorizontallyScrolling(true); 56 text.setTypeface(Typeface.MONOSPACE); 57 text.setGravity(Gravity.BOTTOM | Gravity.LEFT); 58 59 this.active = true; 60 try { 61 logger = new FileOutputStream("/tmp/logviewer.txt"); 62 new Thread(new LogReader()).start(); 63 } catch (IOException e) { 64 appendThrowable(e); 65 } 66 } 67 68 private void appendThrowable(Throwable t) { 69 StringBuilder builder = new StringBuilder(); 70 builder.append("Error reading log: "); 71 builder.append(Log.getStackTraceString(t)); 72 text.getText().append(builder); 73 } 74 75 private class LogReader implements Runnable { 76 77 final Socket socket; 78 final DataInputStream in; 79 StringBuilder builder = new StringBuilder(); 80 long lastTime = System.currentTimeMillis(); 81 82 private static final int HEADER_SIZE = 24; 83 84 public LogReader() throws IOException { 85 this.socket = new Socket("127.0.0.1", 5040); 86 this.in = new DataInputStream(this.socket.getInputStream()); 87 // Write two newlines to indicate "no reader args" 88 this.socket.getOutputStream().write('\n'); 89 this.socket.getOutputStream().write('\n'); 90 } 91 92 public void run() { 93 while (active) { 94 try { 95 while (in.available() > 0) { 96 logger.write("Reading message.\n".getBytes()); 97 98 int length = in.readInt(); 99 byte[] bytes = new byte[length]; 100 in.readFully(bytes); 101 102 int tagEnd = next0(bytes, HEADER_SIZE); 103 int fileEnd = next0(bytes, tagEnd + 1); 104 int messageEnd = next0(bytes, fileEnd + 1); 105 106 CharSequence tag 107 = forAsciiBytes(bytes, HEADER_SIZE, tagEnd); 108 CharSequence message 109 = forAsciiBytes(bytes, fileEnd + 1, messageEnd); 110 111 builder.append(tag) 112 .append(": ") 113 .append(message) 114 .append("\n"); 115 } 116 117 logger.write("Updating UI.\n".getBytes()); 118 handler.post(new AppendCharacters(builder)); 119 builder = new StringBuilder(); 120 121 try { 122 Thread.sleep(1000); 123 } catch (InterruptedException e) {} 124 } catch (final IOException e) { 125 handler.post(new AppendThrowable(e)); 126 } 127 } 128 } 129 } 130 131 static int next0(byte[] bytes, int start) { 132 for (int current = start; current < bytes.length; current++) { 133 if (bytes[current] == 0) 134 return current; 135 } 136 return bytes.length; 137 } 138 139 private class AppendThrowable implements Runnable { 140 141 private final Throwable t; 142 143 public AppendThrowable(Throwable t) { 144 this.t = t; 145 } 146 147 public void run() { 148 appendThrowable(t); 149 } 150 } 151 152 private class AppendCharacters implements Runnable { 153 154 private final CharSequence message; 155 156 public AppendCharacters(CharSequence message) { 157 this.message = message; 158 } 159 160 public void run() { 161 text.getText().append(message); 162// try { 163// logger.write(builder.toString().getBytes()); 164// } catch (IOException e) { 165// appendThrowable(e); 166// } 167 } 168 } 169} 170