Skip to content

Source length calculation in ContentDataSource changed#2963

Merged
ojw28 merged 4 commits intogoogle:dev-v2from
DroidsOnRoids:dev-v2
Jun 23, 2017
Merged

Source length calculation in ContentDataSource changed#2963
ojw28 merged 4 commits intogoogle:dev-v2from
DroidsOnRoids:dev-v2

Conversation

@koral--
Copy link
Contributor

@koral-- koral-- commented Jun 17, 2017

Fixes UnrecognizedInputFormatExceptions with valid files loaded from content:// URIs

Copy link
Contributor

@ojw28 ojw28 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for finding this! Please find a couple of comments inlined.

uri = dataSpec.uri;
assetFileDescriptor = resolver.openAssetFileDescriptor(uri, "r");
inputStream = new FileInputStream(assetFileDescriptor.getFileDescriptor());
inputStream = assetFileDescriptor.createInputStream();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than doing this, I think it would be preferable to modify L84 to do:

bytesRemaining = assetFileDescriptor.getLength();
if (bytesRemaining == AssetFileDescriptor.UNKNOWN_LENGTH) {
  // The asset must extend to the end of the file.
  bytesRemaining = inputStream.available();
  if (bytesRemaining == 0) {
    // FileInputStream.available() returns 0 if the remaining length cannot be determined, or
    // if it's greater than Integer.MAX_VALUE. We don't know the true length in either case,
    // so treat as unbounded.
    bytesRemaining = C.LENGTH_UNSET;
  }
}

Which makes it explicit what's going on (and also allows bytesRemaining to be greater than Integer.MAX_VALUE, at least in theory).

import android.net.Uri;
import android.test.InstrumentationTestCase;

public class AndroidDataSourceTest extends InstrumentationTestCase {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please split into separate AssetDataSourceTest and ContentDataSourceTest classes. Thanks.

@koral--
Copy link
Contributor Author

koral-- commented Jun 19, 2017

Changed.
It seems that there is also one more unhandled edge case.
ContentResolver#openAssetFileDescriptor() may return null which will result in NPE in L73.
Should that be also fixed in this PR?

@ojw28
Copy link
Contributor

ojw28 commented Jun 19, 2017

Do you understand under what conditions null can actually be returned, and have you managed to reproduce? I see it's marked as @Nullable, but I'm finding it hard to work out when null can actually be returned (I followed the source code as far as IContentProvider). It seems plausible null isn't ever returned, and it's just a result of code going through the IContentProvider interface.

If you do understand the conditions, and/or if handling is trivial anyway (which I guess it is), then yes feel free to fix in this PR. What will you do in that case though? Throw something? What?

@koral--
Copy link
Contributor Author

koral-- commented Jun 19, 2017

There may be a custom ContentProvider which returns null from one of its open* methods family e.g. if TestDataProvider#openAssetFile() from unit test in this PR returns null it will be propagated to ContentResolver#openAssetFileDescriptor().
It is even explicitly mentioned in the documentation: https://developer.android.com/reference/android/content/ContentProvider.html#openFile(android.net.Uri, java.lang.String).

What will you do in that case though? Throw something? What?

something like that: throw new IOException("Could not open " + uri)

@ojw28
Copy link
Contributor

ojw28 commented Jun 19, 2017

Maybe FileNotFoundException? IOException seems fine as well.

@koral--
Copy link
Contributor Author

koral-- commented Jun 19, 2017

Done.

@ojw28
Copy link
Contributor

ojw28 commented Jun 23, 2017

Thanks!

@ojw28 ojw28 merged commit 2da22e9 into google:dev-v2 Jun 23, 2017
DataSpec dataSpec = new DataSpec(contentUri);
long sourceLengthBytes = dataSource.open(dataSpec);

assertEquals(SAMPLE_MP4_BYTES, sourceLengthBytes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I tried to modify this test to also validate that the data being read was correct, but it appears the data read from the DataSource is not as expected. Any ideas?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actually broken. Seems reverting back to using assetFileDescriptor.createInputStream(), as you had it originally, fixes the problem. As does adding inputStream.skip(assetFileDescriptor.getStartOffset()).

I'm working on a bit of a cleanup change, so will merge a fix as part of that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8bb6439

ojw28 pushed a commit that referenced this pull request Jun 30, 2017
@google google locked and limited conversation to collaborators Oct 22, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants