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