content: package com.cicada.player.utils;
  
  import android.content.ContentResolver;
  import android.content.Context;
  import android.net.Uri;
  import android.text.TextUtils;
  
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.io.InputStream;
  
  @NativeUsed
  public class ContentDataSource {
  
      private static final int SEEK_SET = 0;    /* set file offset to offset */
      private static final int SEEK_CUR = 1;    /* set file offset to current plus offset */
      private static final int SEEK_END = 2;    /* set file offset to EOF plus offset */
      private static final int SEEK_SIZE = 0x10000;
  
      private static final int ENOENT = 2;
      private static final int EIO = 5;
      private static final int EINVAL = 22;
  
      private String mUri = null;
      private InputStream mStream = null;
      private int mStreamSize = -1;
      private long mOffset = 0;
      private static Context sContext = null;
  
      private static final String TAG = ContentDataSource.class.getSimpleName();
  
      public ContentDataSource() {
  
      }
  
      public static void setContext(Context context) {
          if (context != null && sContext == null) {
              sContext = context.getApplicationContext();
          }
      }
  
      public void setUri(String uri) {
          mUri = uri;
      }
  
      public int open(int flags) {
  
          if (TextUtils.isEmpty(mUri)) {
              return -EINVAL;
          }
  
          if (sContext == null) {
              return -EINVAL;
          }
  
          ContentResolver contentResolver = sContext.getContentResolver();
          Uri uri = Uri.parse(mUri);
  
          try {
              mStream = contentResolver.openInputStream(uri);
          } catch (FileNotFoundException e) {
              return -ENOENT;
          }
  
          if (mStream == null) {
              return -EINVAL;
          }
  
          try {
              mOffset = 0;
              mStreamSize = mStream.available();
          } catch (IOException e) {
              return -EIO;
          }
          return 0;
      }
  
      public int read(byte[] buffer) {
          if (mStream == null) {
              return -EINVAL;
          }
          int read = -1;
          try {
              read = mStream.read(buffer);
              mOffset += read;
          } catch (IOException e) {
              return -EIO;
          }
          return read;
      }
  
      public void close() {
          if (mStream != null) {
              try {
                  mStream.close();
              } catch (IOException e) {
              }
          }
      }
  
      public long seek(long offset, int whence) {
          if (mStream == null) {
              return -EINVAL;
          }
  
          if (whence == SEEK_SIZE) {
              if (mStreamSize <= 0) {
                  return -EINVAL;
              } else {
                  return mStreamSize;
              }
          } else {
              long targetOffset = 0;
              if (whence == SEEK_END) {
                  try {
                      targetOffset = mStream.available();
                  } catch (IOException e) {
                      return -EIO;
                  }
              } else if (whence == SEEK_SET) {
                  targetOffset = offset - mOffset;
              } else if (whence == SEEK_CUR) {
                  targetOffset = offset;
              } else {
                  return -EINVAL;
              }
  
              try {
                  long skipBytes = skip(targetOffset);
                  mOffset += skipBytes;
                  return mOffset;
              } catch (IOException e) {
                  return -EIO;
              }
          }
  
      }
  
      private long skip(long n) throws IOException {
          try {
              long skipBytes = mStream.skip(n);
              return skipBytes;
          } catch (IOException e) {
              long skipBytes = (int) (mOffset + n);
              close();
              open(0);
              long ret = mStream.skip(skipBytes);
              return ret;
          }
      }
  }
  