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