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