1bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondepackage com.android.bluetooth.tests;
2bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
3bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.io.IOException;
4bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.io.InputStream;
5bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport java.io.OutputStream;
6bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
7bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondeimport android.util.Log;
8bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
9bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bondepublic class ObexTestDataHandler {
10bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
11bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    final String TAG;
12bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    String TAG_BASE = "ObexTestDataHandler";
13bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    static final boolean V = true;
14bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
15bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private static final long PROGRESS_INTERVAL_MS = 1000;
16bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    int mBufferSize = 0;
17bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    int mThrottle = 0;
18bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    long mBytesToTransfer = 0;
19bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    long mBytesTransfered = 0;
20bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    long mStartTime = 0;
21bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    long mLastReport = 0;
22bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    IResultLogger mResults;
23bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
24bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public ObexTestDataHandler(String tag) {
25bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        TAG = TAG_BASE + tag;
26bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
27bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
28bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    /**
29bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * Call after a sleep to calculate the number of buffers to
30bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * send to match the throttle value.
31bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     *
32bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param bufferSize
33bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @param throttle
34bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     * @return the number of buffers to send, to match the throttle value
35bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde     */
36bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private int getNumberOfBuffers() {
37bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(mThrottle == 0) {
38bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            return 1;
39bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
40bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        long deltaT = System.currentTimeMillis() - mStartTime;
41bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        long deltaB = deltaT*mThrottle/1000; // the amount of bytes we should have sent
42bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        long bytesMissing = deltaB-mBytesTransfered;
43bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        return (int)((bytesMissing+(mBufferSize>>1))/mBufferSize); // Round result
44bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
45bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
46bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    private void publishProgressIfNeeded() {
47bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        long now = System.currentTimeMillis();
48bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if((now-mLastReport) > PROGRESS_INTERVAL_MS) {
49bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            mLastReport = now;
50bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            String result = "Avg: " + mResults.getAverageSpeed()/1024
51bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    + " Avg(1s): " + mResults.getAverageSpeed(1000)/1024 +
52bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    " mBytesTransfered: " + mBytesTransfered + "\n";
53bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            if(V) Log.v(TAG,result);
54bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
55bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
56bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
57bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public void readData(InputStream inStream, ObexTestParams params) {
58bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        /* TODO: parse in the step params
59bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         * Consider introducing a testStep prepare and wait for completion interface?
60bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde         * in stead of using OBEX headers to carry the index... */
61bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
62bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBufferSize = params.packageSize;
63bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mThrottle = params.throttle;
64bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBytesToTransfer = params.bytesToSend;
65bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBytesTransfered = 0;
66bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mResults = TestResultLogger.createLogger();
67bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mStartTime = System.currentTimeMillis();
68bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
69bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        byte[] buffer = new byte[params.packageSize];
70bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(V) Log.v(TAG, "readData() started data to read: " + params.bytesToSend);
71bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        try {
72bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            while(mBytesTransfered < mBytesToTransfer) {
73bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                int nRx = getNumberOfBuffers();
74bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                for(; nRx > 0 ; nRx--) {
75bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(V) Log.v(TAG, "Read()");
76bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    int count = inStream.read(buffer);
77bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(V) Log.v(TAG, "Read() done - count=" + count);
78bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(count == -1) {
79bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        throw new IOException("EOF reached too early mBytesTransfered=" + mBytesTransfered);
80bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
81bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mBytesTransfered += count;
82bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(mBytesTransfered >= mBytesToTransfer) {
83bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        nRx=0; // break
84bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
85bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mResults.addResult(mBytesTransfered);
86bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    publishProgressIfNeeded();
87bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
88bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if(mThrottle != 0) {
89bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    // Sleep one package of time.
90bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    try {
91bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        long sleepTime = (1000*mBufferSize)/mThrottle;
92bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        if(V) Log.v(TAG, "Throttle Sleep():" + sleepTime);
93bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        Thread.sleep(sleepTime);
94bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    } catch (InterruptedException e) {
95bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        // Just ignore as the getNumberOfBuffersToSend will compensate
96bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        // TODO: Handle Abort
97bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
98bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
99bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
100bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
101bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        catch(IOException e) {
102bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Log.e(TAG, "Error in readData():",e);
103bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            } finally {
104bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
105bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
106bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
107bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    public void writeData(OutputStream outStream, ObexTestParams params) {
108bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBufferSize = params.packageSize;
109bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mThrottle = params.throttle;
110bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBytesToTransfer= params.bytesToSend;
111bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mBytesTransfered = 0;
112bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mResults = TestResultLogger.createLogger();
113bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        mStartTime = System.currentTimeMillis();
114bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
115bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        byte[] buffer = new byte[params.packageSize];
116bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if(V) Log.v(TAG, "writeData() started data to write: " + params.bytesToSend);
117bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        try {
118bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            while(mBytesTransfered < mBytesToTransfer) {
119bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                int nTx = getNumberOfBuffers();
120bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if(V) Log.v(TAG, "Write nTx " + nTx + " packets");
121bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                for(; nTx > 0 ; nTx--) {
122bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(V) Log.v(TAG, "Write()");
123bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if((mBytesTransfered + mBufferSize) < mBytesToTransfer) {
124bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        outStream.write(buffer);
125bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        mBytesTransfered += mBufferSize;
126bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    } else {
127bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        outStream.write(buffer, 0, (int) (mBytesToTransfer-mBytesTransfered));
128bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        mBytesTransfered += mBytesToTransfer-mBytesTransfered;
129bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        nTx = 0;
130bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
131bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    mResults.addResult(mBytesTransfered);
132bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    publishProgressIfNeeded();
133bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    if(V) Log.v(TAG, "Write mBytesTransfered: " + mBytesTransfered);
134bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
135bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                if(mThrottle != 0) {
136bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    // Sleep one package of time.
137bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    try {
138bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        long sleepTime = (1000*mBufferSize)/mThrottle;
139bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        if(V) Log.v(TAG, "Throttle Sleep():" + sleepTime);
140bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        Thread.sleep(sleepTime);
141bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    } catch (InterruptedException e) {
142bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        // Just ignore as the getNumberOfBuffersToSend will compensate
143bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                        // TODO: Handle Abort
144bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                    }
145bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
146bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde                }
147bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde
148bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            }
149bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
150bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        catch(IOException e) {
151bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde            Log.e(TAG, "Error in ListenTask:",e);
152bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        }
153bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde    }
154bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde}
155