- Added realracing3-community.apk (71.57 MB) - Removed 32-bit support (armeabi-v7a) - Only includes arm64-v8a libraries - Decompiled source code included - Added README-community.md with analysis
508 lines
17 KiB
Java
508 lines
17 KiB
Java
package com.singular.sdk.internal;
|
|
|
|
import android.support.v4.media.session.PlaybackStateCompat;
|
|
import com.ironsource.v8;
|
|
import csdk.gluads.Consts;
|
|
import java.io.Closeable;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.RandomAccessFile;
|
|
import java.nio.channels.FileChannel;
|
|
import java.util.ConcurrentModificationException;
|
|
import java.util.Iterator;
|
|
import java.util.NoSuchElementException;
|
|
import kotlin.jvm.internal.ByteCompanionObject;
|
|
|
|
/* loaded from: classes4.dex */
|
|
public final class QueueFile implements Closeable, Iterable {
|
|
public static final byte[] ZEROES = new byte[4096];
|
|
public final byte[] buffer;
|
|
public boolean closed;
|
|
public int elementCount;
|
|
public final File file;
|
|
public long fileLength;
|
|
public Element first;
|
|
public int headerLength;
|
|
public Element last;
|
|
public int modCount = 0;
|
|
public final RandomAccessFile raf;
|
|
public boolean versioned;
|
|
public final boolean zero;
|
|
|
|
public boolean isEmpty() {
|
|
return this.elementCount == 0;
|
|
}
|
|
|
|
public int size() {
|
|
return this.elementCount;
|
|
}
|
|
|
|
public long wrapPosition(long j) {
|
|
long j2 = this.fileLength;
|
|
return j < j2 ? j : (this.headerLength + j) - j2;
|
|
}
|
|
|
|
public static RandomAccessFile initializeFromFile(File file, boolean z) {
|
|
if (!file.exists()) {
|
|
File file2 = new File(file.getPath() + ".tmp");
|
|
RandomAccessFile open = open(file2);
|
|
try {
|
|
open.setLength(PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM);
|
|
open.seek(0L);
|
|
if (z) {
|
|
open.writeInt(4096);
|
|
} else {
|
|
open.writeInt(-2147483647);
|
|
open.writeLong(PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM);
|
|
}
|
|
open.close();
|
|
if (!file2.renameTo(file)) {
|
|
throw new IOException("Rename failed!");
|
|
}
|
|
} catch (Throwable th) {
|
|
open.close();
|
|
throw th;
|
|
}
|
|
}
|
|
return open(file);
|
|
}
|
|
|
|
public static RandomAccessFile open(File file) {
|
|
return new RandomAccessFile(file, "rwd");
|
|
}
|
|
|
|
public QueueFile(File file, RandomAccessFile randomAccessFile, boolean z, boolean z2) {
|
|
long readInt;
|
|
long j;
|
|
byte[] bArr = new byte[32];
|
|
this.buffer = bArr;
|
|
this.file = file;
|
|
this.raf = randomAccessFile;
|
|
this.zero = z;
|
|
randomAccessFile.seek(0L);
|
|
randomAccessFile.readFully(bArr);
|
|
boolean z3 = (z2 || (bArr[0] & ByteCompanionObject.MIN_VALUE) == 0) ? false : true;
|
|
this.versioned = z3;
|
|
if (z3) {
|
|
this.headerLength = 32;
|
|
int readInt2 = readInt(bArr, 0) & Integer.MAX_VALUE;
|
|
if (readInt2 != 1) {
|
|
throw new IOException("Unable to read version " + readInt2 + " format. Supported versions are 1 and legacy.");
|
|
}
|
|
this.fileLength = readLong(bArr, 4);
|
|
this.elementCount = readInt(bArr, 12);
|
|
j = readLong(bArr, 16);
|
|
readInt = readLong(bArr, 24);
|
|
} else {
|
|
this.headerLength = 16;
|
|
this.fileLength = readInt(bArr, 0);
|
|
this.elementCount = readInt(bArr, 4);
|
|
long readInt3 = readInt(bArr, 8);
|
|
readInt = readInt(bArr, 12);
|
|
j = readInt3;
|
|
}
|
|
if (this.fileLength > randomAccessFile.length()) {
|
|
throw new IOException("File is truncated. Expected length: " + this.fileLength + ", Actual length: " + randomAccessFile.length());
|
|
}
|
|
if (this.fileLength <= this.headerLength) {
|
|
throw new IOException("File is corrupt; length stored in header (" + this.fileLength + ") is invalid.");
|
|
}
|
|
this.first = readElement(j);
|
|
this.last = readElement(readInt);
|
|
}
|
|
|
|
public static void writeInt(byte[] bArr, int i, int i2) {
|
|
bArr[i] = (byte) (i2 >> 24);
|
|
bArr[i + 1] = (byte) (i2 >> 16);
|
|
bArr[i + 2] = (byte) (i2 >> 8);
|
|
bArr[i + 3] = (byte) i2;
|
|
}
|
|
|
|
public static int readInt(byte[] bArr, int i) {
|
|
return ((bArr[i] & 255) << 24) + ((bArr[i + 1] & 255) << 16) + ((bArr[i + 2] & 255) << 8) + (bArr[i + 3] & 255);
|
|
}
|
|
|
|
public static void writeLong(byte[] bArr, int i, long j) {
|
|
bArr[i] = (byte) (j >> 56);
|
|
bArr[i + 1] = (byte) (j >> 48);
|
|
bArr[i + 2] = (byte) (j >> 40);
|
|
bArr[i + 3] = (byte) (j >> 32);
|
|
bArr[i + 4] = (byte) (j >> 24);
|
|
bArr[i + 5] = (byte) (j >> 16);
|
|
bArr[i + 6] = (byte) (j >> 8);
|
|
bArr[i + 7] = (byte) j;
|
|
}
|
|
|
|
public static long readLong(byte[] bArr, int i) {
|
|
return ((bArr[i] & 255) << 56) + ((bArr[i + 1] & 255) << 48) + ((bArr[i + 2] & 255) << 40) + ((bArr[i + 3] & 255) << 32) + ((bArr[i + 4] & 255) << 24) + ((bArr[i + 5] & 255) << 16) + ((bArr[i + 6] & 255) << 8) + (bArr[i + 7] & 255);
|
|
}
|
|
|
|
public final void writeHeader(long j, int i, long j2, long j3) {
|
|
this.raf.seek(0L);
|
|
if (this.versioned) {
|
|
writeInt(this.buffer, 0, -2147483647);
|
|
writeLong(this.buffer, 4, j);
|
|
writeInt(this.buffer, 12, i);
|
|
writeLong(this.buffer, 16, j2);
|
|
writeLong(this.buffer, 24, j3);
|
|
this.raf.write(this.buffer, 0, 32);
|
|
return;
|
|
}
|
|
writeInt(this.buffer, 0, (int) j);
|
|
writeInt(this.buffer, 4, i);
|
|
writeInt(this.buffer, 8, (int) j2);
|
|
writeInt(this.buffer, 12, (int) j3);
|
|
this.raf.write(this.buffer, 0, 16);
|
|
}
|
|
|
|
public Element readElement(long j) {
|
|
if (j == 0) {
|
|
return Element.NULL;
|
|
}
|
|
ringRead(j, this.buffer, 0, 4);
|
|
return new Element(j, readInt(this.buffer, 0));
|
|
}
|
|
|
|
public final void ringWrite(long j, byte[] bArr, int i, int i2) {
|
|
long wrapPosition = wrapPosition(j);
|
|
long j2 = i2 + wrapPosition;
|
|
long j3 = this.fileLength;
|
|
if (j2 <= j3) {
|
|
this.raf.seek(wrapPosition);
|
|
this.raf.write(bArr, i, i2);
|
|
return;
|
|
}
|
|
int i3 = (int) (j3 - wrapPosition);
|
|
this.raf.seek(wrapPosition);
|
|
this.raf.write(bArr, i, i3);
|
|
this.raf.seek(this.headerLength);
|
|
this.raf.write(bArr, i + i3, i2 - i3);
|
|
}
|
|
|
|
public final void ringErase(long j, long j2) {
|
|
while (j2 > 0) {
|
|
byte[] bArr = ZEROES;
|
|
int min = (int) Math.min(j2, bArr.length);
|
|
ringWrite(j, bArr, 0, min);
|
|
long j3 = min;
|
|
j2 -= j3;
|
|
j += j3;
|
|
}
|
|
}
|
|
|
|
public void ringRead(long j, byte[] bArr, int i, int i2) {
|
|
long wrapPosition = wrapPosition(j);
|
|
long j2 = i2 + wrapPosition;
|
|
long j3 = this.fileLength;
|
|
if (j2 <= j3) {
|
|
this.raf.seek(wrapPosition);
|
|
this.raf.readFully(bArr, i, i2);
|
|
return;
|
|
}
|
|
int i3 = (int) (j3 - wrapPosition);
|
|
this.raf.seek(wrapPosition);
|
|
this.raf.readFully(bArr, i, i3);
|
|
this.raf.seek(this.headerLength);
|
|
this.raf.readFully(bArr, i + i3, i2 - i3);
|
|
}
|
|
|
|
public void add(byte[] bArr, int i, int i2) {
|
|
long wrapPosition;
|
|
if (bArr == null) {
|
|
throw new NullPointerException("data == null");
|
|
}
|
|
if ((i | i2) < 0 || i2 > bArr.length - i) {
|
|
throw new IndexOutOfBoundsException();
|
|
}
|
|
if (this.closed) {
|
|
throw new IOException(Consts.PLACEMENT_STATUS_CLOSED);
|
|
}
|
|
expandIfNecessary(i2);
|
|
boolean isEmpty = isEmpty();
|
|
if (isEmpty) {
|
|
wrapPosition = this.headerLength;
|
|
} else {
|
|
wrapPosition = wrapPosition(this.last.position + 4 + r0.length);
|
|
}
|
|
Element element = new Element(wrapPosition, i2);
|
|
writeInt(this.buffer, 0, i2);
|
|
ringWrite(element.position, this.buffer, 0, 4);
|
|
ringWrite(element.position + 4, bArr, i, i2);
|
|
writeHeader(this.fileLength, this.elementCount + 1, isEmpty ? element.position : this.first.position, element.position);
|
|
this.last = element;
|
|
this.elementCount++;
|
|
this.modCount++;
|
|
if (isEmpty) {
|
|
this.first = element;
|
|
}
|
|
}
|
|
|
|
public final long usedBytes() {
|
|
if (this.elementCount == 0) {
|
|
return this.headerLength;
|
|
}
|
|
long j = this.last.position;
|
|
long j2 = this.first.position;
|
|
if (j >= j2) {
|
|
return (j - j2) + 4 + r0.length + this.headerLength;
|
|
}
|
|
return (((j + 4) + r0.length) + this.fileLength) - j2;
|
|
}
|
|
|
|
public final long remainingBytes() {
|
|
return this.fileLength - usedBytes();
|
|
}
|
|
|
|
public final void expandIfNecessary(long j) {
|
|
long j2;
|
|
long j3;
|
|
long j4 = j + 4;
|
|
long remainingBytes = remainingBytes();
|
|
if (remainingBytes >= j4) {
|
|
return;
|
|
}
|
|
long j5 = this.fileLength;
|
|
while (true) {
|
|
remainingBytes += j5;
|
|
j2 = j5 << 1;
|
|
if (remainingBytes >= j4) {
|
|
break;
|
|
} else {
|
|
j5 = j2;
|
|
}
|
|
}
|
|
setLength(j2);
|
|
long wrapPosition = wrapPosition(this.last.position + 4 + r2.length);
|
|
if (wrapPosition <= this.first.position) {
|
|
FileChannel channel = this.raf.getChannel();
|
|
channel.position(this.fileLength);
|
|
int i = this.headerLength;
|
|
j3 = wrapPosition - i;
|
|
if (channel.transferTo(i, j3, channel) != j3) {
|
|
throw new AssertionError("Copied insufficient number of bytes!");
|
|
}
|
|
} else {
|
|
j3 = 0;
|
|
}
|
|
long j6 = j3;
|
|
long j7 = this.last.position;
|
|
long j8 = this.first.position;
|
|
if (j7 < j8) {
|
|
long j9 = (this.fileLength + j7) - this.headerLength;
|
|
writeHeader(j2, this.elementCount, j8, j9);
|
|
this.last = new Element(j9, this.last.length);
|
|
} else {
|
|
writeHeader(j2, this.elementCount, j8, j7);
|
|
}
|
|
this.fileLength = j2;
|
|
if (this.zero) {
|
|
ringErase(this.headerLength, j6);
|
|
}
|
|
}
|
|
|
|
public final void setLength(long j) {
|
|
this.raf.setLength(j);
|
|
this.raf.getChannel().force(true);
|
|
}
|
|
|
|
public byte[] peek() {
|
|
if (this.closed) {
|
|
throw new IOException(Consts.PLACEMENT_STATUS_CLOSED);
|
|
}
|
|
if (isEmpty()) {
|
|
return null;
|
|
}
|
|
Element element = this.first;
|
|
int i = element.length;
|
|
if (i > 32768) {
|
|
throw new IOException("QueueFile is probably corrupt, first.length is " + this.first.length);
|
|
}
|
|
byte[] bArr = new byte[i];
|
|
ringRead(4 + element.position, bArr, 0, i);
|
|
return bArr;
|
|
}
|
|
|
|
@Override // java.lang.Iterable
|
|
public Iterator iterator() {
|
|
return new ElementIterator();
|
|
}
|
|
|
|
public final class ElementIterator implements Iterator {
|
|
public int expectedModCount;
|
|
public int nextElementIndex = 0;
|
|
public long nextElementPosition;
|
|
|
|
public ElementIterator() {
|
|
this.nextElementPosition = QueueFile.this.first.position;
|
|
this.expectedModCount = QueueFile.this.modCount;
|
|
}
|
|
|
|
public final void checkForComodification() {
|
|
if (QueueFile.this.modCount != this.expectedModCount) {
|
|
throw new ConcurrentModificationException();
|
|
}
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public boolean hasNext() {
|
|
if (QueueFile.this.closed) {
|
|
throw new IllegalStateException(Consts.PLACEMENT_STATUS_CLOSED);
|
|
}
|
|
checkForComodification();
|
|
return this.nextElementIndex != QueueFile.this.elementCount;
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public byte[] next() {
|
|
if (QueueFile.this.closed) {
|
|
throw new IllegalStateException(Consts.PLACEMENT_STATUS_CLOSED);
|
|
}
|
|
checkForComodification();
|
|
if (QueueFile.this.isEmpty()) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
int i = this.nextElementIndex;
|
|
QueueFile queueFile = QueueFile.this;
|
|
if (i >= queueFile.elementCount) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
try {
|
|
Element readElement = queueFile.readElement(this.nextElementPosition);
|
|
byte[] bArr = new byte[readElement.length];
|
|
long wrapPosition = QueueFile.this.wrapPosition(readElement.position + 4);
|
|
this.nextElementPosition = wrapPosition;
|
|
QueueFile.this.ringRead(wrapPosition, bArr, 0, readElement.length);
|
|
this.nextElementPosition = QueueFile.this.wrapPosition(readElement.position + 4 + readElement.length);
|
|
this.nextElementIndex++;
|
|
return bArr;
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("todo: throw a proper error", e);
|
|
}
|
|
}
|
|
|
|
@Override // java.util.Iterator
|
|
public void remove() {
|
|
checkForComodification();
|
|
if (QueueFile.this.isEmpty()) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
if (this.nextElementIndex != 1) {
|
|
throw new UnsupportedOperationException("Removal is only permitted from the head.");
|
|
}
|
|
try {
|
|
QueueFile.this.remove();
|
|
this.expectedModCount = QueueFile.this.modCount;
|
|
this.nextElementIndex--;
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("todo: throw a proper error", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void remove() {
|
|
remove(1);
|
|
}
|
|
|
|
public void remove(int i) {
|
|
if (i < 0) {
|
|
throw new IllegalArgumentException("Cannot remove negative (" + i + ") number of elements.");
|
|
}
|
|
if (i == 0) {
|
|
return;
|
|
}
|
|
if (i == this.elementCount) {
|
|
clear();
|
|
return;
|
|
}
|
|
if (isEmpty()) {
|
|
throw new NoSuchElementException();
|
|
}
|
|
if (i > this.elementCount) {
|
|
throw new IllegalArgumentException("Cannot remove more elements (" + i + ") than present in queue (" + this.elementCount + ").");
|
|
}
|
|
Element element = this.first;
|
|
long j = element.position;
|
|
int i2 = element.length;
|
|
long j2 = 0;
|
|
int i3 = 0;
|
|
long j3 = j;
|
|
while (i3 < i) {
|
|
j2 += i2 + 4;
|
|
long wrapPosition = wrapPosition(j3 + 4 + i2);
|
|
ringRead(wrapPosition, this.buffer, 0, 4);
|
|
i2 = readInt(this.buffer, 0);
|
|
i3++;
|
|
j3 = wrapPosition;
|
|
}
|
|
writeHeader(this.fileLength, this.elementCount - i, j3, this.last.position);
|
|
this.elementCount -= i;
|
|
this.modCount++;
|
|
this.first = new Element(j3, i2);
|
|
if (this.zero) {
|
|
ringErase(j, j2);
|
|
}
|
|
}
|
|
|
|
public void clear() {
|
|
if (this.closed) {
|
|
throw new IOException(Consts.PLACEMENT_STATUS_CLOSED);
|
|
}
|
|
writeHeader(PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM, 0, 0L, 0L);
|
|
if (this.zero) {
|
|
this.raf.seek(this.headerLength);
|
|
this.raf.write(ZEROES, 0, 4096 - this.headerLength);
|
|
}
|
|
this.elementCount = 0;
|
|
Element element = Element.NULL;
|
|
this.first = element;
|
|
this.last = element;
|
|
if (this.fileLength > PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM) {
|
|
setLength(PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM);
|
|
}
|
|
this.fileLength = PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM;
|
|
this.modCount++;
|
|
}
|
|
|
|
@Override // java.io.Closeable, java.lang.AutoCloseable
|
|
public void close() {
|
|
this.closed = true;
|
|
this.raf.close();
|
|
}
|
|
|
|
public String toString() {
|
|
return QueueFile.class.getSimpleName() + "[length=" + this.fileLength + ", size=" + this.elementCount + ", first=" + this.first + ", last=" + this.last + v8.i.e;
|
|
}
|
|
|
|
public static class Element {
|
|
public static final Element NULL = new Element(0, 0);
|
|
public final int length;
|
|
public final long position;
|
|
|
|
public Element(long j, int i) {
|
|
this.position = j;
|
|
this.length = i;
|
|
}
|
|
|
|
public String toString() {
|
|
return getClass().getSimpleName() + "[position=" + this.position + ", length=" + this.length + v8.i.e;
|
|
}
|
|
}
|
|
|
|
public static final class Builder {
|
|
public final File file;
|
|
public boolean zero = true;
|
|
public boolean forceLegacy = false;
|
|
|
|
public Builder(File file) {
|
|
if (file == null) {
|
|
throw new NullPointerException("file == null");
|
|
}
|
|
this.file = file;
|
|
}
|
|
|
|
public QueueFile build() {
|
|
return new QueueFile(this.file, QueueFile.initializeFromFile(this.file, this.forceLegacy), this.zero, this.forceLegacy);
|
|
}
|
|
}
|
|
}
|