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