title: broken pipe when passing input stream of pdf file
body: <p>I am creating an app, that uses FTP/CLoudRail to access files over the internet. When opening a file, I use this method to first get the input stream, and then to parse it as ParcelFileDescriptor. The problem is, when opening PDF files, I get brokenPipe error. Note that this does not happen with other file types like images/text files</p>
  
  <p>Here is the code I use:</p>
  
  <pre><code>@Override
  public ParcelFileDescriptor openDocument(final String documentId, final String mode,
                                           CancellationSignal signal)
          throws FileNotFoundException {
      Log.d(TAG,"Opening document");
      final CloudFile file = getFileForDocId(documentId);
      final CloudConnection connection = getCloudConnection(documentId);
      //TODO Open a file
      try {
          final boolean isWrite = (mode.indexOf('w') != -1);
          if (isWrite) {
              return null;
          } else {
              InputStream inputStream = connection.getConnectedClient().download(file.getPath());
              if(null != inputStream){
                  return ParcelFileDescriptorUtil.pipeFrom(inputStream);
              }
          }
  
          return null;
      } catch (Exception e) {
          CrashReportingManager.logException(e);
          throw new FileNotFoundException("Failed to open document with id " + documentId +
                  " and mode " + mode);
      }
  }
  </code></pre>
  
  <p>Here is the ParcelFileDescriptorUtil:</p>
  
  <pre><code>public class ParcelFileDescriptorUtil {
  public static ParcelFileDescriptor pipeFrom(InputStream inputStream)
          throws IOException {
      final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
      final OutputStream output = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
  
      new TransferThread(inputStream, output).start();
  
      return pipe[0];
  }
  
  @SuppressWarnings("unused")
  public static ParcelFileDescriptor pipeTo(OutputStream outputStream)
          throws IOException {
      final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
      final InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]);
  
      new TransferThread(input, outputStream).start();
  
      return pipe[1];
  }
  
  static class TransferThread extends Thread {
      final InputStream mIn;
      final OutputStream mOut;
  
      TransferThread(InputStream in, OutputStream out) {
          super("ParcelFileDescriptor Transfer Thread");
          mIn = in;
          mOut = out;
          setDaemon(true);
      }
  
      @Override
      public void run() {
          try {
              IoUtils.copy(mIn, mOut);
          } catch (IOException e) {
              Log.e("TransferThread", "writing failed");
              CrashReportingManager.logException(e);
          } finally {
              IoUtils.flushQuietly(mOut);
              IoUtils.closeQuietly(mIn);
              IoUtils.closeQuietly(mOut);
          }
      }
  }
  
  public static int parseMode(String mode) {
      final int modeBits;
      if ("r".equals(mode)) {
          modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
      } else if ("w".equals(mode) || "wt".equals(mode)) {
          modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
                  | ParcelFileDescriptor.MODE_CREATE
                  | ParcelFileDescriptor.MODE_TRUNCATE;
      } else if ("wa".equals(mode)) {
          modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
                  | ParcelFileDescriptor.MODE_CREATE
                  | ParcelFileDescriptor.MODE_APPEND;
      } else if ("rw".equals(mode)) {
          modeBits = ParcelFileDescriptor.MODE_READ_WRITE
                  | ParcelFileDescriptor.MODE_CREATE;
      } else if ("rwt".equals(mode)) {
          modeBits = ParcelFileDescriptor.MODE_READ_WRITE
                  | ParcelFileDescriptor.MODE_CREATE
                  | ParcelFileDescriptor.MODE_TRUNCATE;
      } else {
          throw new IllegalArgumentException("Bad mode '" + mode + "'");
      }
      return modeBits;
  }
  
  @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener)
          throws IOException {
      ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createReliablePipe();
      ParcelFileDescriptor readSide = pipe[0];
      ParcelFileDescriptor writeSide = pipe[1];
  
      // start the transfer thread
      new TransferThread2(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide),
              listener)
              .start();
  
      return readSide;
  }
  
  public static ParcelFileDescriptor pipeTo(OutputStream outputStream, IThreadListener listener)
          throws IOException {
      ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
      ParcelFileDescriptor readSide = pipe[0];
      ParcelFileDescriptor writeSide = pipe[1];
  
      // start the transfer thread
      new TransferThread2(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream,
              listener)
              .start();
  
      return writeSide;
  }
  
  static class TransferThread2 extends Thread {
      final InputStream mIn;
      final OutputStream mOut;
      final IThreadListener mListener;
  
      TransferThread2(InputStream in, OutputStream out, IThreadListener listener) {
          super("ParcelFileDescriptor Transfer Thread");
          mIn = in;
          mOut = out;
          mListener = listener;
          setDaemon(true);
      }
  
      @Override
      public void run() {
          byte[] buf = new byte[1024*8];
          int len;
  
          try {
              while ((len = mIn.read(buf)) &gt; 0) {
                  mOut.write(buf, 0, len);
              }
              mOut.flush(); // just to be safe
          } catch (IOException e) {
              Log.e("TransferThread", "writing failed");
              e.printStackTrace();
          } finally {
              try {
                  mIn.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              try {
                  mOut.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          if (mListener != null)
              mListener.onThreadFinished(this);
      }
  }
  </code></pre>
  
  <p>What is weird that usually, it happens when you don't have root permission. But, for displaying pdf, you don't need that of course. </p>
  
  <p>By the way, here is the error:</p>
  
  <pre><code>12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err: java.io.IOException: write failed: EPIPE (Broken pipe)
  12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:     at libcore.io.IoBridge.write(IoBridge.java:558)
  12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:     at java.io.FileOutputStream.write(FileOutputStream.java:326)
  12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:     at com.tproductions.Openit.libcore.io.IoUtils.copyLarge(IoUtils.java:310)
  12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:     at com.tproductions.Openit.libcore.io.IoUtils.copy(IoUtils.java:283)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:     at com.tproductions.Openit.misc.ParcelFileDescriptorUtil$TransferThread.run(ParcelFileDescriptorUtil.java:70)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err: Caused by: android.system.ErrnoException: write failed: EPIPE (Broken pipe)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:     at libcore.io.Linux.writeBytes(Native Method)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:     at libcore.io.Linux.write(Linux.java:286)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:     at libcore.io.BlockGuardOs.write(BlockGuardOs.java:345)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:     at libcore.io.IoBridge.write(IoBridge.java:553)
  12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  ... 4 more
  </code></pre>