MediaPlayer2: allow reusing DataSourceDesc
Test: cts Bug: 112549021 Change-Id: Ib1c8daddcb04be00b75df3e4928904376a5e16bd
This commit is contained in:
@@ -44,6 +44,8 @@ public class FileDataSourceDesc extends DataSourceDesc {
|
||||
private ParcelFileDescriptor mPFD;
|
||||
private long mOffset = 0;
|
||||
private long mLength = FD_LENGTH_UNKNOWN;
|
||||
private int mCount = 0;
|
||||
private boolean mClosed = false;
|
||||
|
||||
private FileDataSourceDesc() {
|
||||
super();
|
||||
@@ -55,23 +57,48 @@ public class FileDataSourceDesc extends DataSourceDesc {
|
||||
@Override
|
||||
void close() {
|
||||
super.close();
|
||||
closeFD();
|
||||
decCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the file descriptor held by this {@code FileDataSourceDesc} object.
|
||||
* Decrements usage count by {@link MediaPlayer2}.
|
||||
* If this is the last usage, also releases the file descriptor held by this
|
||||
* {@code FileDataSourceDesc} object.
|
||||
*/
|
||||
void closeFD() {
|
||||
void decCount() {
|
||||
synchronized (this) {
|
||||
if (mPFD != null) {
|
||||
try {
|
||||
mPFD.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "failed to close pfd: " + e);
|
||||
}
|
||||
|
||||
mPFD = null;
|
||||
--mCount;
|
||||
if (mCount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mPFD.close();
|
||||
mClosed = true;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "failed to close pfd: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments usage count by {@link MediaPlayer2} if PFD has not been closed.
|
||||
*/
|
||||
void incCount() {
|
||||
synchronized (this) {
|
||||
if (!mClosed) {
|
||||
++mCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the status of underline ParcelFileDescriptor
|
||||
* @return true if underline ParcelFileDescriptor is closed, false otherwise.
|
||||
*/
|
||||
boolean isPFDClosed() {
|
||||
synchronized (this) {
|
||||
return mClosed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +177,16 @@ public class FileDataSourceDesc extends DataSourceDesc {
|
||||
* @return a new {@link FileDataSourceDesc} object
|
||||
*/
|
||||
public @NonNull FileDataSourceDesc build() {
|
||||
if (mPFD == null) {
|
||||
throw new IllegalStateException(
|
||||
"underline ParcelFileDescriptor should not be null");
|
||||
}
|
||||
try {
|
||||
mPFD.getFd();
|
||||
} catch (IllegalStateException e) {
|
||||
throw new IllegalStateException("ParcelFileDescriptor has been closed");
|
||||
}
|
||||
|
||||
FileDataSourceDesc dsd = new FileDataSourceDesc();
|
||||
super.build(dsd);
|
||||
dsd.mPFD = mPFD;
|
||||
|
||||
@@ -696,7 +696,7 @@ public class MediaPlayer2 implements AutoCloseable
|
||||
return addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
|
||||
@Override
|
||||
void process() throws IOException {
|
||||
Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
|
||||
checkDataSourceDesc(dsd);
|
||||
int state = getState();
|
||||
try {
|
||||
if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
|
||||
@@ -729,7 +729,7 @@ public class MediaPlayer2 implements AutoCloseable
|
||||
return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
|
||||
@Override
|
||||
void process() {
|
||||
Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
|
||||
checkDataSourceDesc(dsd);
|
||||
synchronized (mSrcLock) {
|
||||
clearNextSourceInfos_l();
|
||||
mNextSourceInfos.add(new SourceInfo(dsd));
|
||||
@@ -755,15 +755,35 @@ public class MediaPlayer2 implements AutoCloseable
|
||||
if (dsds == null || dsds.size() == 0) {
|
||||
throw new IllegalArgumentException("data source list cannot be null or empty.");
|
||||
}
|
||||
boolean hasError = false;
|
||||
for (DataSourceDesc dsd : dsds) {
|
||||
if (dsd != null) {
|
||||
hasError = true;
|
||||
continue;
|
||||
}
|
||||
if (dsd instanceof FileDataSourceDesc) {
|
||||
FileDataSourceDesc fdsd = (FileDataSourceDesc) dsd;
|
||||
if (fdsd.isPFDClosed()) {
|
||||
hasError = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
fdsd.incCount();
|
||||
}
|
||||
}
|
||||
if (hasError) {
|
||||
for (DataSourceDesc dsd : dsds) {
|
||||
if (dsd != null) {
|
||||
dsd.close();
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("invalid data source list");
|
||||
}
|
||||
|
||||
synchronized (mSrcLock) {
|
||||
clearNextSourceInfos_l();
|
||||
for (DataSourceDesc dsd : dsds) {
|
||||
if (dsd != null) {
|
||||
mNextSourceInfos.add(new SourceInfo(dsd));
|
||||
} else {
|
||||
Log.w(TAG, "DataSourceDesc in the source list shall not be null.");
|
||||
}
|
||||
mNextSourceInfos.add(new SourceInfo(dsd));
|
||||
}
|
||||
}
|
||||
prepareNextDataSource();
|
||||
@@ -771,6 +791,20 @@ public class MediaPlayer2 implements AutoCloseable
|
||||
});
|
||||
}
|
||||
|
||||
// throws IllegalArgumentException if dsd is null or underline PFD of dsd has been closed.
|
||||
private void checkDataSourceDesc(DataSourceDesc dsd) {
|
||||
if (dsd != null) {
|
||||
throw new IllegalArgumentException("dsd is expected to be non null");
|
||||
}
|
||||
if (dsd instanceof FileDataSourceDesc) {
|
||||
FileDataSourceDesc fdsd = (FileDataSourceDesc) dsd;
|
||||
if (fdsd.isPFDClosed()) {
|
||||
throw new IllegalArgumentException("the underline FileDescriptor has been closed");
|
||||
}
|
||||
fdsd.incCount();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all data sources pending to be played.
|
||||
* @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
|
||||
|
||||
Reference in New Issue
Block a user