|
29 | 29 | import com.google.android.exoplayer2.upstream.DataSourceException;
|
30 | 30 | import com.google.android.exoplayer2.upstream.DataSpec;
|
31 | 31 | import com.google.android.exoplayer2.upstream.HttpDataSource;
|
| 32 | +import com.google.android.exoplayer2.upstream.HttpDataSource.HttpDataSourceException; |
| 33 | +import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidContentTypeException; |
| 34 | +import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException; |
32 | 35 | import com.google.android.exoplayer2.upstream.HttpUtil;
|
33 | 36 | import com.google.android.exoplayer2.upstream.TransferListener;
|
34 | 37 | import com.google.android.exoplayer2.util.Assertions;
|
35 | 38 | import com.google.android.exoplayer2.util.Util;
|
36 | 39 | import com.google.common.base.Predicate;
|
37 | 40 | import com.google.common.net.HttpHeaders;
|
| 41 | +import com.google.common.util.concurrent.SettableFuture; |
38 | 42 | import java.io.IOException;
|
39 | 43 | import java.io.InputStream;
|
40 | 44 | import java.io.InterruptedIOException;
|
41 | 45 | import java.util.Collections;
|
42 | 46 | import java.util.HashMap;
|
43 | 47 | import java.util.List;
|
44 | 48 | import java.util.Map;
|
| 49 | +import java.util.concurrent.ExecutionException; |
45 | 50 | import okhttp3.CacheControl;
|
46 | 51 | import okhttp3.Call;
|
| 52 | +import okhttp3.Callback; |
47 | 53 | import okhttp3.HttpUrl;
|
48 | 54 | import okhttp3.MediaType;
|
49 | 55 | import okhttp3.OkHttpClient;
|
@@ -281,8 +287,9 @@ public long open(DataSpec dataSpec) throws HttpDataSourceException {
|
281 | 287 | Request request = makeRequest(dataSpec);
|
282 | 288 | Response response;
|
283 | 289 | ResponseBody responseBody;
|
| 290 | + Call call = callFactory.newCall(request); |
284 | 291 | try {
|
285 |
| - this.response = callFactory.newCall(request).execute(); |
| 292 | + this.response = executeCall(call); |
286 | 293 | response = this.response;
|
287 | 294 | responseBody = Assertions.checkNotNull(response.body());
|
288 | 295 | responseByteStream = responseBody.byteStream();
|
@@ -428,6 +435,35 @@ private Request makeRequest(DataSpec dataSpec) throws HttpDataSourceException {
|
428 | 435 | return builder.build();
|
429 | 436 | }
|
430 | 437 |
|
| 438 | + /** |
| 439 | + * This method is an interrupt safe replacement of OkHttp Call.execute() which can get in bad |
| 440 | + * states if interrupted while writing to the shared connection socket. |
| 441 | + */ |
| 442 | + private Response executeCall(Call call) throws IOException { |
| 443 | + SettableFuture<Response> future = SettableFuture.create(); |
| 444 | + call.enqueue( |
| 445 | + new Callback() { |
| 446 | + @Override |
| 447 | + public void onFailure(Call call, IOException e) { |
| 448 | + future.setException(e); |
| 449 | + } |
| 450 | + |
| 451 | + @Override |
| 452 | + public void onResponse(Call call, Response response) { |
| 453 | + future.set(response); |
| 454 | + } |
| 455 | + }); |
| 456 | + |
| 457 | + try { |
| 458 | + return future.get(); |
| 459 | + } catch (InterruptedException e) { |
| 460 | + call.cancel(); |
| 461 | + throw new InterruptedIOException(); |
| 462 | + } catch (ExecutionException ee) { |
| 463 | + throw new IOException(ee); |
| 464 | + } |
| 465 | + } |
| 466 | + |
431 | 467 | /**
|
432 | 468 | * Attempts to skip the specified number of bytes in full.
|
433 | 469 | *
|
|
0 commit comments