blob: 0be05aee20aa76ad9b4d6ba8dcbcd66eacffe602 [file] [log] [blame]
/*
* Copyright (C) 2011 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.ide.eclipse.gltrace;
import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage;
import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/** A class that streams data received from a socket into the trace file. */
public class TraceFileWriter {
private DataInputStream mInputStream;
private DataOutputStream mOutputStream;
private Thread mReceiverThread;
private int mFileSize = 0;
private int mFrameCount = 0;
/**
* Construct a trace file writer.
* @param fos output stream to write trace data to
* @param is input stream from which trace data is read
*/
public TraceFileWriter(FileOutputStream fos, DataInputStream is) {
mOutputStream = new DataOutputStream(fos);
mInputStream = is;
}
public void start() {
// launch thread
mReceiverThread = new Thread(new GLTraceReceiverTask());
mReceiverThread.setName("GL Trace Receiver");
mReceiverThread.start();
}
public void stopTracing() {
// close socket to stop the receiver thread
try {
mInputStream.close();
} catch (IOException e) {
// ignore exception while closing socket
}
// wait for receiver to complete
try {
mReceiverThread.join();
} catch (InterruptedException e1) {
// ignore, this cannot be interrupted
}
// close stream
try {
mOutputStream.close();
} catch (IOException e) {
// ignore error while closing stream
}
}
/**
* The GLTraceReceiverTask collects trace data from the device and writes it
* into a file while collecting some stats on the way.
*/
private class GLTraceReceiverTask implements Runnable {
@Override
public void run() {
while (true) {
byte[] buffer = readTraceData(mInputStream);
if (buffer == null) {
break;
}
try {
writeTraceData(buffer, mOutputStream);
} catch (IOException e) {
break;
}
updateTraceStats(buffer);
}
}
}
private byte[] readTraceData(DataInputStream dis) {
int len;
try {
len = dis.readInt();
} catch (IOException e1) {
return null;
}
len = Integer.reverseBytes(len); // readInt is big endian, we want little endian
byte[] buffer = new byte[len];
int readLen = 0;
while (readLen < len) {
try {
int read = dis.read(buffer, readLen, len - readLen);
if (read < 0) {
return null;
} else {
readLen += read;
}
} catch (IOException e) {
return null;
}
}
return buffer;
}
private void writeTraceData(byte[] buffer, DataOutputStream stream) throws IOException {
stream.writeInt(buffer.length);
stream.write(buffer);
}
private void updateTraceStats(byte[] buffer) {
GLMessage msg = null;
try {
msg = GLMessage.parseFrom(buffer);
} catch (InvalidProtocolBufferException e) {
return;
}
mFileSize += buffer.length;
if (msg.getFunction() == Function.eglSwapBuffers) {
mFrameCount++;
}
}
public int getCurrentFileSize() {
return mFileSize;
}
public int getCurrentFrameCount() {
return mFrameCount;
}
}