19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you to close it when done with it.
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ParcelFileDescriptor implements Parcelable {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final FileDescriptor mFileDescriptor;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mClosed;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //this field is to create wrapper for ParcelFileDescriptor using another
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //PartialFileDescriptor but avoid invoking close twice
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //consider ParcelFileDescriptor A(fileDescriptor fd),  ParcelFileDescriptor B(A)
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //in this particular case fd.close might be invoked twice.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final ParcelFileDescriptor mParcelDescriptor;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and this file doesn't already exist, then create the file with
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * permissions such that any application can read it.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_WORLD_READABLE = 0x00000001;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and this file doesn't already exist, then create the file with
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * permissions such that any application can write it.
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_WORLD_WRITEABLE = 0x00000002;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: open the file with read-only access.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_READ_ONLY = 0x10000000;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: open the file with write-only access.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_WRITE_ONLY = 0x20000000;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: open the file with read and write access.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_READ_WRITE = 0x30000000;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: create the file if it doesn't already exist.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_CREATE = 0x08000000;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: erase contents of file when opening.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_TRUNCATE = 0x04000000;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with {@link #open}: append to end of file while writing.
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_APPEND = 0x02000000;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new ParcelFileDescriptor accessing a given file.
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param file The file to be opened.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode The desired access mode, must be one of
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #MODE_READ_WRITE}; may also be any combination of
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #MODE_WORLD_READABLE}, and {@link #MODE_WORLD_WRITEABLE}.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new ParcelFileDescriptor pointing to the given
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file.
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws FileNotFoundException Throws FileNotFoundException if the given
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * file does not exist or can not be opened with the requested mode.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ParcelFileDescriptor open(File file, int mode)
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws FileNotFoundException {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String path = file.getPath();
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SecurityManager security = System.getSecurityManager();
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (security != null) {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            security.checkRead(path);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((mode&MODE_WRITE_ONLY) != 0) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                security.checkWrite(path);
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((mode&MODE_READ_WRITE) == 0) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException(
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileDescriptor fd = Parcel.openFileDescriptor(path, mode);
116186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        return fd != null ? new ParcelFileDescriptor(fd) : null;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new ParcelFileDescriptor from the specified Socket.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param socket The Socket whose FileDescriptor is used to create
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               a new ParcelFileDescriptor.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A new ParcelFileDescriptor with the FileDescriptor of the
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         specified Socket.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static ParcelFileDescriptor fromSocket(Socket socket) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FileDescriptor fd = getFileDescriptorFromSocket(socket);
130186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        return fd != null ? new ParcelFileDescriptor(fd) : null;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Extracts the file descriptor from the specified socket and returns it untouched
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native FileDescriptor getFileDescriptorFromSocket(Socket socket);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
137389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton     * Create two ParcelFileDescriptors structured as a data pipe.  The first
138389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton     * ParcelFileDescriptor in the returned array is the read side; the second
139389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton     * is the write side.
140389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton     */
141389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton    public static ParcelFileDescriptor[] createPipe() throws IOException {
142389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton        FileDescriptor[] fds = new FileDescriptor[2];
143389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton        int res = createPipeNative(fds);
144389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton        if (res == 0) {
145389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton            ParcelFileDescriptor[] pfds = new ParcelFileDescriptor[2];
146389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton            pfds[0] = new ParcelFileDescriptor(fds[0]);
147389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton            pfds[1] = new ParcelFileDescriptor(fds[1]);
148389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton            return pfds;
149389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton        }
150389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton        throw new IOException("Unable to create pipe: errno=" + -res);
151389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton    }
152389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton
153389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton    private static native int createPipeNative(FileDescriptor[] outFds);
154389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton
155389a440ad13f7b16e8f7c7f1670bdd55f1e2112aJeff Hamilton    /**
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the actual FileDescriptor associated with this object.
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the FileDescriptor associated with this object.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public FileDescriptor getFileDescriptor() {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFileDescriptor;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the total size of the file representing this fd, as determined
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by stat().  Returns -1 if the fd is not a file.
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native long getStatSize();
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream,
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and I really don't think we want it to be public.
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native long seekTo(long pos);
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Close the ParcelFileDescriptor. This implementation closes the underlying
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * OS resources allocated to represent this stream.
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *             If an error occurs attempting to close this ParcelFileDescriptor.
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void close() throws IOException {
185186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        synchronized (this) {
186186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn            if (mClosed) return;
187186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn            mClosed = true;
188186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mParcelDescriptor != null) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If this is a proxy to another file descriptor, just call through to its
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // close method.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mParcelDescriptor.close();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Parcel.closeFileDescriptor(mFileDescriptor);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An InputStream you can create on a ParcelFileDescriptor, which will
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * take care of calling {@link ParcelFileDescriptor#close
201fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate     * ParcelFileDescriptor.close()} for you when the stream is closed.
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class AutoCloseInputStream extends FileInputStream {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ParcelFileDescriptor mFd;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public AutoCloseInputStream(ParcelFileDescriptor fd) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(fd.getFileDescriptor());
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFd = fd;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void close() throws IOException {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFd.close();
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * An OutputStream you can create on a ParcelFileDescriptor, which will
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * take care of calling {@link ParcelFileDescriptor#close
220fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate     * ParcelFileDescriptor.close()} for you when the stream is closed.
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static class AutoCloseOutputStream extends FileOutputStream {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ParcelFileDescriptor mFd;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public AutoCloseOutputStream(ParcelFileDescriptor fd) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(fd.getFileDescriptor());
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFd = fd;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void close() throws IOException {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFd.close();
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return "{ParcelFileDescriptor: " + mFileDescriptor + "}";
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mClosed) {
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close();
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mParcelDescriptor = descriptor;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileDescriptor = mParcelDescriptor.mFileDescriptor;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package */ParcelFileDescriptor(FileDescriptor descriptor) {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
260186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        if (descriptor == null) {
261186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn            throw new NullPointerException("descriptor must not be null");
262186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn        }
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFileDescriptor = descriptor;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mParcelDescriptor = null;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* Parcelable interface */
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int describeContents() {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Parcelable.CONTENTS_FILE_DESCRIPTOR;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
272b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor    /**
273b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor     * {@inheritDoc}
274b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor     * If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags,
275b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor     * the file descriptor will be closed after a copy is written to the Parcel.
276b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor     */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void writeToParcel(Parcel out, int flags) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        out.writeFileDescriptor(mFileDescriptor);
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                close();
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Empty
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new Parcelable.Creator<ParcelFileDescriptor>() {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ParcelFileDescriptor createFromParcel(Parcel in) {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return in.readFileDescriptor();
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ParcelFileDescriptor[] newArray(int size) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ParcelFileDescriptor[size];
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
299