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; 187407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 19da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport static libcore.io.OsConstants.AF_UNIX; 20da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport static libcore.io.OsConstants.SEEK_SET; 21da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport static libcore.io.OsConstants.SOCK_STREAM; 22da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport static libcore.io.OsConstants.S_ISLNK; 23da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport static libcore.io.OsConstants.S_ISREG; 24da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 25da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport android.content.BroadcastReceiver; 26da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport android.content.ContentProvider; 27da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport android.util.Log; 28da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 297407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkeyimport dalvik.system.CloseGuard; 307407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 31da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.ErrnoException; 32da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.IoUtils; 33da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.Libcore; 34da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.Memory; 35da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.OsConstants; 36da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport libcore.io.StructStat; 37da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 38e861b423790e5bf2d5a55b096065c6ad0541d5bbJeff Sharkeyimport java.io.Closeable; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 4547f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yehimport java.net.DatagramSocket; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.Socket; 47da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkeyimport java.nio.ByteOrder; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you to close it when done with it. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 53e861b423790e5bf2d5a55b096065c6ad0541d5bbJeff Sharkeypublic class ParcelFileDescriptor implements Parcelable, Closeable { 54da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static final String TAG = "ParcelFileDescriptor"; 55da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 56da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private final FileDescriptor mFd; 57da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 58da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 59da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Optional socket used to communicate close events, status at close, and 60da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * detect remote process crashes. 61da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 62da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private FileDescriptor mCommFd; 637407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 647407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey /** 657407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey * Wrapped {@link ParcelFileDescriptor}, if any. Used to avoid 66da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * double-closing {@link #mFd}. 677407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey */ 687407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey private final ParcelFileDescriptor mWrapped; 697407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 70da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 71da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Maximum {@link #mStatusBuf} size; longer status messages will be 72da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * truncated. 73da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 74da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static final int MAX_STATUS = 1024; 75da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 76da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 77da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Temporary buffer used by {@link #readCommStatus(FileDescriptor, byte[])}, 78da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * allocated on-demand. 79da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 80da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private byte[] mStatusBuf; 81da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 82da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 83b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * Status read by {@link #checkError()}, or null if not read yet. 84da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 85da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private Status mStatus; 86da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 877407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey private volatile boolean mClosed; 887407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 897407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey private final CloseGuard mGuard = CloseGuard.get(); 904390758f277645de6e81f6482d582473383cc917Elliott Hughes 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 92da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and 93da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * this file doesn't already exist, then create the file with permissions 94da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * such that any application can read it. 95da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 96da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @deprecated Creating world-readable files is very dangerous, and likely 97da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * to cause security holes in applications. It is strongly 98da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * discouraged; instead, applications should use more formal 99da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * mechanism for interactions such as {@link ContentProvider}, 100da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link BroadcastReceiver}, and {@link android.app.Service}. 101da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * There are no guarantees that this access mode will remain on 102da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * a file, such as when it goes through a backup and restore. 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 104da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey @Deprecated 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_WORLD_READABLE = 0x00000001; 1064390758f277645de6e81f6482d582473383cc917Elliott Hughes 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 108da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and 109da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * this file doesn't already exist, then create the file with permissions 110da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * such that any application can write it. 111da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 112da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @deprecated Creating world-writable files is very dangerous, and likely 113da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * to cause security holes in applications. It is strongly 114da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * discouraged; instead, applications should use more formal 115da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * mechanism for interactions such as {@link ContentProvider}, 116da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link BroadcastReceiver}, and {@link android.app.Service}. 117da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * There are no guarantees that this access mode will remain on 118da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * a file, such as when it goes through a backup and restore. 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 120da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey @Deprecated 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_WORLD_WRITEABLE = 0x00000002; 1224390758f277645de6e81f6482d582473383cc917Elliott Hughes 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: open the file with read-only access. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_READ_ONLY = 0x10000000; 1274390758f277645de6e81f6482d582473383cc917Elliott Hughes 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: open the file with write-only access. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_WRITE_ONLY = 0x20000000; 1324390758f277645de6e81f6482d582473383cc917Elliott Hughes 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: open the file with read and write access. 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_READ_WRITE = 0x30000000; 1374390758f277645de6e81f6482d582473383cc917Elliott Hughes 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: create the file if it doesn't already exist. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_CREATE = 0x08000000; 1424390758f277645de6e81f6482d582473383cc917Elliott Hughes 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: erase contents of file when opening. 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_TRUNCATE = 0x04000000; 1474390758f277645de6e81f6482d582473383cc917Elliott Hughes 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For use with {@link #open}: append to end of file while writing. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_APPEND = 0x02000000; 1524390758f277645de6e81f6482d582473383cc917Elliott Hughes 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 154da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Create a new ParcelFileDescriptor wrapped around another descriptor. By 155da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * default all method calls are delegated to the wrapped descriptor. 156da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 157da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public ParcelFileDescriptor(ParcelFileDescriptor wrapped) { 158da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // We keep a strong reference to the wrapped PFD, and rely on its 159da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // finalizer to trigger CloseGuard. All calls are delegated to wrapper. 160da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mWrapped = wrapped; 161da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mFd = null; 162da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mCommFd = null; 163da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mClosed = true; 164da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 165da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 166da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** {@hide} */ 167da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public ParcelFileDescriptor(FileDescriptor fd) { 168da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey this(fd, null); 169da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 170da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 171da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** {@hide} */ 172da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public ParcelFileDescriptor(FileDescriptor fd, FileDescriptor commChannel) { 173da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (fd == null) { 174da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new NullPointerException("FileDescriptor must not be null"); 175da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 176da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mWrapped = null; 177da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mFd = fd; 178da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mCommFd = commChannel; 179da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mGuard.open("close"); 180da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 181da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 182da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new ParcelFileDescriptor accessing a given file. 1844390758f277645de6e81f6482d582473383cc917Elliott Hughes * 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param file The file to be opened. 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mode The desired access mode, must be one of 187da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or 188da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_READ_WRITE}; may also be any combination of 189da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE}, 190da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_WORLD_READABLE}, and 191da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_WORLD_WRITEABLE}. 192da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @return a new ParcelFileDescriptor pointing to the given file. 193da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @throws FileNotFoundException if the given file does not exist or can not 194da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * be opened with the requested mode. 195e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * @see #parseMode(String) 196da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 197da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static ParcelFileDescriptor open(File file, int mode) throws FileNotFoundException { 198da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd = openInternal(file, mode); 199da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (fd == null) return null; 200da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 201da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor(fd); 202da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 203da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 204da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 205da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Create a new ParcelFileDescriptor accessing a given file. 2064390758f277645de6e81f6482d582473383cc917Elliott Hughes * 207da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param file The file to be opened. 208da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param mode The desired access mode, must be one of 209da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or 210da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_READ_WRITE}; may also be any combination of 211da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE}, 212da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_WORLD_READABLE}, and 213da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #MODE_WORLD_WRITEABLE}. 214da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param handler to call listener from; must not be null. 215da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param listener to be invoked when the returned descriptor has been 216da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * closed; must not be null. 217da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @return a new ParcelFileDescriptor pointing to the given file. 218da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @throws FileNotFoundException if the given file does not exist or can not 219da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * be opened with the requested mode. 220e8c00d8ed477e199b7f8d1b1e2f37e9cf8593372Jeff Sharkey * @see #parseMode(String) 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 222da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static ParcelFileDescriptor open( 223da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey File file, int mode, Handler handler, OnCloseListener listener) throws IOException { 224da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (handler == null) { 225da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new IllegalArgumentException("Handler must not be null"); 226da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 227da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (listener == null) { 228da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new IllegalArgumentException("Listener must not be null"); 229da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 230da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 231da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd = openInternal(file, mode); 232da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (fd == null) return null; 233da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 234d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final FileDescriptor[] comm = createCommSocketPair(); 235da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]); 236da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 237da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Kick off thread to watch for status updates 238d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey IoUtils.setBlocking(comm[1], true); 239da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final ListenerBridge bridge = new ListenerBridge(comm[1], handler.getLooper(), listener); 240da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey bridge.start(); 241da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 242da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return pfd; 243da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 2444390758f277645de6e81f6482d582473383cc917Elliott Hughes 245da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException { 246da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if ((mode & MODE_READ_WRITE) == 0) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException( 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE"); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2504390758f277645de6e81f6482d582473383cc917Elliott Hughes 251da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final String path = file.getPath(); 252da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return Parcel.openFileDescriptor(path, mode); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 256e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * Create a new ParcelFileDescriptor that is a dup of an existing 257e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * FileDescriptor. This obeys standard POSIX semantics, where the 258e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * new file descriptor shared state such as file position with the 259e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn * original file descriptor. 260e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn */ 261e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException { 262da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 263da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd = Libcore.os.dup(orig); 264da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor(fd); 265da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 266da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 267da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 268e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn } 269e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn 270e17aeb31030cfeed339a39a107912ad5e9178390Dianne Hackborn /** 27162f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn * Create a new ParcelFileDescriptor that is a dup of the existing 27262f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn * FileDescriptor. This obeys standard POSIX semantics, where the 27362f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn * new file descriptor shared state such as file position with the 27462f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn * original file descriptor. 27562f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn */ 27662f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn public ParcelFileDescriptor dup() throws IOException { 277da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 278da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.dup(); 279da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 280da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return dup(getFileDescriptor()); 281da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 28262f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn } 28362f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn 28462f20ecf492d2b29881bba307c79ff55e68760e6Dianne Hackborn /** 285ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * Create a new ParcelFileDescriptor from a raw native fd. The new 286ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * ParcelFileDescriptor holds a dup of the original fd passed in here, 287ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * so you must still close that fd as well as the new ParcelFileDescriptor. 288ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * 289ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * @param fd The native fd that the ParcelFileDescriptor should dup. 290ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * 291ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * @return Returns a new ParcelFileDescriptor holding a FileDescriptor 292ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * for a dup of the given fd. 293ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn */ 294ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn public static ParcelFileDescriptor fromFd(int fd) throws IOException { 295da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor original = new FileDescriptor(); 296da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey original.setInt$(fd); 297ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn 298da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 299da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor dup = Libcore.os.dup(original); 300da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor(dup); 301da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 302da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 303da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 304da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 305ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn 306ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn /** 307ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * Take ownership of a raw native fd in to a new ParcelFileDescriptor. 308ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * The returned ParcelFileDescriptor now owns the given fd, and will be 309ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * responsible for closing it. You must not close the fd yourself. 310ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * 311ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * @param fd The native fd that the ParcelFileDescriptor should adopt. 312ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * 313ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * @return Returns a new ParcelFileDescriptor holding a FileDescriptor 314ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * for the given fd. 315ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn */ 316ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn public static ParcelFileDescriptor adoptFd(int fd) { 317da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fdesc = new FileDescriptor(); 318da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey fdesc.setInt$(fd); 319da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 320ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn return new ParcelFileDescriptor(fdesc); 321ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn } 322ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn 323ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn /** 324ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * Create a new ParcelFileDescriptor from the specified Socket. The new 325ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * ParcelFileDescriptor holds a dup of the original FileDescriptor in 326ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * the Socket, so you must still close the Socket as well as the new 327ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn * ParcelFileDescriptor. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param socket The Socket whose FileDescriptor is used to create 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a new ParcelFileDescriptor. 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A new ParcelFileDescriptor with the FileDescriptor of the 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified Socket. 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ParcelFileDescriptor fromSocket(Socket socket) { 3364390758f277645de6e81f6482d582473383cc917Elliott Hughes FileDescriptor fd = socket.getFileDescriptor$(); 337186683923ce8d6a2d5c6fd4768b26b90308661e9Dianne Hackborn return fd != null ? new ParcelFileDescriptor(fd) : null; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 34147f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * Create a new ParcelFileDescriptor from the specified DatagramSocket. 34247f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * 34347f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * @param datagramSocket The DatagramSocket whose FileDescriptor is used 34447f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * to create a new ParcelFileDescriptor. 34547f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * 34647f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * @return A new ParcelFileDescriptor with the FileDescriptor of the 34747f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh * specified DatagramSocket. 34847f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh */ 34947f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh public static ParcelFileDescriptor fromDatagramSocket(DatagramSocket datagramSocket) { 35047f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh FileDescriptor fd = datagramSocket.getFileDescriptor$(); 35147f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh return fd != null ? new ParcelFileDescriptor(fd) : null; 35247f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh } 35347f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh 35447f8f0fa70343ea0d150e644f4109fb2d1185044Chia-chi Yeh /** 35523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * Create two ParcelFileDescriptors structured as a data pipe. The first 35623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * ParcelFileDescriptor in the returned array is the read side; the second 35723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn * is the write side. 35823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn */ 35923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn public static ParcelFileDescriptor[] createPipe() throws IOException { 360da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 361da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor[] fds = Libcore.os.pipe(); 362da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor[] { 363da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fds[0]), 364da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fds[1]) }; 365da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 366da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 367da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 368da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 369da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 370da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 371da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Create two ParcelFileDescriptors structured as a data pipe. The first 372da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * ParcelFileDescriptor in the returned array is the read side; the second 373da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * is the write side. 374da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * <p> 375da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * The write end has the ability to deliver an error message through 376da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #closeWithError(String)} which can be handled by the read end 377b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * calling {@link #checkError()}, usually after detecting an EOF. 378da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * This can also be used to detect remote crashes. 379da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 380da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static ParcelFileDescriptor[] createReliablePipe() throws IOException { 381da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 382d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final FileDescriptor[] comm = createCommSocketPair(); 383da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor[] fds = Libcore.os.pipe(); 384da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor[] { 385da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fds[0], comm[0]), 386da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fds[1], comm[1]) }; 387da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 388da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 389da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 39023fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 39123fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 392da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 393da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Create two ParcelFileDescriptors structured as a pair of sockets 394da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * connected to each other. The two sockets are indistinguishable. 395da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 396da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static ParcelFileDescriptor[] createSocketPair() throws IOException { 397da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 398da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd0 = new FileDescriptor(); 399da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd1 = new FileDescriptor(); 400da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); 401da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor[] { 402da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fd0), 403da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fd1) }; 404da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 405da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 406da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 407da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 408da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 409da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 410da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Create two ParcelFileDescriptors structured as a pair of sockets 411da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * connected to each other. The two sockets are indistinguishable. 412da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * <p> 413da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Both ends have the ability to deliver an error message through 414da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #closeWithError(String)} which can be detected by the other end 415b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * calling {@link #checkError()}, usually after detecting an EOF. 416da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * This can also be used to detect remote crashes. 417da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 418da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException { 419da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 420d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final FileDescriptor[] comm = createCommSocketPair(); 421da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd0 = new FileDescriptor(); 422da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd1 = new FileDescriptor(); 423da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); 424da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor[] { 425da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fd0, comm[0]), 426da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey new ParcelFileDescriptor(fd1, comm[1]) }; 427da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 428da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 429da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 430da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 431da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 432d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey private static FileDescriptor[] createCommSocketPair() throws IOException { 433da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 434da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor comm1 = new FileDescriptor(); 435da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor comm2 = new FileDescriptor(); 436da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2); 437d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey IoUtils.setBlocking(comm1, false); 438d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey IoUtils.setBlocking(comm2, false); 439da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new FileDescriptor[] { comm1, comm2 }; 440da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 441da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 442da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 443da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 44423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 44523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn /** 446540f86aa42877ac73f6f2f24dac49382432aa078Dianne Hackborn * @hide Please use createPipe() or ContentProvider.openPipeHelper(). 447a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * Gets a file descriptor for a read-only copy of the given data. 448a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * 449a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @param data Data to copy. 450a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @param name Name for the shared memory area that may back the file descriptor. 451a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * This is purely informative and may be {@code null}. 452a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @return A ParcelFileDescriptor. 453a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * @throws IOException if there is an error while creating the shared memory area. 454a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert */ 455a2ea747faaf5fcd437afbaaf4085cfc29e7c16b8Dianne Hackborn @Deprecated 456a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert public static ParcelFileDescriptor fromData(byte[] data, String name) throws IOException { 457a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert if (data == null) return null; 458a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert MemoryFile file = new MemoryFile(name, data.length); 459a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert if (data.length > 0) { 460a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert file.writeBytes(data, 0, 0, data.length); 461a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 462a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert file.deactivate(); 463a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert FileDescriptor fd = file.getFileDescriptor(); 464a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert return fd != null ? new ParcelFileDescriptor(fd) : null; 465a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert } 466a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert 467a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert /** 468eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use 469eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * with {@link #open}. 470eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * <p> 471eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * @param mode The string representation of the file mode. 472eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * @return A bitmask representing the given file mode. 473eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski * @throws IllegalArgumentException if the given string does not match a known file mode. 474eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski */ 475eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski public static int parseMode(String mode) { 476eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski final int modeBits; 477eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski if ("r".equals(mode)) { 478eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski modeBits = ParcelFileDescriptor.MODE_READ_ONLY; 479eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } else if ("w".equals(mode) || "wt".equals(mode)) { 480eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY 481eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_CREATE 482eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_TRUNCATE; 483eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } else if ("wa".equals(mode)) { 484eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY 485eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_CREATE 486eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_APPEND; 487eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } else if ("rw".equals(mode)) { 488eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski modeBits = ParcelFileDescriptor.MODE_READ_WRITE 489eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_CREATE; 490eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } else if ("rwt".equals(mode)) { 491eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski modeBits = ParcelFileDescriptor.MODE_READ_WRITE 492eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_CREATE 493eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski | ParcelFileDescriptor.MODE_TRUNCATE; 494eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } else { 495eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski throw new IllegalArgumentException("Bad mode '" + mode + "'"); 496eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } 497eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski return modeBits; 498eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski } 499eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski 500eb8c3f93edc826413ff4143284dec01c1061d5ccAdam Lesinski /** 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieve the actual FileDescriptor associated with this object. 5024390758f277645de6e81f6482d582473383cc917Elliott Hughes * 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns the FileDescriptor associated with this object. 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public FileDescriptor getFileDescriptor() { 506da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 507da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.getFileDescriptor(); 508da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 509da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mFd; 510da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5124390758f277645de6e81f6482d582473383cc917Elliott Hughes 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 514da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Return the total size of the file representing this fd, as determined by 515da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@code stat()}. Returns -1 if the fd is not a file. 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 517da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public long getStatSize() { 518da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 519da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.getStatSize(); 520da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 521da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 522da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final StructStat st = Libcore.os.fstat(mFd); 523da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 524da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return st.st_size; 525da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 526da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return -1; 527da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 528da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 529da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.w(TAG, "fstat() failed: " + e); 530da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return -1; 531da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 532da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 533da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 5344390758f277645de6e81f6482d582473383cc917Elliott Hughes 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream, 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and I really don't think we want it to be public. 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 540da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public long seekTo(long pos) throws IOException { 541da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 542da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.seekTo(pos); 543da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 544da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 545da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return Libcore.os.lseek(mFd, pos, SEEK_SET); 546da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 547da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw e.rethrowAsIOException(); 548da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 549da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 550da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 5514390758f277645de6e81f6482d582473383cc917Elliott Hughes 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 553c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn * Return the native fd int for this ParcelFileDescriptor. The 554c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn * ParcelFileDescriptor still owns the fd, and it still must be closed 555c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn * through this API. 556c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn */ 557c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn public int getFd() { 558da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 559da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.getFd(); 560da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 561da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mClosed) { 562da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new IllegalStateException("Already closed"); 563da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 564da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mFd.getInt$(); 565c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn } 566c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn } 5674390758f277645de6e81f6482d582473383cc917Elliott Hughes 568c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn /** 569da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Return the native fd int for this ParcelFileDescriptor and detach it from 570da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * the object here. You are now responsible for closing the fd in native 571da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * code. 572da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * <p> 573da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * You should not detach when the original creator of the descriptor is 574da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * expecting a reliable signal through {@link #close()} or 575da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link #closeWithError(String)}. 576da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 577da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @see #canDetectErrors() 578c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn */ 579c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn public int detachFd() { 5807407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey if (mWrapped != null) { 581da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.detachFd(); 582da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 583da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mClosed) { 584da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new IllegalStateException("Already closed"); 585da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 586da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final int fd = getFd(); 587da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Parcel.clearFileDescriptor(mFd); 588da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey writeCommStatusAndClose(Status.DETACHED, null); 589c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn return fd; 590c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn } 591c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn } 5924390758f277645de6e81f6482d582473383cc917Elliott Hughes 593c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn /** 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Close the ParcelFileDescriptor. This implementation closes the underlying 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * OS resources allocated to represent this stream. 5964390758f277645de6e81f6482d582473383cc917Elliott Hughes * 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IOException 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If an error occurs attempting to close this ParcelFileDescriptor. 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6007407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey @Override 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 6027407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey if (mWrapped != null) { 603487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani try { 604487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani mWrapped.close(); 605487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } finally { 606487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani releaseResources(); 607487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 609da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey closeWithStatus(Status.OK, null); 610da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 611da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 612da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 613da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 614da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Close the ParcelFileDescriptor, informing any peer that an error occurred 615da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * while processing. If the creator of this descriptor is not observing 616da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * errors, it will close normally. 617da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 618da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param msg describing the error; must not be null. 619da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 620da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public void closeWithError(String msg) throws IOException { 621da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 622487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani try { 623487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani mWrapped.closeWithError(msg); 624487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } finally { 625487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani releaseResources(); 626487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } 627da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 628da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (msg == null) { 629da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw new IllegalArgumentException("Message must not be null"); 630da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 631da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey closeWithStatus(Status.ERROR, msg); 632da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 633da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 634da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 635487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani private void closeWithStatus(int status, String msg) { 636487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani if (mClosed) return; 637487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani mClosed = true; 638487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani mGuard.close(); 639487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani // Status MUST be sent before closing actual descriptor 640487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani writeCommStatusAndClose(status, msg); 641487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani IoUtils.closeQuietly(mFd); 642487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani releaseResources(); 643487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } 644487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani 645487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani /** 646487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani * Called when the fd is being closed, for subclasses to release any other resources 647487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani * associated with it, such as acquired providers. 648487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani * @hide 649487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani */ 650487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani public void releaseResources() { 651da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 652da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 653da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private byte[] getOrCreateStatusBuffer() { 654da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mStatusBuf == null) { 655da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mStatusBuf = new byte[MAX_STATUS]; 656da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 657da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mStatusBuf; 658da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 659da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 660da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private void writeCommStatusAndClose(int status, String msg) { 661da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mCommFd == null) { 662da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Not reliable, or someone already sent status 663da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (msg != null) { 664da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.w(TAG, "Unable to inform peer: " + msg); 665da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 666da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return; 667da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 668da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 669da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (status == Status.DETACHED) { 670da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.w(TAG, "Peer expected signal when closed; unable to deliver after detach"); 671da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 672da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 673da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 674d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey if (status == Status.SILENCE) return; 675d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey 676d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey // Since we're about to close, read off any remote status. It's 677d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey // okay to remember missing here. 678d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer()); 679da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 680d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey // Skip writing status when other end has already gone away. 681d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey if (mStatus != null) return; 682d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey 683d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey try { 684d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final byte[] buf = getOrCreateStatusBuffer(); 685d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey int writePtr = 0; 686da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 687d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN); 688d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey writePtr += 4; 689da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 690d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey if (msg != null) { 691d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final byte[] rawMsg = msg.getBytes(); 692d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey final int len = Math.min(rawMsg.length, buf.length - writePtr); 693d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey System.arraycopy(rawMsg, 0, buf, writePtr, len); 694d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey writePtr += len; 695da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 696d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey 697d99f9caba6600f1b5e0bc8a21681162ae42d6518Jeff Sharkey Libcore.os.write(mCommFd, buf, 0, writePtr); 698da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 699da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Reporting status is best-effort 700da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.w(TAG, "Failed to report status: " + e); 701da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 702da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 703da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } finally { 704da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey IoUtils.closeQuietly(mCommFd); 705da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mCommFd = null; 706da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 707da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 708da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 709da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static Status readCommStatus(FileDescriptor comm, byte[] buf) { 710da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 711da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final int n = Libcore.os.read(comm, buf, 0, buf.length); 712da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (n == 0) { 713da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // EOF means they're dead 714da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new Status(Status.DEAD); 715da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 716da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final int status = Memory.peekInt(buf, 0, ByteOrder.BIG_ENDIAN); 717da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (status == Status.ERROR) { 718da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final String msg = new String(buf, 4, n - 4); 719da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new Status(status, msg); 720da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 721da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new Status(status); 722da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 723da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } catch (ErrnoException e) { 724da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (e.errno == OsConstants.EAGAIN) { 725da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Remote is still alive, but no status written yet 726da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return null; 727da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 728da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.d(TAG, "Failed to read status; assuming dead: " + e); 729da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new Status(Status.DEAD); 730da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 731da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 732da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 733da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 734da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 735da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Indicates if this ParcelFileDescriptor can communicate and detect remote 736da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * errors/crashes. 737da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 738b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * @see #checkError() 739da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 740da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public boolean canDetectErrors() { 741da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 742da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.canDetectErrors(); 743da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 744da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mCommFd != null; 745da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 746da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 747da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 748da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 749da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Detect and throw if the other end of a pipe or socket pair encountered an 750da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * error or crashed. This allows a reader to distinguish between a valid EOF 751da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * and an error/crash. 752da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * <p> 753da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * If this ParcelFileDescriptor is unable to detect remote errors, it will 754da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * return silently. 755da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 756b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * @throws IOException for normal errors. 757b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * @throws FileDescriptorDetachedException 758b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * if the remote side called {@link #detachFd()}. Once detached, the remote 759da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * side is unable to communicate any errors through 760b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * {@link #closeWithError(String)}. 761da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @see #canDetectErrors() 762da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 763b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani public void checkError() throws IOException { 764da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 765b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani mWrapped.checkError(); 766da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 767da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mStatus == null) { 768da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mCommFd == null) { 769da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey Log.w(TAG, "Peer didn't provide a comm channel; unable to check for errors"); 770da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return; 771da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 772da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 773da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Try reading status; it might be null if nothing written yet. 774da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // Either way, we keep comm open to write our status later. 775da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer()); 776da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 777da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 778b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani if (mStatus == null || mStatus.status == Status.OK) { 779da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // No status yet, or everything is peachy! 780da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return; 781da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 782da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey throw mStatus.asIOException(); 783da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7864390758f277645de6e81f6482d582473383cc917Elliott Hughes 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An InputStream you can create on a ParcelFileDescriptor, which will 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * take care of calling {@link ParcelFileDescriptor#close 790fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * ParcelFileDescriptor.close()} for you when the stream is closed. 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class AutoCloseInputStream extends FileInputStream { 793da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private final ParcelFileDescriptor mPfd; 7944390758f277645de6e81f6482d582473383cc917Elliott Hughes 795da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public AutoCloseInputStream(ParcelFileDescriptor pfd) { 796da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey super(pfd.getFileDescriptor()); 797da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mPfd = pfd; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 802fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom try { 803da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mPfd.close(); 804fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom } finally { 805fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom super.close(); 806fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom } 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8094390758f277645de6e81f6482d582473383cc917Elliott Hughes 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * An OutputStream you can create on a ParcelFileDescriptor, which will 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * take care of calling {@link ParcelFileDescriptor#close 813fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * ParcelFileDescriptor.close()} for you when the stream is closed. 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class AutoCloseOutputStream extends FileOutputStream { 816da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private final ParcelFileDescriptor mPfd; 8174390758f277645de6e81f6482d582473383cc917Elliott Hughes 818da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public AutoCloseOutputStream(ParcelFileDescriptor pfd) { 819da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey super(pfd.getFileDescriptor()); 820da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mPfd = pfd; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() throws IOException { 825fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom try { 826da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mPfd.close(); 827fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom } finally { 828fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom super.close(); 829fd9ddd1a40efc801dc7512950cb9336967b6f775Brian Carlstrom } 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8324390758f277645de6e81f6482d582473383cc917Elliott Hughes 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 835da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 836da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.toString(); 837da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 838da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return "{ParcelFileDescriptor: " + mFd + "}"; 839da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8414390758f277645de6e81f6482d582473383cc917Elliott Hughes 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 844487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani if (mWrapped != null) { 845487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani releaseResources(); 846487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } 8477407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey if (mGuard != null) { 8487407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey mGuard.warnIfOpen(); 8497407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey } 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mClosed) { 852da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey closeWithStatus(Status.LEAKED, null); 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.finalize(); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8584390758f277645de6e81f6482d582473383cc917Elliott Hughes 8597407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey @Override 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int describeContents() { 861da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 862da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return mWrapped.describeContents(); 863da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 864da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return Parcelable.CONTENTS_FILE_DESCRIPTOR; 865da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 868b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor /** 869b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor * {@inheritDoc} 870b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor * If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags, 871b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor * the file descriptor will be closed after a copy is written to the Parcel. 872b3e4ef37021a9e5518fdbc7d0cbb0a1709d5301bDan Egnor */ 8737407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey @Override 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel out, int flags) { 875da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mWrapped != null) { 876487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani try { 877487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani mWrapped.writeToParcel(out, flags); 878487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } finally { 879487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani releaseResources(); 880487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani } 881da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 882da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey out.writeFileDescriptor(mFd); 883da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (mCommFd != null) { 884da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey out.writeInt(1); 885da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey out.writeFileDescriptor(mCommFd); 886da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } else { 887da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey out.writeInt(0); 888da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 889da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) { 890487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani // Not a real close, so emit no status 891487c11a3101c6cd9fc18758b3032383666f55e46Amith Yamasani closeWithStatus(Status.SILENCE, null); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new Parcelable.Creator<ParcelFileDescriptor>() { 8987407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey @Override 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ParcelFileDescriptor createFromParcel(Parcel in) { 900da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final FileDescriptor fd = in.readRawFileDescriptor(); 901da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey FileDescriptor commChannel = null; 902da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey if (in.readInt() != 0) { 903da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey commChannel = in.readRawFileDescriptor(); 904da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 905da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new ParcelFileDescriptor(fd, commChannel); 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9077407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey 9087407c948cbe7305c63ca33c471cf9e2a78674368Jeff Sharkey @Override 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ParcelFileDescriptor[] newArray(int size) { 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new ParcelFileDescriptor[size]; 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 913da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 914da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 915da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Callback indicating that a ParcelFileDescriptor has been closed. 916da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 917da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public interface OnCloseListener { 918da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 919da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Event indicating the ParcelFileDescriptor to which this listener was 920da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * attached has been closed. 921da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * 922da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * @param e error state, or {@code null} if closed cleanly. 923b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * If the close event was the result of 924b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * {@link ParcelFileDescriptor#detachFd()}, this will be a 925b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * {@link FileDescriptorDetachedException}. After detach the 926b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * remote side may continue reading/writing to the underlying 927b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * {@link FileDescriptor}, but they can no longer deliver 928b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * reliable close/error events. 929da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 930b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani public void onClose(IOException e); 931b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani } 932b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani 933b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani /** 934b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani * Exception that indicates that the file descriptor was detached. 935b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani */ 936b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani public static class FileDescriptorDetachedException extends IOException { 937b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani 938b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani private static final long serialVersionUID = 0xDe7ac4edFdL; 939b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani 940b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani public FileDescriptorDetachedException() { 941b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani super("Remote side is detached"); 942b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani } 943da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 944da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 945da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 946da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Internal class representing a remote status read by 947da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}. 948da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 949da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static class Status { 950da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Special value indicating remote side died. */ 951da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int DEAD = -2; 952da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Special value indicating no status should be written. */ 953da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int SILENCE = -1; 954da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 955da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Remote reported that everything went better than expected. */ 956da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int OK = 0; 957da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Remote reported error; length and message follow. */ 958da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int ERROR = 1; 959da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Remote reported {@link #detachFd()} and went rogue. */ 960da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int DETACHED = 2; 961da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** Remote reported their object was finalized. */ 962da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public static final int LEAKED = 3; 963da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 964da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public final int status; 965da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public final String msg; 966da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 967da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public Status(int status) { 968da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey this(status, null); 969da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 970da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 971da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public Status(int status, String msg) { 972da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey this.status = status; 973da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey this.msg = msg; 974da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 975da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 976da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public IOException asIOException() { 977da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey switch (status) { 978da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey case DEAD: 979da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new IOException("Remote side is dead"); 980da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey case OK: 981da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return null; 982da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey case ERROR: 983da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new IOException("Remote error: " + msg); 984da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey case DETACHED: 985b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani return new FileDescriptorDetachedException(); 986da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey case LEAKED: 987da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new IOException("Remote side was leaked"); 988da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey default: 989da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey return new IOException("Unknown status: " + status); 990da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 991da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 992da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 993da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 994da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey /** 995da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * Bridge to watch for remote status, and deliver to listener. Currently 996da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey * requires that communication socket is <em>blocking</em>. 997da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey */ 998da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private static final class ListenerBridge extends Thread { 999da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey // TODO: switch to using Looper to avoid burning a thread 1000da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 1001da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private FileDescriptor mCommFd; 1002da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey private final Handler mHandler; 1003da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 1004da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public ListenerBridge(FileDescriptor comm, Looper looper, final OnCloseListener listener) { 1005da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mCommFd = comm; 1006da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mHandler = new Handler(looper) { 1007da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey @Override 1008da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public void handleMessage(Message msg) { 1009da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final Status s = (Status) msg.obj; 1010b433bb8c96f98d280f4a8508ba500bd8f196a773Amith Yamasani listener.onClose(s != null ? s.asIOException() : null); 1011da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 1012da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey }; 1013da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 1014da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey 1015da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey @Override 1016da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey public void run() { 1017da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey try { 1018da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final byte[] buf = new byte[MAX_STATUS]; 1019da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey final Status status = readCommStatus(mCommFd, buf); 1020da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mHandler.obtainMessage(0, status).sendToTarget(); 1021da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } finally { 1022da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey IoUtils.closeQuietly(mCommFd); 1023da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey mCommFd = null; 1024da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 1025da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 1026da5a3e12f4f8f965c57d6f93c74190f43ea233f3Jeff Sharkey } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1028