1package com.android.bluetooth.tests;
2
3import java.util.ArrayList;
4
5/**
6 * Class for collecting test results, and presenting them in different formats.
7 * @author cbonde
8 *
9 */
10public class TestResultLogger implements IResultLogger {
11
12    private ArrayList<Result> mResults;
13
14    private class Result {
15        public long timeStamp; // ms precision Unix Time UTC.
16        public long receivedBytes;
17        public Result(long t, long b) {
18            timeStamp = t;
19            receivedBytes = b;
20        }
21    }
22
23    private TestResultLogger() {
24        mResults = new ArrayList<Result>(1000);
25    }
26
27    public static IResultLogger createLogger(){
28        return new TestResultLogger();
29    }
30
31    @Override
32    public void addResult(long bytesTransfered) {
33        mResults.add(new Result(System.currentTimeMillis(), bytesTransfered));
34    }
35
36    @Override
37    public int getAverageSpeed() {
38        if(mResults.size() < 1){
39            return 0;
40        }
41        Result first = mResults.get(0);
42        Result last = mResults.get(mResults.size()-1);
43        // Multiply by 1000 to convert from ms to sec without loss
44        // of precision.
45        return (int) ((1000*(last.receivedBytes + first.receivedBytes))/
46                (last.timeStamp - first.timeStamp+1));
47    }
48
49    /**
50     * Optimized to perform best when period is closest to the last
51     * result entry.
52     * If the period does not match a log entry, an estimate will be made
53     * to compensate.
54     * If the result log does not contain data to cover the entire period
55     * the resulting value will represent the average speed of the content
56     * in the log.
57     */
58    @Override
59    public int getAverageSpeed(long period) {
60        Result preFirst = null;
61        Result first = mResults.get(0);
62        int i = mResults.size()-1;
63        Result last = mResults.get(i--);
64        long firstTimeStamp = last.timeStamp - period;
65        if(first.timeStamp > firstTimeStamp || mResults.size() < 3) {
66            // Not enough data, use total average
67            return getAverageSpeed();
68        }
69        for(; i >= 0 ; i--) {
70            preFirst = mResults.get(i);
71            if(preFirst.timeStamp < firstTimeStamp) {
72                first = mResults.get(i+1);
73                break;
74            }
75        }
76        long timeError = period - (last.timeStamp-first.timeStamp);
77        long errorBytes = 0;
78        if(timeError > 0) {
79            // Find the amount of bytes to use for correction
80            errorBytes = (timeError*(preFirst.receivedBytes - first.receivedBytes))
81                            /(preFirst.timeStamp - first.timeStamp+1);
82        }
83        // Calculate the result
84        return (int) ((1000*(errorBytes+last.receivedBytes-first.receivedBytes))/period);
85    }
86
87
88}
89