1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os; 18 19 import static android.system.OsConstants.AF_UNIX; 20 import static android.system.OsConstants.F_DUPFD; 21 import static android.system.OsConstants.F_DUPFD_CLOEXEC; 22 import static android.system.OsConstants.O_CLOEXEC; 23 import static android.system.OsConstants.SEEK_SET; 24 import static android.system.OsConstants.SOCK_CLOEXEC; 25 import static android.system.OsConstants.SOCK_SEQPACKET; 26 import static android.system.OsConstants.SOCK_STREAM; 27 import static android.system.OsConstants.S_IROTH; 28 import static android.system.OsConstants.S_IRWXG; 29 import static android.system.OsConstants.S_IRWXU; 30 import static android.system.OsConstants.S_ISLNK; 31 import static android.system.OsConstants.S_ISREG; 32 import static android.system.OsConstants.S_IWOTH; 33 34 import android.annotation.NonNull; 35 import android.annotation.SuppressLint; 36 import android.annotation.SystemApi; 37 import android.annotation.TestApi; 38 import android.compat.annotation.UnsupportedAppUsage; 39 import android.content.BroadcastReceiver; 40 import android.content.ContentProvider; 41 import android.content.ContentResolver; 42 import android.net.Uri; 43 import android.os.MessageQueue.OnFileDescriptorEventListener; 44 import android.system.ErrnoException; 45 import android.system.Os; 46 import android.system.OsConstants; 47 import android.system.StructStat; 48 import android.util.Log; 49 import android.util.Size; 50 51 import dalvik.system.CloseGuard; 52 import dalvik.system.VMRuntime; 53 54 import libcore.io.IoUtils; 55 import libcore.io.Memory; 56 57 import java.io.Closeable; 58 import java.io.File; 59 import java.io.FileDescriptor; 60 import java.io.FileInputStream; 61 import java.io.FileNotFoundException; 62 import java.io.FileOutputStream; 63 import java.io.IOException; 64 import java.io.InterruptedIOException; 65 import java.io.UncheckedIOException; 66 import java.net.DatagramSocket; 67 import java.net.Socket; 68 import java.nio.ByteOrder; 69 70 /** 71 * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing 72 * you to close it when done with it. 73 */ 74 public class ParcelFileDescriptor implements Parcelable, Closeable { 75 private static final String TAG = "ParcelFileDescriptor"; 76 77 private final FileDescriptor mFd; 78 79 /** 80 * Optional socket used to communicate close events, status at close, and 81 * detect remote process crashes. 82 */ 83 private FileDescriptor mCommFd; 84 85 /** 86 * Wrapped {@link ParcelFileDescriptor}, if any. Used to avoid 87 * double-closing {@link #mFd}. 88 * mClosed is always true if mWrapped is non-null. 89 */ 90 private final ParcelFileDescriptor mWrapped; 91 92 /** 93 * Maximum {@link #mStatusBuf} size; longer status messages will be 94 * truncated. 95 */ 96 private static final int MAX_STATUS = 1024; 97 98 /** 99 * Temporary buffer used by {@link #readCommStatus(FileDescriptor, byte[])}, 100 * allocated on-demand. 101 */ 102 private byte[] mStatusBuf; 103 104 /** 105 * Status read by {@link #checkError()}, or null if not read yet. 106 */ 107 private Status mStatus; 108 109 private volatile boolean mClosed; 110 111 private final CloseGuard mGuard = CloseGuard.get(); 112 113 /** 114 * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and 115 * this file doesn't already exist, then create the file with permissions 116 * such that any application can read it. 117 * 118 * @deprecated Creating world-readable files is very dangerous, and likely 119 * to cause security holes in applications. It is strongly 120 * discouraged; instead, applications should use more formal 121 * mechanism for interactions such as {@link ContentProvider}, 122 * {@link BroadcastReceiver}, and {@link android.app.Service}. 123 * There are no guarantees that this access mode will remain on 124 * a file, such as when it goes through a backup and restore. 125 */ 126 @Deprecated 127 public static final int MODE_WORLD_READABLE = 0x00000001; 128 129 /** 130 * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and 131 * this file doesn't already exist, then create the file with permissions 132 * such that any application can write it. 133 * 134 * @deprecated Creating world-writable files is very dangerous, and likely 135 * to cause security holes in applications. It is strongly 136 * discouraged; instead, applications should use more formal 137 * mechanism for interactions such as {@link ContentProvider}, 138 * {@link BroadcastReceiver}, and {@link android.app.Service}. 139 * There are no guarantees that this access mode will remain on 140 * a file, such as when it goes through a backup and restore. 141 */ 142 @Deprecated 143 public static final int MODE_WORLD_WRITEABLE = 0x00000002; 144 145 /** 146 * For use with {@link #open}: open the file with read-only access. 147 */ 148 public static final int MODE_READ_ONLY = 0x10000000; 149 150 /** 151 * For use with {@link #open}: open the file with write-only access. 152 */ 153 public static final int MODE_WRITE_ONLY = 0x20000000; 154 155 /** 156 * For use with {@link #open}: open the file with read and write access. 157 */ 158 public static final int MODE_READ_WRITE = 0x30000000; 159 160 /** 161 * For use with {@link #open}: create the file if it doesn't already exist. 162 */ 163 public static final int MODE_CREATE = 0x08000000; 164 165 /** 166 * For use with {@link #open}: erase contents of file when opening. 167 */ 168 public static final int MODE_TRUNCATE = 0x04000000; 169 170 /** 171 * For use with {@link #open}: append to end of file while writing. 172 */ 173 public static final int MODE_APPEND = 0x02000000; 174 175 /** 176 * Create a new ParcelFileDescriptor wrapped around another descriptor. By 177 * default all method calls are delegated to the wrapped descriptor. 178 */ ParcelFileDescriptor(ParcelFileDescriptor wrapped)179 public ParcelFileDescriptor(ParcelFileDescriptor wrapped) { 180 // We keep a strong reference to the wrapped PFD, and rely on its 181 // finalizer to trigger CloseGuard. All calls are delegated to wrapper. 182 mWrapped = wrapped; 183 mFd = null; 184 mCommFd = null; 185 mClosed = true; 186 } 187 188 /** {@hide} */ 189 @UnsupportedAppUsage ParcelFileDescriptor(FileDescriptor fd)190 public ParcelFileDescriptor(FileDescriptor fd) { 191 this(fd, null); 192 } 193 194 /** {@hide} */ ParcelFileDescriptor(FileDescriptor fd, FileDescriptor commChannel)195 public ParcelFileDescriptor(FileDescriptor fd, FileDescriptor commChannel) { 196 if (fd == null) { 197 throw new NullPointerException("FileDescriptor must not be null"); 198 } 199 mWrapped = null; 200 mFd = fd; 201 IoUtils.setFdOwner(mFd, this); 202 203 mCommFd = commChannel; 204 if (mCommFd != null) { 205 IoUtils.setFdOwner(mCommFd, this); 206 } 207 208 mGuard.open("close"); 209 } 210 211 /** 212 * Create a new ParcelFileDescriptor accessing a given file. 213 * <p> 214 * This method should only be used for files that you have direct access to; 215 * if you'd like to work with files hosted outside your app, use an API like 216 * {@link ContentResolver#openFile(Uri, String, CancellationSignal)}. 217 * 218 * @param file The file to be opened. 219 * @param mode The desired access mode, must be one of 220 * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or 221 * {@link #MODE_READ_WRITE}; may also be any combination of 222 * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE}, 223 * {@link #MODE_WORLD_READABLE}, and 224 * {@link #MODE_WORLD_WRITEABLE}. 225 * @return a new ParcelFileDescriptor pointing to the given file. 226 * @throws FileNotFoundException if the given file does not exist or can not 227 * be opened with the requested mode. 228 * @see #parseMode(String) 229 */ open(File file, int mode)230 public static ParcelFileDescriptor open(File file, int mode) throws FileNotFoundException { 231 final FileDescriptor fd = openInternal(file, mode); 232 if (fd == null) return null; 233 234 return new ParcelFileDescriptor(fd); 235 } 236 237 /** 238 * Create a new ParcelFileDescriptor accessing a given file. 239 * <p> 240 * This method should only be used for files that you have direct access to; 241 * if you'd like to work with files hosted outside your app, use an API like 242 * {@link ContentResolver#openFile(Uri, String, CancellationSignal)}. 243 * 244 * @param file The file to be opened. 245 * @param mode The desired access mode, must be one of 246 * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or 247 * {@link #MODE_READ_WRITE}; may also be any combination of 248 * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE}, 249 * {@link #MODE_WORLD_READABLE}, and 250 * {@link #MODE_WORLD_WRITEABLE}. 251 * @param handler to call listener from; must not be null. 252 * @param listener to be invoked when the returned descriptor has been 253 * closed; must not be null. 254 * @return a new ParcelFileDescriptor pointing to the given file. 255 * @throws FileNotFoundException if the given file does not exist or can not 256 * be opened with the requested mode. 257 * @see #parseMode(String) 258 */ 259 // We can't accept a generic Executor here, since we need to use 260 // MessageQueue.addOnFileDescriptorEventListener() 261 @SuppressLint("ExecutorRegistration") open(File file, int mode, Handler handler, final OnCloseListener listener)262 public static ParcelFileDescriptor open(File file, int mode, Handler handler, 263 final OnCloseListener listener) throws IOException { 264 if (handler == null) { 265 throw new IllegalArgumentException("Handler must not be null"); 266 } 267 if (listener == null) { 268 throw new IllegalArgumentException("Listener must not be null"); 269 } 270 271 final FileDescriptor fd = openInternal(file, mode); 272 if (fd == null) return null; 273 274 return fromFd(fd, handler, listener); 275 } 276 277 /** 278 * Create a new ParcelFileDescriptor wrapping an already-opened file. 279 * 280 * @param pfd The already-opened file. 281 * @param handler to call listener from. 282 * @param listener to be invoked when the returned descriptor has been 283 * closed. 284 * @return a new ParcelFileDescriptor pointing to the given file. 285 */ 286 // We can't accept a generic Executor here, since we need to use 287 // MessageQueue.addOnFileDescriptorEventListener() 288 @SuppressLint("ExecutorRegistration") wrap(@onNull ParcelFileDescriptor pfd, @NonNull Handler handler, @NonNull OnCloseListener listener)289 public static @NonNull ParcelFileDescriptor wrap(@NonNull ParcelFileDescriptor pfd, 290 @NonNull Handler handler, @NonNull OnCloseListener listener) throws IOException { 291 final FileDescriptor original = new FileDescriptor(); 292 original.setInt$(pfd.detachFd()); 293 return fromFd(original, handler, listener); 294 } 295 296 /** {@hide} */ fromFd(FileDescriptor fd, Handler handler, final OnCloseListener listener)297 public static ParcelFileDescriptor fromFd(FileDescriptor fd, Handler handler, 298 final OnCloseListener listener) throws IOException { 299 if (handler == null) { 300 throw new IllegalArgumentException("Handler must not be null"); 301 } 302 if (listener == null) { 303 throw new IllegalArgumentException("Listener must not be null"); 304 } 305 306 final FileDescriptor[] comm = createCommSocketPair(); 307 final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]); 308 final MessageQueue queue = handler.getLooper().getQueue(); 309 queue.addOnFileDescriptorEventListener(comm[1], 310 OnFileDescriptorEventListener.EVENT_INPUT, new OnFileDescriptorEventListener() { 311 @Override 312 public int onFileDescriptorEvents(FileDescriptor fd, int events) { 313 Status status = null; 314 if ((events & OnFileDescriptorEventListener.EVENT_INPUT) != 0) { 315 final byte[] buf = new byte[MAX_STATUS]; 316 status = readCommStatus(fd, buf); 317 } else if ((events & OnFileDescriptorEventListener.EVENT_ERROR) != 0) { 318 status = new Status(Status.DEAD); 319 } 320 if (status != null) { 321 queue.removeOnFileDescriptorEventListener(fd); 322 IoUtils.closeQuietly(fd); 323 listener.onClose(status.asIOException()); 324 return 0; 325 } 326 return EVENT_INPUT; 327 } 328 }); 329 330 return pfd; 331 } 332 openInternal(File file, int mode)333 private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException { 334 final int flags = FileUtils.translateModePfdToPosix(mode) | ifAtLeastQ(O_CLOEXEC); 335 336 int realMode = S_IRWXU | S_IRWXG; 337 if ((mode & MODE_WORLD_READABLE) != 0) realMode |= S_IROTH; 338 if ((mode & MODE_WORLD_WRITEABLE) != 0) realMode |= S_IWOTH; 339 340 final String path = file.getPath(); 341 try { 342 return Os.open(path, flags, realMode); 343 } catch (ErrnoException e) { 344 throw new FileNotFoundException(e.getMessage()); 345 } 346 } 347 348 /** 349 * Create a new ParcelFileDescriptor that is a dup of an existing 350 * FileDescriptor. This obeys standard POSIX semantics, where the 351 * new file descriptor shared state such as file position with the 352 * original file descriptor. 353 */ dup(FileDescriptor orig)354 public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException { 355 try { 356 final FileDescriptor fd = new FileDescriptor(); 357 int intfd = Os.fcntlInt(orig, (isAtLeastQ() ? F_DUPFD_CLOEXEC : F_DUPFD), 0); 358 fd.setInt$(intfd); 359 return new ParcelFileDescriptor(fd); 360 } catch (ErrnoException e) { 361 throw e.rethrowAsIOException(); 362 } 363 } 364 365 /** 366 * Create a new ParcelFileDescriptor that is a dup of the existing 367 * FileDescriptor. This obeys standard POSIX semantics, where the 368 * new file descriptor shared state such as file position with the 369 * original file descriptor. 370 */ dup()371 public ParcelFileDescriptor dup() throws IOException { 372 if (mWrapped != null) { 373 return mWrapped.dup(); 374 } else { 375 return dup(getFileDescriptor()); 376 } 377 } 378 379 /** 380 * Create a new ParcelFileDescriptor from a raw native fd. The new 381 * ParcelFileDescriptor holds a dup of the original fd passed in here, 382 * so you must still close that fd as well as the new ParcelFileDescriptor. 383 * 384 * @param fd The native fd that the ParcelFileDescriptor should dup. 385 * 386 * @return Returns a new ParcelFileDescriptor holding a FileDescriptor 387 * for a dup of the given fd. 388 */ fromFd(int fd)389 public static ParcelFileDescriptor fromFd(int fd) throws IOException { 390 final FileDescriptor original = new FileDescriptor(); 391 original.setInt$(fd); 392 393 try { 394 final FileDescriptor dup = new FileDescriptor(); 395 int intfd = Os.fcntlInt(original, (isAtLeastQ() ? F_DUPFD_CLOEXEC : F_DUPFD), 0); 396 dup.setInt$(intfd); 397 return new ParcelFileDescriptor(dup); 398 } catch (ErrnoException e) { 399 throw e.rethrowAsIOException(); 400 } 401 } 402 403 /** 404 * Take ownership of a raw native fd in to a new ParcelFileDescriptor. 405 * The returned ParcelFileDescriptor now owns the given fd, and will be 406 * responsible for closing it. 407 * <p> 408 * <strong>WARNING:</strong> You must not close the fd yourself after 409 * this call, and ownership of the file descriptor must have been 410 * released prior to the call to this function. 411 * 412 * @param fd The native fd that the ParcelFileDescriptor should adopt. 413 * 414 * @return Returns a new ParcelFileDescriptor holding a FileDescriptor 415 * for the given fd. 416 */ adoptFd(int fd)417 public static ParcelFileDescriptor adoptFd(int fd) { 418 final FileDescriptor fdesc = new FileDescriptor(); 419 fdesc.setInt$(fd); 420 421 return new ParcelFileDescriptor(fdesc); 422 } 423 424 /** 425 * Create a new ParcelFileDescriptor from the specified Socket. The new 426 * ParcelFileDescriptor holds a dup of the original FileDescriptor in 427 * the Socket, so you must still close the Socket as well as the new 428 * ParcelFileDescriptor. 429 * <p> 430 * <strong>WARNING:</strong> Prior to API level 29, this function would not 431 * actually dup the Socket's FileDescriptor, and would take a 432 * reference to the its internal FileDescriptor instead. If the Socket 433 * gets garbage collected before the ParcelFileDescriptor, this may 434 * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid 435 * this, the following pattern can be used: 436 * <pre>{@code 437 * ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket).dup(); 438 * }</pre> 439 * 440 * @param socket The Socket whose FileDescriptor is used to create 441 * a new ParcelFileDescriptor. 442 * 443 * @return A new ParcelFileDescriptor with a duped copy of the 444 * FileDescriptor of the specified Socket. 445 * 446 * @throws UncheckedIOException if {@link #dup(FileDescriptor)} throws IOException. 447 */ fromSocket(Socket socket)448 public static ParcelFileDescriptor fromSocket(Socket socket) { 449 FileDescriptor fd = socket.getFileDescriptor$(); 450 try { 451 return fd != null ? ParcelFileDescriptor.dup(fd) : null; 452 } catch (IOException e) { 453 throw new UncheckedIOException(e); 454 } 455 } 456 457 /** 458 * Create a new ParcelFileDescriptor from the specified DatagramSocket. The 459 * new ParcelFileDescriptor holds a dup of the original FileDescriptor in 460 * the DatagramSocket, so you must still close the DatagramSocket as well 461 * as the new ParcelFileDescriptor. 462 * <p> 463 * <strong>WARNING:</strong> Prior to API level 29, this function would not 464 * actually dup the DatagramSocket's FileDescriptor, and would take a 465 * reference to the its internal FileDescriptor instead. If the DatagramSocket 466 * gets garbage collected before the ParcelFileDescriptor, this may 467 * lead to the ParcelFileDescriptor being unexpectedly closed. To avoid 468 * this, the following pattern can be used: 469 * <pre>{@code 470 * ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket).dup(); 471 * }</pre> 472 * 473 * @param datagramSocket The DatagramSocket whose FileDescriptor is used 474 * to create a new ParcelFileDescriptor. 475 * 476 * @return A new ParcelFileDescriptor with a duped copy of the 477 * FileDescriptor of the specified Socket. 478 * 479 * @throws UncheckedIOException if {@link #dup(FileDescriptor)} throws IOException. 480 */ fromDatagramSocket(DatagramSocket datagramSocket)481 public static ParcelFileDescriptor fromDatagramSocket(DatagramSocket datagramSocket) { 482 FileDescriptor fd = datagramSocket.getFileDescriptor$(); 483 try { 484 return fd != null ? ParcelFileDescriptor.dup(fd) : null; 485 } catch (IOException e) { 486 throw new UncheckedIOException(e); 487 } 488 } 489 490 /** 491 * Create two ParcelFileDescriptors structured as a data pipe. The first 492 * ParcelFileDescriptor in the returned array is the read side; the second 493 * is the write side. 494 */ createPipe()495 public static ParcelFileDescriptor[] createPipe() throws IOException { 496 try { 497 final FileDescriptor[] fds = Os.pipe2(ifAtLeastQ(O_CLOEXEC)); 498 return new ParcelFileDescriptor[] { 499 new ParcelFileDescriptor(fds[0]), 500 new ParcelFileDescriptor(fds[1]) }; 501 } catch (ErrnoException e) { 502 throw e.rethrowAsIOException(); 503 } 504 } 505 506 /** 507 * Create two ParcelFileDescriptors structured as a data pipe. The first 508 * ParcelFileDescriptor in the returned array is the read side; the second 509 * is the write side. 510 * <p> 511 * The write end has the ability to deliver an error message through 512 * {@link #closeWithError(String)} which can be handled by the read end 513 * calling {@link #checkError()}, usually after detecting an EOF. 514 * This can also be used to detect remote crashes. 515 */ createReliablePipe()516 public static ParcelFileDescriptor[] createReliablePipe() throws IOException { 517 try { 518 final FileDescriptor[] comm = createCommSocketPair(); 519 final FileDescriptor[] fds = Os.pipe2(ifAtLeastQ(O_CLOEXEC)); 520 return new ParcelFileDescriptor[] { 521 new ParcelFileDescriptor(fds[0], comm[0]), 522 new ParcelFileDescriptor(fds[1], comm[1]) }; 523 } catch (ErrnoException e) { 524 throw e.rethrowAsIOException(); 525 } 526 } 527 528 /** 529 * Create two ParcelFileDescriptors structured as a pair of sockets 530 * connected to each other. The two sockets are indistinguishable. 531 */ createSocketPair()532 public static ParcelFileDescriptor[] createSocketPair() throws IOException { 533 return createSocketPair(SOCK_STREAM); 534 } 535 536 /** 537 * @hide 538 */ createSocketPair(int type)539 public static ParcelFileDescriptor[] createSocketPair(int type) throws IOException { 540 try { 541 final FileDescriptor fd0 = new FileDescriptor(); 542 final FileDescriptor fd1 = new FileDescriptor(); 543 Os.socketpair(AF_UNIX, type | ifAtLeastQ(SOCK_CLOEXEC), 0, fd0, fd1); 544 return new ParcelFileDescriptor[] { 545 new ParcelFileDescriptor(fd0), 546 new ParcelFileDescriptor(fd1) }; 547 } catch (ErrnoException e) { 548 throw e.rethrowAsIOException(); 549 } 550 } 551 552 /** 553 * Create two ParcelFileDescriptors structured as a pair of sockets 554 * connected to each other. The two sockets are indistinguishable. 555 * <p> 556 * Both ends have the ability to deliver an error message through 557 * {@link #closeWithError(String)} which can be detected by the other end 558 * calling {@link #checkError()}, usually after detecting an EOF. 559 * This can also be used to detect remote crashes. 560 */ createReliableSocketPair()561 public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException { 562 return createReliableSocketPair(SOCK_STREAM); 563 } 564 565 /** 566 * @hide 567 */ createReliableSocketPair(int type)568 public static ParcelFileDescriptor[] createReliableSocketPair(int type) throws IOException { 569 try { 570 final FileDescriptor[] comm = createCommSocketPair(); 571 final FileDescriptor fd0 = new FileDescriptor(); 572 final FileDescriptor fd1 = new FileDescriptor(); 573 Os.socketpair(AF_UNIX, type | ifAtLeastQ(SOCK_CLOEXEC), 0, fd0, fd1); 574 return new ParcelFileDescriptor[] { 575 new ParcelFileDescriptor(fd0, comm[0]), 576 new ParcelFileDescriptor(fd1, comm[1]) }; 577 } catch (ErrnoException e) { 578 throw e.rethrowAsIOException(); 579 } 580 } 581 createCommSocketPair()582 private static FileDescriptor[] createCommSocketPair() throws IOException { 583 try { 584 // Use SOCK_SEQPACKET so that we have a guarantee that the status 585 // is written and read atomically as one unit and is not split 586 // across multiple IO operations. 587 final FileDescriptor comm1 = new FileDescriptor(); 588 final FileDescriptor comm2 = new FileDescriptor(); 589 Os.socketpair(AF_UNIX, SOCK_SEQPACKET | ifAtLeastQ(SOCK_CLOEXEC), 0, comm1, comm2); 590 IoUtils.setBlocking(comm1, false); 591 IoUtils.setBlocking(comm2, false); 592 return new FileDescriptor[] { comm1, comm2 }; 593 } catch (ErrnoException e) { 594 throw e.rethrowAsIOException(); 595 } 596 } 597 598 /** 599 * @hide Please use createPipe() or ContentProvider.openPipeHelper(). 600 * Gets a file descriptor for a read-only copy of the given data. 601 * 602 * @param data Data to copy. 603 * @param name Name for the shared memory area that may back the file descriptor. 604 * This is purely informative and may be {@code null}. 605 * @return A ParcelFileDescriptor. 606 * @throws IOException if there is an error while creating the shared memory area. 607 */ 608 @UnsupportedAppUsage 609 @Deprecated fromData(byte[] data, String name)610 public static ParcelFileDescriptor fromData(byte[] data, String name) throws IOException { 611 if (data == null) return null; 612 MemoryFile file = new MemoryFile(name, data.length); 613 try { 614 if (data.length > 0) { 615 file.writeBytes(data, 0, 0, data.length); 616 } 617 file.deactivate(); 618 FileDescriptor fd = file.getFileDescriptor(); 619 return fd != null ? ParcelFileDescriptor.dup(fd) : null; 620 } finally { 621 file.close(); 622 } 623 } 624 625 /** 626 * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use 627 * with {@link #open}. 628 * <p> 629 * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw" 630 * or "rwt". 631 * @return A bitmask representing the given file mode. 632 * @throws IllegalArgumentException if the given string does not match a known file mode. 633 */ parseMode(String mode)634 public static int parseMode(String mode) { 635 return FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode)); 636 } 637 638 /** 639 * Return the filesystem path of the real file on disk that is represented 640 * by the given {@link FileDescriptor}. 641 * 642 * @hide 643 */ 644 @TestApi getFile(FileDescriptor fd)645 public static File getFile(FileDescriptor fd) throws IOException { 646 try { 647 final String path = Os.readlink("/proc/self/fd/" + fd.getInt$()); 648 if (OsConstants.S_ISREG(Os.stat(path).st_mode) 649 || OsConstants.S_ISCHR(Os.stat(path).st_mode)) { 650 return new File(path); 651 } else { 652 throw new IOException("Not a regular file or character device: " + path); 653 } 654 } catch (ErrnoException e) { 655 throw e.rethrowAsIOException(); 656 } 657 } 658 659 /** 660 * Retrieve the actual FileDescriptor associated with this object. 661 * 662 * @return Returns the FileDescriptor associated with this object. 663 */ getFileDescriptor()664 public FileDescriptor getFileDescriptor() { 665 if (mWrapped != null) { 666 return mWrapped.getFileDescriptor(); 667 } else { 668 return mFd; 669 } 670 } 671 672 /** 673 * Return the total size of the file representing this fd, as determined by 674 * {@code stat()}. Returns -1 if the fd is not a file. 675 */ getStatSize()676 public long getStatSize() { 677 if (mWrapped != null) { 678 return mWrapped.getStatSize(); 679 } else { 680 try { 681 final StructStat st = Os.fstat(mFd); 682 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 683 return st.st_size; 684 } else { 685 return -1; 686 } 687 } catch (ErrnoException e) { 688 Log.w(TAG, "fstat() failed: " + e); 689 return -1; 690 } 691 } 692 } 693 694 /** 695 * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream, 696 * and I really don't think we want it to be public. 697 * @hide 698 */ 699 @UnsupportedAppUsage seekTo(long pos)700 public long seekTo(long pos) throws IOException { 701 if (mWrapped != null) { 702 return mWrapped.seekTo(pos); 703 } else { 704 try { 705 return Os.lseek(mFd, pos, SEEK_SET); 706 } catch (ErrnoException e) { 707 throw e.rethrowAsIOException(); 708 } 709 } 710 } 711 712 /** 713 * Return the native fd int for this ParcelFileDescriptor. The 714 * ParcelFileDescriptor still owns the fd, and it still must be closed 715 * through this API. 716 * <p> 717 * <strong>WARNING:</strong> Do not call close on the return value of this 718 * function or pass it to a function that assumes ownership of the fd. 719 */ getFd()720 public int getFd() { 721 if (mWrapped != null) { 722 return mWrapped.getFd(); 723 } else { 724 if (mClosed) { 725 throw new IllegalStateException("Already closed"); 726 } 727 return mFd.getInt$(); 728 } 729 } 730 731 /** 732 * Return the native fd int for this ParcelFileDescriptor and detach it from 733 * the object here. You are now responsible for closing the fd in native 734 * code. 735 * <p> 736 * You should not detach when the original creator of the descriptor is 737 * expecting a reliable signal through {@link #close()} or 738 * {@link #closeWithError(String)}. 739 * 740 * @see #canDetectErrors() 741 */ detachFd()742 public int detachFd() { 743 if (mWrapped != null) { 744 return mWrapped.detachFd(); 745 } else { 746 if (mClosed) { 747 throw new IllegalStateException("Already closed"); 748 } 749 int fd = IoUtils.acquireRawFd(mFd); 750 writeCommStatusAndClose(Status.DETACHED, null); 751 mClosed = true; 752 mGuard.close(); 753 releaseResources(); 754 return fd; 755 } 756 } 757 758 /** 759 * Close the ParcelFileDescriptor. This implementation closes the underlying 760 * OS resources allocated to represent this stream. 761 * 762 * @throws IOException 763 * If an error occurs attempting to close this ParcelFileDescriptor. 764 */ 765 @Override close()766 public void close() throws IOException { 767 if (mWrapped != null) { 768 try { 769 mWrapped.close(); 770 } finally { 771 releaseResources(); 772 } 773 } else { 774 closeWithStatus(Status.OK, null); 775 } 776 } 777 778 /** 779 * Close the ParcelFileDescriptor, informing any peer that an error occurred 780 * while processing. If the creator of this descriptor is not observing 781 * errors, it will close normally. 782 * 783 * @param msg describing the error; must not be null. 784 */ closeWithError(String msg)785 public void closeWithError(String msg) throws IOException { 786 if (mWrapped != null) { 787 try { 788 mWrapped.closeWithError(msg); 789 } finally { 790 releaseResources(); 791 } 792 } else { 793 if (msg == null) { 794 throw new IllegalArgumentException("Message must not be null"); 795 } 796 closeWithStatus(Status.ERROR, msg); 797 } 798 } 799 closeWithStatus(int status, String msg)800 private void closeWithStatus(int status, String msg) { 801 if (mClosed) return; 802 mClosed = true; 803 if (mGuard != null) { 804 mGuard.close(); 805 } 806 // Status MUST be sent before closing actual descriptor 807 writeCommStatusAndClose(status, msg); 808 IoUtils.closeQuietly(mFd); 809 releaseResources(); 810 } 811 812 /** 813 * Called when the fd is being closed, for subclasses to release any other resources 814 * associated with it, such as acquired providers. 815 * @hide 816 */ releaseResources()817 public void releaseResources() { 818 } 819 getOrCreateStatusBuffer()820 private byte[] getOrCreateStatusBuffer() { 821 if (mStatusBuf == null) { 822 mStatusBuf = new byte[MAX_STATUS]; 823 } 824 return mStatusBuf; 825 } 826 writeCommStatusAndClose(int status, String msg)827 private void writeCommStatusAndClose(int status, String msg) { 828 if (mCommFd == null) { 829 // Not reliable, or someone already sent status 830 if (msg != null) { 831 Log.w(TAG, "Unable to inform peer: " + msg); 832 } 833 return; 834 } 835 836 if (status == Status.DETACHED) { 837 Log.w(TAG, "Peer expected signal when closed; unable to deliver after detach"); 838 } 839 840 try { 841 if (status == Status.SILENCE) return; 842 843 // Since we're about to close, read off any remote status. It's 844 // okay to remember missing here. 845 mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer()); 846 847 // Skip writing status when other end has already gone away. 848 if (mStatus != null) return; 849 850 try { 851 final byte[] buf = getOrCreateStatusBuffer(); 852 int writePtr = 0; 853 854 Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN); 855 writePtr += 4; 856 857 if (msg != null) { 858 final byte[] rawMsg = msg.getBytes(); 859 final int len = Math.min(rawMsg.length, buf.length - writePtr); 860 System.arraycopy(rawMsg, 0, buf, writePtr, len); 861 writePtr += len; 862 } 863 864 // Must write the entire status as a single operation. 865 Os.write(mCommFd, buf, 0, writePtr); 866 } catch (ErrnoException e) { 867 // Reporting status is best-effort 868 Log.w(TAG, "Failed to report status: " + e); 869 } catch (InterruptedIOException e) { 870 // Reporting status is best-effort 871 Log.w(TAG, "Failed to report status: " + e); 872 } 873 874 } finally { 875 IoUtils.closeQuietly(mCommFd); 876 mCommFd = null; 877 } 878 } 879 readCommStatus(FileDescriptor comm, byte[] buf)880 private static Status readCommStatus(FileDescriptor comm, byte[] buf) { 881 try { 882 // Must read the entire status as a single operation. 883 final int n = Os.read(comm, buf, 0, buf.length); 884 if (n == 0) { 885 // EOF means they're dead 886 return new Status(Status.DEAD); 887 } else { 888 final int status = Memory.peekInt(buf, 0, ByteOrder.BIG_ENDIAN); 889 if (status == Status.ERROR) { 890 final String msg = new String(buf, 4, n - 4); 891 return new Status(status, msg); 892 } 893 return new Status(status); 894 } 895 } catch (ErrnoException e) { 896 if (e.errno == OsConstants.EAGAIN) { 897 // Remote is still alive, but no status written yet 898 return null; 899 } else { 900 Log.d(TAG, "Failed to read status; assuming dead: " + e); 901 return new Status(Status.DEAD); 902 } 903 } catch (InterruptedIOException e) { 904 Log.d(TAG, "Failed to read status; assuming dead: " + e); 905 return new Status(Status.DEAD); 906 } 907 } 908 909 /** 910 * Indicates if this ParcelFileDescriptor can communicate and detect remote 911 * errors/crashes. 912 * 913 * @see #checkError() 914 */ canDetectErrors()915 public boolean canDetectErrors() { 916 if (mWrapped != null) { 917 return mWrapped.canDetectErrors(); 918 } else { 919 return mCommFd != null; 920 } 921 } 922 923 /** 924 * Detect and throw if the other end of a pipe or socket pair encountered an 925 * error or crashed. This allows a reader to distinguish between a valid EOF 926 * and an error/crash. 927 * <p> 928 * If this ParcelFileDescriptor is unable to detect remote errors, it will 929 * return silently. 930 * 931 * @throws IOException for normal errors. 932 * @throws FileDescriptorDetachedException 933 * if the remote side called {@link #detachFd()}. Once detached, the remote 934 * side is unable to communicate any errors through 935 * {@link #closeWithError(String)}. 936 * @see #canDetectErrors() 937 */ checkError()938 public void checkError() throws IOException { 939 if (mWrapped != null) { 940 mWrapped.checkError(); 941 } else { 942 if (mStatus == null) { 943 if (mCommFd == null) { 944 Log.w(TAG, "Peer didn't provide a comm channel; unable to check for errors"); 945 return; 946 } 947 948 // Try reading status; it might be null if nothing written yet. 949 // Either way, we keep comm open to write our status later. 950 mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer()); 951 } 952 953 if (mStatus == null || mStatus.status == Status.OK) { 954 // No status yet, or everything is peachy! 955 return; 956 } else { 957 throw mStatus.asIOException(); 958 } 959 } 960 } 961 962 /** 963 * An InputStream you can create on a ParcelFileDescriptor, which will 964 * take care of calling {@link ParcelFileDescriptor#close 965 * ParcelFileDescriptor.close()} for you when the stream is closed. 966 */ 967 public static class AutoCloseInputStream extends FileInputStream { 968 private final ParcelFileDescriptor mPfd; 969 AutoCloseInputStream(ParcelFileDescriptor pfd)970 public AutoCloseInputStream(ParcelFileDescriptor pfd) { 971 super(pfd.getFileDescriptor()); 972 mPfd = pfd; 973 } 974 975 @Override close()976 public void close() throws IOException { 977 try { 978 super.close(); 979 } finally { 980 mPfd.close(); 981 } 982 } 983 984 @Override read()985 public int read() throws IOException { 986 final int result = super.read(); 987 if (result == -1 && mPfd.canDetectErrors()) { 988 // Check for errors only on EOF, to minimize overhead. 989 mPfd.checkError(); 990 } 991 return result; 992 } 993 994 @Override read(byte[] b)995 public int read(byte[] b) throws IOException { 996 final int result = super.read(b); 997 if (result == -1 && mPfd.canDetectErrors()) { 998 mPfd.checkError(); 999 } 1000 return result; 1001 } 1002 1003 @Override read(byte[] b, int off, int len)1004 public int read(byte[] b, int off, int len) throws IOException { 1005 final int result = super.read(b, off, len); 1006 if (result == -1 && mPfd.canDetectErrors()) { 1007 mPfd.checkError(); 1008 } 1009 return result; 1010 } 1011 } 1012 1013 /** 1014 * An OutputStream you can create on a ParcelFileDescriptor, which will 1015 * take care of calling {@link ParcelFileDescriptor#close 1016 * ParcelFileDescriptor.close()} for you when the stream is closed. 1017 */ 1018 public static class AutoCloseOutputStream extends FileOutputStream { 1019 private final ParcelFileDescriptor mPfd; 1020 AutoCloseOutputStream(ParcelFileDescriptor pfd)1021 public AutoCloseOutputStream(ParcelFileDescriptor pfd) { 1022 super(pfd.getFileDescriptor()); 1023 mPfd = pfd; 1024 } 1025 1026 @Override close()1027 public void close() throws IOException { 1028 try { 1029 super.close(); 1030 } finally { 1031 mPfd.close(); 1032 } 1033 } 1034 } 1035 1036 @Override toString()1037 public String toString() { 1038 if (mWrapped != null) { 1039 return mWrapped.toString(); 1040 } else { 1041 return "{ParcelFileDescriptor: " + mFd + "}"; 1042 } 1043 } 1044 1045 @Override finalize()1046 protected void finalize() throws Throwable { 1047 if (mWrapped != null) { 1048 releaseResources(); 1049 } 1050 if (mGuard != null) { 1051 mGuard.warnIfOpen(); 1052 } 1053 try { 1054 if (!mClosed) { 1055 // mWrapped was and is null. 1056 closeWithStatus(Status.LEAKED, null); 1057 } 1058 } finally { 1059 super.finalize(); 1060 } 1061 } 1062 1063 @Override describeContents()1064 public int describeContents() { 1065 if (mWrapped != null) { 1066 return mWrapped.describeContents(); 1067 } else { 1068 return Parcelable.CONTENTS_FILE_DESCRIPTOR; 1069 } 1070 } 1071 1072 /** 1073 * {@inheritDoc} 1074 * If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags, 1075 * the file descriptor will be closed after a copy is written to the Parcel. 1076 */ 1077 @Override writeToParcel(Parcel out, int flags)1078 public void writeToParcel(Parcel out, int flags) { 1079 if (mWrapped != null) { 1080 try { 1081 mWrapped.writeToParcel(out, flags); 1082 } finally { 1083 releaseResources(); 1084 } 1085 } else { 1086 if (mCommFd != null) { 1087 out.writeInt(1); 1088 out.writeFileDescriptor(mFd); 1089 out.writeFileDescriptor(mCommFd); 1090 } else { 1091 out.writeInt(0); 1092 out.writeFileDescriptor(mFd); 1093 } 1094 if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) { 1095 // Not a real close, so emit no status 1096 closeWithStatus(Status.SILENCE, null); 1097 } 1098 } 1099 } 1100 1101 public static final @android.annotation.NonNull Parcelable.Creator<ParcelFileDescriptor> CREATOR 1102 = new Parcelable.Creator<ParcelFileDescriptor>() { 1103 @Override 1104 public ParcelFileDescriptor createFromParcel(Parcel in) { 1105 int hasCommChannel = in.readInt(); 1106 final FileDescriptor fd = in.readRawFileDescriptor(); 1107 FileDescriptor commChannel = null; 1108 if (hasCommChannel != 0) { 1109 commChannel = in.readRawFileDescriptor(); 1110 } 1111 return new ParcelFileDescriptor(fd, commChannel); 1112 } 1113 1114 @Override 1115 public ParcelFileDescriptor[] newArray(int size) { 1116 return new ParcelFileDescriptor[size]; 1117 } 1118 }; 1119 1120 /** 1121 * Callback indicating that a ParcelFileDescriptor has been closed. 1122 */ 1123 public interface OnCloseListener { 1124 /** 1125 * Event indicating the ParcelFileDescriptor to which this listener was 1126 * attached has been closed. 1127 * 1128 * @param e error state, or {@code null} if closed cleanly. 1129 * If the close event was the result of 1130 * {@link ParcelFileDescriptor#detachFd()}, this will be a 1131 * {@link FileDescriptorDetachedException}. After detach the 1132 * remote side may continue reading/writing to the underlying 1133 * {@link FileDescriptor}, but they can no longer deliver 1134 * reliable close/error events. 1135 */ onClose(IOException e)1136 public void onClose(IOException e); 1137 } 1138 1139 /** 1140 * Exception that indicates that the file descriptor was detached. 1141 */ 1142 public static class FileDescriptorDetachedException extends IOException { 1143 1144 private static final long serialVersionUID = 0xDe7ac4edFdL; 1145 FileDescriptorDetachedException()1146 public FileDescriptorDetachedException() { 1147 super("Remote side is detached"); 1148 } 1149 } 1150 1151 /** 1152 * Internal class representing a remote status read by 1153 * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}. 1154 * 1155 * Warning: this must be kept in sync with ParcelFileDescriptorStatus at 1156 * frameworks/native/libs/binder/Parcel.cpp 1157 */ 1158 private static class Status { 1159 /** Special value indicating remote side died. */ 1160 public static final int DEAD = -2; 1161 /** Special value indicating no status should be written. */ 1162 public static final int SILENCE = -1; 1163 1164 /** Remote reported that everything went better than expected. */ 1165 public static final int OK = 0; 1166 /** Remote reported error; length and message follow. */ 1167 public static final int ERROR = 1; 1168 /** Remote reported {@link #detachFd()} and went rogue. */ 1169 public static final int DETACHED = 2; 1170 /** Remote reported their object was finalized. */ 1171 public static final int LEAKED = 3; 1172 1173 public final int status; 1174 public final String msg; 1175 Status(int status)1176 public Status(int status) { 1177 this(status, null); 1178 } 1179 Status(int status, String msg)1180 public Status(int status, String msg) { 1181 this.status = status; 1182 this.msg = msg; 1183 } 1184 asIOException()1185 public IOException asIOException() { 1186 switch (status) { 1187 case DEAD: 1188 return new IOException("Remote side is dead"); 1189 case OK: 1190 return null; 1191 case ERROR: 1192 return new IOException("Remote error: " + msg); 1193 case DETACHED: 1194 return new FileDescriptorDetachedException(); 1195 case LEAKED: 1196 return new IOException("Remote side was leaked"); 1197 default: 1198 return new IOException("Unknown status: " + status); 1199 } 1200 } 1201 1202 @Override toString()1203 public String toString() { 1204 return "{" + status + ": " + msg + "}"; 1205 } 1206 } 1207 isAtLeastQ()1208 private static boolean isAtLeastQ() { 1209 return (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q); 1210 } 1211 ifAtLeastQ(int value)1212 private static int ifAtLeastQ(int value) { 1213 return isAtLeastQ() ? value : 0; 1214 } 1215 } 1216