blob: 43eb5e7bf8f3a7a2122e087f0dad1740d4d64ae1 [file] [log] [blame]
/*
* Copyright (C) 2016 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 org.drrickorang.loopback;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Iterator;
/**
* Maintains and returns pairs of callback timestamps (in milliseconds since beginning of test) and
* lengths (milliseconds between a callback and the previous callback).
*/
public class BufferCallbackTimes implements Iterable<BufferCallbackTimes.BufferCallback>,
Parcelable {
private final int[] mTimeStamps;
private final short[] mCallbackDurations;
private final short mExpectedBufferPeriod;
private boolean mExceededCapacity;
private int mIndex;
public BufferCallbackTimes(int maxRecords, int expectedBufferPeriod) {
mIndex = 0;
mTimeStamps = new int[maxRecords];
mCallbackDurations = new short[maxRecords];
mExceededCapacity = false;
mExpectedBufferPeriod = (short) expectedBufferPeriod;
}
/**
* Instantiates an iterable object with already recorded callback times and lengths
* used for callbacks recorded by native sles callback functions.
*
* exceededCapacity should be set to true only when there were late callbacks observed but
* unable to be recorded because allocated arrays were already at capacity
*/
public BufferCallbackTimes(int[] timeStamps, short[] callbackDurations,
boolean exceededCapacity, short expectedBufferPeriod) {
mTimeStamps = timeStamps;
mCallbackDurations = callbackDurations;
mExceededCapacity = exceededCapacity;
mIndex = mTimeStamps.length;
mExpectedBufferPeriod = expectedBufferPeriod;
}
/** Record the length of a late/early callback and the time it occurred. Used by Java Thread. */
public void recordCallbackTime(int timeStamp, short callbackLength) {
if (!mExceededCapacity && callbackLength != mExpectedBufferPeriod
&& callbackLength != mExpectedBufferPeriod + 1) {
//only marked as exceeded if attempting to record a late callback after arrays full
if (mIndex == mTimeStamps.length) {
mExceededCapacity = true;
return;
}
mTimeStamps[mIndex] = timeStamp;
mCallbackDurations[mIndex] = callbackLength;
mIndex++;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (BufferCallback callback : this) {
sb.append(callback.timeStamp);
sb.append(",");
sb.append(callback.callbackDuration);
sb.append("\n");
}
return sb.toString();
}
// True only if arrays are full and recording more late or early callbacks is attempted.
public boolean isCapacityExceeded() {
return mExceededCapacity;
}
public int getNumLateOrEarlyCallbacks() {
return mIndex;
}
public short getExpectedBufferPeriod() {
return mExpectedBufferPeriod;
}
@Override
public Iterator<BufferCallback> iterator() {
return new Iterator<BufferCallback>() {
int mIteratorIndex = 0;
@Override
public boolean hasNext() {
return mIteratorIndex < mIndex;
}
@Override
public BufferCallback next() {
return new BufferCallback(mTimeStamps[mIteratorIndex],
mCallbackDurations[mIteratorIndex++]);
}
@Override
public void remove() {
throw new UnsupportedOperationException("Buffer Time Stamps are Immutable");
}
};
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
Bundle out = new Bundle();
out.putIntArray("mTimeStamps", mTimeStamps);
out.putShortArray("mCallbackDurations", mCallbackDurations);
out.putShort("mExpectedBufferPeriod", mExpectedBufferPeriod);
out.putBoolean("mExceededCapacity", mExceededCapacity);
out.putInt("mIndex", mIndex);
dest.writeBundle(out);
}
private BufferCallbackTimes(Parcel source) {
Bundle in = source.readBundle(getClass().getClassLoader());
mTimeStamps = in.getIntArray("mTimeStamps");
mCallbackDurations = in.getShortArray("mCallbackDurations");
mExpectedBufferPeriod = in.getShort("mExpectedBufferPeriod");
mExceededCapacity = in.getBoolean("mExceededCapacity");
mIndex = in.getInt("mIndex");
}
public static final Parcelable.Creator<BufferCallbackTimes> CREATOR
= new Parcelable.Creator<BufferCallbackTimes>() {
public BufferCallbackTimes createFromParcel(Parcel in) {
return new BufferCallbackTimes(in);
}
public BufferCallbackTimes[] newArray(int size) {
return new BufferCallbackTimes[size];
}
};
/** Wrapper for iteration over timestamp and length pairs */
public class BufferCallback {
public final int timeStamp;
public final short callbackDuration;
BufferCallback(final int ts, final short cd) {
timeStamp = ts;
callbackDuration = cd;
}
}
}