content: package com.genymobile.scrcpy;
  
  import android.system.ErrnoException;
  import android.system.Os;
  import android.system.OsConstants;
  
  import java.io.FileDescriptor;
  import java.io.IOException;
  import java.io.InputStream;
  import java.nio.ByteBuffer;
  import java.util.Scanner;
  
  public final class IO {
      private IO() {
          // not instantiable
      }
  
      public static void writeFully(FileDescriptor fd, ByteBuffer from) throws IOException {
          // ByteBuffer position is not updated as expected by Os.write() on old Android versions, so
          // count the remaining bytes manually.
          // See <https://github.com/Genymobile/scrcpy/issues/291>.
          int remaining = from.remaining();
          while (remaining > 0) {
              try {
                  int w = Os.write(fd, from);
                  if (BuildConfig.DEBUG && w < 0) {
                      // w should not be negative, since an exception is thrown on error
                      throw new AssertionError("Os.write() returned a negative value (" + w + ")");
                  }
                  remaining -= w;
              } catch (ErrnoException e) {
                  if (e.errno != OsConstants.EINTR) {
                      throw new IOException(e);
                  }
              }
          }
      }
  
      public static void writeFully(FileDescriptor fd, byte[] buffer, int offset, int len) throws IOException {
          writeFully(fd, ByteBuffer.wrap(buffer, offset, len));
      }
  
      public static String toString(InputStream inputStream) {
          StringBuilder builder = new StringBuilder();
          Scanner scanner = new Scanner(inputStream);
          while (scanner.hasNextLine()) {
              builder.append(scanner.nextLine()).append('\n');
          }
          return builder.toString();
      }
  
      public static boolean isBrokenPipe(IOException e) {
          Throwable cause = e.getCause();
          return cause instanceof ErrnoException && ((ErrnoException) cause).errno == OsConstants.EPIPE;
      }
  }
  