• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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