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