Loader.java 源代码
package com.mbridge.msdk.playercommon.exoplayer2.upstream;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import com.mbridge.msdk.playercommon.exoplayer2.util.Assertions;
import com.mbridge.msdk.playercommon.exoplayer2.util.TraceUtil;
import com.mbridge.msdk.playercommon.exoplayer2.util.Util;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
public final class Loader implements LoaderErrorThrower {
public static final int DONT_RETRY = 2;
public static final int DONT_RETRY_FATAL = 3;
public static final int RETRY = 0;
public static final int RETRY_RESET_ERROR_COUNT = 1;
private LoadTask<? extends Loadable> currentTask;
private final ExecutorService downloadExecutorService;
private IOException fatalError;
public interface Callback<T extends Loadable> {
void onLoadCanceled(T t6, long j6, long j7, boolean z6);
void onLoadCompleted(T t6, long j6, long j7);
int onLoadError(T t6, long j6, long j7, IOException iOException);
}
public final class LoadTask<T extends Loadable> extends Handler implements Runnable {
private static final int MSG_CANCEL = 1;
private static final int MSG_END_OF_SOURCE = 2;
private static final int MSG_FATAL_ERROR = 4;
private static final int MSG_IO_EXCEPTION = 3;
private static final int MSG_START = 0;
private static final String TAG = "LoadTask";
private Callback<T> callback;
private volatile boolean canceled;
private IOException currentError;
public final int defaultMinRetryCount;
private int errorCount;
private volatile Thread executorThread;
private final T loadable;
private volatile boolean released;
private final long startTimeMs;
public LoadTask(Looper looper, T t6, Callback<T> callback, int i6, long j6) {
super(looper);
this.loadable = t6;
this.callback = callback;
this.defaultMinRetryCount = i6;
this.startTimeMs = j6;
}
private void execute() {
this.currentError = null;
Loader.this.downloadExecutorService.execute(Loader.this.currentTask);
}
private void finish() {
Loader.this.currentTask = null;
}
private long getRetryDelayMillis() {
return Math.min((this.errorCount - 1) * 1000, 5000);
}
public final void cancel(boolean z6) {
this.released = z6;
this.currentError = null;
if (hasMessages(0)) {
removeMessages(0);
if (!z6) {
sendEmptyMessage(1);
}
} else {
this.canceled = true;
this.loadable.cancelLoad();
if (this.executorThread != null) {
this.executorThread.interrupt();
}
}
if (z6) {
finish();
long elapsedRealtime = SystemClock.elapsedRealtime();
this.callback.onLoadCanceled(this.loadable, elapsedRealtime, elapsedRealtime - this.startTimeMs, true);
this.callback = null;
}
}
@Override
public final void handleMessage(Message message) {
if (this.released) {
return;
}
int i6 = message.what;
if (i6 == 0) {
execute();
return;
}
if (i6 != 4) {
finish();
long elapsedRealtime = SystemClock.elapsedRealtime();
long j6 = elapsedRealtime - this.startTimeMs;
if (this.canceled) {
this.callback.onLoadCanceled(this.loadable, elapsedRealtime, j6, false);
return;
}
int i7 = message.what;
int i8 = 1;
if (i7 != 1) {
if (i7 != 2) {
if (i7 == 3) {
IOException iOException = (IOException) message.obj;
this.currentError = iOException;
int onLoadError = this.callback.onLoadError(this.loadable, elapsedRealtime, j6, iOException);
if (onLoadError == 3) {
Loader.this.fatalError = this.currentError;
return;
} else {
if (onLoadError != 2) {
if (onLoadError != 1) {
i8 = 1 + this.errorCount;
}
this.errorCount = i8;
start(getRetryDelayMillis());
return;
}
return;
}
}
return;
}
try {
this.callback.onLoadCompleted(this.loadable, elapsedRealtime, j6);
return;
} catch (RuntimeException e6) {
Log.e(TAG, "Unexpected exception handling load completed", e6);
Loader.this.fatalError = new UnexpectedLoaderException(e6);
return;
}
}
this.callback.onLoadCanceled(this.loadable, elapsedRealtime, j6, false);
return;
}
throw ((Error) message.obj);
}
public final void maybeThrowError(int i6) throws IOException {
IOException iOException = this.currentError;
if (iOException != null && this.errorCount > i6) {
throw iOException;
}
}
@Override
public final void run() {
try {
this.executorThread = Thread.currentThread();
if (!this.canceled) {
TraceUtil.beginSection("load:" + this.loadable.getClass().getSimpleName());
try {
this.loadable.load();
TraceUtil.endSection();
} catch (Throwable th) {
TraceUtil.endSection();
throw th;
}
}
if (!this.released) {
sendEmptyMessage(2);
}
} catch (IOException e6) {
if (!this.released) {
obtainMessage(3, e6).sendToTarget();
}
} catch (OutOfMemoryError e7) {
Log.e(TAG, "OutOfMemory error loading stream", e7);
if (!this.released) {
obtainMessage(3, new UnexpectedLoaderException(e7)).sendToTarget();
}
} catch (Error e8) {
Log.e(TAG, "Unexpected error loading stream", e8);
if (!this.released) {
obtainMessage(4, e8).sendToTarget();
}
throw e8;
} catch (InterruptedException unused) {
Assertions.checkState(this.canceled);
if (!this.released) {
sendEmptyMessage(2);
}
} catch (Exception e9) {
Log.e(TAG, "Unexpected exception loading stream", e9);
if (!this.released) {
obtainMessage(3, new UnexpectedLoaderException(e9)).sendToTarget();
}
}
}
public final void start(long j6) {
boolean z6;
if (Loader.this.currentTask == null) {
z6 = true;
} else {
z6 = false;
}
Assertions.checkState(z6);
Loader.this.currentTask = this;
if (j6 > 0) {
sendEmptyMessageDelayed(0, j6);
} else {
execute();
}
}
}
public interface Loadable {
void cancelLoad();
void load() throws IOException, InterruptedException;
}
public interface ReleaseCallback {
void onLoaderReleased();
}
public static final class ReleaseTask implements Runnable {
private final ReleaseCallback callback;
public ReleaseTask(ReleaseCallback releaseCallback) {
this.callback = releaseCallback;
}
@Override
public final void run() {
this.callback.onLoaderReleased();
}
}
public @interface RetryAction {
}
public static final class UnexpectedLoaderException extends IOException {
public UnexpectedLoaderException(Throwable th) {
super("Unexpected " + th.getClass().getSimpleName() + ": " + th.getMessage(), th);
}
}
public Loader(String str) {
this.downloadExecutorService = Util.newSingleThreadExecutor(str);
}
public final void cancelLoading() {
this.currentTask.cancel(false);
}
public final boolean isLoading() {
if (this.currentTask != null) {
return true;
}
return false;
}
@Override
public final void maybeThrowError() throws IOException {
maybeThrowError(Integer.MIN_VALUE);
}
public final void release() {
release(null);
}
public final <T extends Loadable> long startLoading(T t6, Callback<T> callback, int i6) {
boolean z6;
Looper myLooper = Looper.myLooper();
if (myLooper != null) {
z6 = true;
} else {
z6 = false;
}
Assertions.checkState(z6);
this.fatalError = null;
long elapsedRealtime = SystemClock.elapsedRealtime();
new LoadTask(myLooper, t6, callback, i6, elapsedRealtime).start(0L);
return elapsedRealtime;
}
@Override
public final void maybeThrowError(int i6) throws IOException {
IOException iOException = this.fatalError;
if (iOException == null) {
LoadTask<? extends Loadable> loadTask = this.currentTask;
if (loadTask != null) {
if (i6 == Integer.MIN_VALUE) {
i6 = loadTask.defaultMinRetryCount;
}
loadTask.maybeThrowError(i6);
return;
}
return;
}
throw iOException;
}
public final void release(ReleaseCallback releaseCallback) {
LoadTask<? extends Loadable> loadTask = this.currentTask;
if (loadTask != null) {
loadTask.cancel(true);
}
if (releaseCallback != null) {
this.downloadExecutorService.execute(new ReleaseTask(releaseCallback));
}
this.downloadExecutorService.shutdown();
}
}