1 /* 2 * Copyright (C) 2011 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.ide.eclipse.gltrace; 18 19 import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage; 20 import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function; 21 import com.google.protobuf.InvalidProtocolBufferException; 22 23 import java.io.DataInputStream; 24 import java.io.DataOutputStream; 25 import java.io.FileOutputStream; 26 import java.io.IOException; 27 28 /** A class that streams data received from a socket into the trace file. */ 29 public class TraceFileWriter { 30 private DataInputStream mInputStream; 31 private DataOutputStream mOutputStream; 32 private Thread mReceiverThread; 33 34 private int mFileSize = 0; 35 private int mFrameCount = 0; 36 37 /** 38 * Construct a trace file writer. 39 * @param fos output stream to write trace data to 40 * @param is input stream from which trace data is read 41 */ TraceFileWriter(FileOutputStream fos, DataInputStream is)42 public TraceFileWriter(FileOutputStream fos, DataInputStream is) { 43 mOutputStream = new DataOutputStream(fos); 44 mInputStream = is; 45 } 46 start()47 public void start() { 48 // launch thread 49 mReceiverThread = new Thread(new GLTraceReceiverTask()); 50 mReceiverThread.setName("GL Trace Receiver"); 51 mReceiverThread.start(); 52 } 53 stopTracing()54 public void stopTracing() { 55 // close socket to stop the receiver thread 56 try { 57 mInputStream.close(); 58 } catch (IOException e) { 59 // ignore exception while closing socket 60 } 61 62 // wait for receiver to complete 63 try { 64 mReceiverThread.join(); 65 } catch (InterruptedException e1) { 66 // ignore, this cannot be interrupted 67 } 68 69 // close stream 70 try { 71 mOutputStream.close(); 72 } catch (IOException e) { 73 // ignore error while closing stream 74 } 75 } 76 77 /** 78 * The GLTraceReceiverTask collects trace data from the device and writes it 79 * into a file while collecting some stats on the way. 80 */ 81 private class GLTraceReceiverTask implements Runnable { 82 @Override run()83 public void run() { 84 while (true) { 85 byte[] buffer = readTraceData(mInputStream); 86 if (buffer == null) { 87 break; 88 } 89 90 try { 91 writeTraceData(buffer, mOutputStream); 92 } catch (IOException e) { 93 break; 94 } 95 96 updateTraceStats(buffer); 97 } 98 } 99 } 100 readTraceData(DataInputStream dis)101 private byte[] readTraceData(DataInputStream dis) { 102 int len; 103 try { 104 len = dis.readInt(); 105 } catch (IOException e1) { 106 return null; 107 } 108 len = Integer.reverseBytes(len); // readInt is big endian, we want little endian 109 110 byte[] buffer = new byte[len]; 111 int readLen = 0; 112 while (readLen < len) { 113 try { 114 int read = dis.read(buffer, readLen, len - readLen); 115 if (read < 0) { 116 return null; 117 } else { 118 readLen += read; 119 } 120 } catch (IOException e) { 121 return null; 122 } 123 } 124 125 return buffer; 126 } 127 128 writeTraceData(byte[] buffer, DataOutputStream stream)129 private void writeTraceData(byte[] buffer, DataOutputStream stream) throws IOException { 130 stream.writeInt(buffer.length); 131 stream.write(buffer); 132 } 133 updateTraceStats(byte[] buffer)134 private void updateTraceStats(byte[] buffer) { 135 GLMessage msg = null; 136 try { 137 msg = GLMessage.parseFrom(buffer); 138 } catch (InvalidProtocolBufferException e) { 139 return; 140 } 141 142 mFileSize += buffer.length; 143 144 if (msg.getFunction() == Function.eglSwapBuffers) { 145 mFrameCount++; 146 } 147 } 148 getCurrentFileSize()149 public int getCurrentFileSize() { 150 return mFileSize; 151 } 152 getCurrentFrameCount()153 public int getCurrentFrameCount() { 154 return mFrameCount; 155 } 156 } 157