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 
17 package com.android.development;
18 
19 import static com.android.internal.util.CharSequences.forAsciiBytes;
20 
21 import java.io.DataInputStream;
22 import java.io.IOException;
23 import java.io.FileOutputStream;
24 import java.net.Socket;
25 
26 import android.app.Activity;
27 import android.os.Handler;
28 import android.os.Bundle;
29 import android.util.Log;
30 import android.graphics.Typeface;
31 import android.view.Gravity;
32 
33 /**
34  * Views the device log.
35  */
36 public 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
onCreate(Bundle icicle)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 
appendThrowable(Throwable t)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 
LogReader()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 
run()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 
next0(byte[] bytes, int start)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 
AppendThrowable(Throwable t)143         public AppendThrowable(Throwable t) {
144             this.t = t;
145         }
146 
run()147         public void run() {
148             appendThrowable(t);
149         }
150     }
151 
152     private class AppendCharacters implements Runnable {
153 
154         private final CharSequence message;
155 
AppendCharacters(CharSequence message)156         public AppendCharacters(CharSequence message) {
157             this.message = message;
158         }
159 
run()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