title: Transfer InputStream to another Service (across process boundaries) with ParcelFileDescriptor.createPipe() failes with "EBADF (Bad file number)"
body: <p>I want to "send" an InputStream from one Android Service to another service running within a different process by using <a href="http://developer.android.com/reference/android/os/ParcelFileDescriptor.html#createPipe%28%29" rel="noreferrer"><code>ParcelFileDescriptor.createPipe()</code></a>, a stream-to-stream copy thread and a ParcelFileDescriptor, representing the read side of the pipe, which is given to the other service with means of Binder IPC.</p>
  
  <h2>Sending Code (Process A)</h2>
  
  <p>I want to send a given InputStream to the receiving service:</p>
  
  <pre><code>public sendInputStream() {
      InputStream is = ...; // that's the stream for process/service B
      ParcelFileDescriptor pdf = ParcelFileDescriptorUtil.pipeFrom(is);
      inputStreamService.inputStream(pdf);
  }
  </code></pre>
  
  <p>The ParcelFileDescriptorUtil is a helper class, with a classic <code>java.io.</code> stream-to-stream copy Thread:</p>
  
  <pre><code>public class ParcelFileDescriptorUtil {
  
      public static ParcelFileDescriptor pipeFrom(InputStream inputStream) throws IOException {
          ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
          ParcelFileDescriptor readSide = pipe[0];
          ParcelFileDescriptor writeSide = pipe[1];
  
          // start the transfer thread
          new TransferThread(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide)).start();
  
          return readSide;
      }
  
      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() {
              byte[] buf = new byte[1024];
              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", e);
              }
              finally {
                  try {
                      mIn.close();
                  } catch (IOException e) {
                  }
                  try {
                      mOut.close();
                  } catch (IOException e) {
                  }
              }
          }
      }
  }
  </code></pre>
  
  <h2>Receiving Service Code (Process B)</h2>
  
  <p>The receiving service's <code>.aidl</code>:</p>
  
  <pre><code>package org.exmaple;
  interface IInputStreamService {
      void inputStream(in ParcelFileDescriptor pfd);
  }
  </code></pre>
  
  <p>The receiving service, called by Process A:</p>
  
  <pre><code>public class InputStreamService extends Service {
  
  @Override
  public IBinder onBind(Intent intent) {
      return mBinder;
  }
  
  private final IInputStreamService.Stub mBinder = new IInputStreamService.Stub() {
  
      @Override
      public void inputStream(ParcelFileDescriptor pfd) throws RemoteException {
  
          InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
          OutputStream os = ...;
          int len;
          byte[] buf = new byte[1024];
          try {
              while ((len = is.read(buf)) &gt; 0) {
                  os.write(buf, 0, len);
              }
          } catch (IOException e) {
                          // this catches the exception shown below
          }
      }
  };
  </code></pre>
  
  <p>But <code>in.read()</code> in <code>inputStream()</code> always throws a <code>IOException</code></p>
  
  <pre><code>java.io.IOException: read failed: EBADF (Bad file number)
      at libcore.io.IoBridge.read(IoBridge.java:442)
      at java.io.FileInputStream.read(FileInputStream.java:179)
      at java.io.InputStream.read(InputStream.java:163)
  </code></pre>
  
  <p>It seems like the EBADF errno is set by <code>read()</code> when the file descriptor is closed. But I don't know what is causing it and how to fix it.</p>
  
  <p>And yes, I know that a ConentProvider would also be a possibility. But shouldn't it also work with my approach? Are there any other ways to hand an InputStream stream to a different service in Android?</p>
  
  <p><sup>On a side note: CommonsWare created a similar <a href="https://github.com/commonsguy/cw-omnibus/blob/master/ContentProvider/Pipe/src/com/commonsware/android/cp/pipe/PipeProvider.java" rel="noreferrer">project using a ContentProvider</a> (related SO questions <a href="https://stackoverflow.com/questions/12920429/anyone-have-mediaplayer-working-with-parcelfiledescriptor-and-createpipe">1</a>, <a href="https://stackoverflow.com/questions/12894976/anyone-have-mediarecorder-working-with-parcelfiledescriptor-and-createpipe">2</a>). It's where I got most of the ideas for my approach from</sup></p>