Methods Summary |
---|
public static android.os.ParcelFileDescriptor | adoptFd(int fd)Take ownership of a raw native fd in to a new ParcelFileDescriptor.
The returned ParcelFileDescriptor now owns the given fd, and will be
responsible for closing it. You must not close the fd yourself.
final FileDescriptor fdesc = new FileDescriptor();
fdesc.setInt$(fd);
return new ParcelFileDescriptor(fdesc);
|
public boolean | canDetectErrors()Indicates if this ParcelFileDescriptor can communicate and detect remote
errors/crashes.
if (mWrapped != null) {
return mWrapped.canDetectErrors();
} else {
return mCommFd != null;
}
|
public void | checkError()Detect and throw if the other end of a pipe or socket pair encountered an
error or crashed. This allows a reader to distinguish between a valid EOF
and an error/crash.
If this ParcelFileDescriptor is unable to detect remote errors, it will
return silently.
if (mWrapped != null) {
mWrapped.checkError();
} else {
if (mStatus == null) {
if (mCommFd == null) {
Log.w(TAG, "Peer didn't provide a comm channel; unable to check for errors");
return;
}
// Try reading status; it might be null if nothing written yet.
// Either way, we keep comm open to write our status later.
mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
}
if (mStatus == null || mStatus.status == Status.OK) {
// No status yet, or everything is peachy!
return;
} else {
throw mStatus.asIOException();
}
}
|
public void | close()Close the ParcelFileDescriptor. This implementation closes the underlying
OS resources allocated to represent this stream.
if (mWrapped != null) {
try {
mWrapped.close();
} finally {
releaseResources();
}
} else {
closeWithStatus(Status.OK, null);
}
|
public void | closeWithError(java.lang.String msg)Close the ParcelFileDescriptor, informing any peer that an error occurred
while processing. If the creator of this descriptor is not observing
errors, it will close normally.
if (mWrapped != null) {
try {
mWrapped.closeWithError(msg);
} finally {
releaseResources();
}
} else {
if (msg == null) {
throw new IllegalArgumentException("Message must not be null");
}
closeWithStatus(Status.ERROR, msg);
}
|
private void | closeWithStatus(int status, java.lang.String msg)
if (mClosed) return;
mClosed = true;
mGuard.close();
// Status MUST be sent before closing actual descriptor
writeCommStatusAndClose(status, msg);
IoUtils.closeQuietly(mFd);
releaseResources();
|
private static java.io.FileDescriptor[] | createCommSocketPair()
try {
final FileDescriptor comm1 = new FileDescriptor();
final FileDescriptor comm2 = new FileDescriptor();
Os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
IoUtils.setBlocking(comm1, false);
IoUtils.setBlocking(comm2, false);
return new FileDescriptor[] { comm1, comm2 };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public static android.os.ParcelFileDescriptor[] | createPipe()Create two ParcelFileDescriptors structured as a data pipe. The first
ParcelFileDescriptor in the returned array is the read side; the second
is the write side.
try {
final FileDescriptor[] fds = Os.pipe();
return new ParcelFileDescriptor[] {
new ParcelFileDescriptor(fds[0]),
new ParcelFileDescriptor(fds[1]) };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public static android.os.ParcelFileDescriptor[] | createReliablePipe()Create two ParcelFileDescriptors structured as a data pipe. The first
ParcelFileDescriptor in the returned array is the read side; the second
is the write side.
The write end has the ability to deliver an error message through
{@link #closeWithError(String)} which can be handled by the read end
calling {@link #checkError()}, usually after detecting an EOF.
This can also be used to detect remote crashes.
try {
final FileDescriptor[] comm = createCommSocketPair();
final FileDescriptor[] fds = Os.pipe();
return new ParcelFileDescriptor[] {
new ParcelFileDescriptor(fds[0], comm[0]),
new ParcelFileDescriptor(fds[1], comm[1]) };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public static android.os.ParcelFileDescriptor[] | createReliableSocketPair()Create two ParcelFileDescriptors structured as a pair of sockets
connected to each other. The two sockets are indistinguishable.
Both ends have the ability to deliver an error message through
{@link #closeWithError(String)} which can be detected by the other end
calling {@link #checkError()}, usually after detecting an EOF.
This can also be used to detect remote crashes.
try {
final FileDescriptor[] comm = createCommSocketPair();
final FileDescriptor fd0 = new FileDescriptor();
final FileDescriptor fd1 = new FileDescriptor();
Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
return new ParcelFileDescriptor[] {
new ParcelFileDescriptor(fd0, comm[0]),
new ParcelFileDescriptor(fd1, comm[1]) };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public static android.os.ParcelFileDescriptor[] | createSocketPair()Create two ParcelFileDescriptors structured as a pair of sockets
connected to each other. The two sockets are indistinguishable.
try {
final FileDescriptor fd0 = new FileDescriptor();
final FileDescriptor fd1 = new FileDescriptor();
Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
return new ParcelFileDescriptor[] {
new ParcelFileDescriptor(fd0),
new ParcelFileDescriptor(fd1) };
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public int | describeContents()
if (mWrapped != null) {
return mWrapped.describeContents();
} else {
return Parcelable.CONTENTS_FILE_DESCRIPTOR;
}
|
public int | detachFd()Return the native fd int for this ParcelFileDescriptor and detach it from
the object here. You are now responsible for closing the fd in native
code.
You should not detach when the original creator of the descriptor is
expecting a reliable signal through {@link #close()} or
{@link #closeWithError(String)}.
if (mWrapped != null) {
return mWrapped.detachFd();
} else {
if (mClosed) {
throw new IllegalStateException("Already closed");
}
final int fd = getFd();
Parcel.clearFileDescriptor(mFd);
writeCommStatusAndClose(Status.DETACHED, null);
return fd;
}
|
public static android.os.ParcelFileDescriptor | dup(java.io.FileDescriptor orig)Create a new ParcelFileDescriptor that is a dup of an existing
FileDescriptor. This obeys standard POSIX semantics, where the
new file descriptor shared state such as file position with the
original file descriptor.
try {
final FileDescriptor fd = Os.dup(orig);
return new ParcelFileDescriptor(fd);
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public android.os.ParcelFileDescriptor | dup()Create a new ParcelFileDescriptor that is a dup of the existing
FileDescriptor. This obeys standard POSIX semantics, where the
new file descriptor shared state such as file position with the
original file descriptor.
if (mWrapped != null) {
return mWrapped.dup();
} else {
return dup(getFileDescriptor());
}
|
protected void | finalize()
if (mWrapped != null) {
releaseResources();
}
if (mGuard != null) {
mGuard.warnIfOpen();
}
try {
if (!mClosed) {
closeWithStatus(Status.LEAKED, null);
}
} finally {
super.finalize();
}
|
public static android.os.ParcelFileDescriptor | fromData(byte[] data, java.lang.String name)
if (data == null) return null;
MemoryFile file = new MemoryFile(name, data.length);
if (data.length > 0) {
file.writeBytes(data, 0, 0, data.length);
}
file.deactivate();
FileDescriptor fd = file.getFileDescriptor();
return fd != null ? new ParcelFileDescriptor(fd) : null;
|
public static android.os.ParcelFileDescriptor | fromDatagramSocket(java.net.DatagramSocket datagramSocket)Create a new ParcelFileDescriptor from the specified DatagramSocket.
FileDescriptor fd = datagramSocket.getFileDescriptor$();
return fd != null ? new ParcelFileDescriptor(fd) : null;
|
public static android.os.ParcelFileDescriptor | fromFd(int fd)Create a new ParcelFileDescriptor from a raw native fd. The new
ParcelFileDescriptor holds a dup of the original fd passed in here,
so you must still close that fd as well as the new ParcelFileDescriptor.
final FileDescriptor original = new FileDescriptor();
original.setInt$(fd);
try {
final FileDescriptor dup = Os.dup(original);
return new ParcelFileDescriptor(dup);
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
|
public static android.os.ParcelFileDescriptor | fromSocket(java.net.Socket socket)Create a new ParcelFileDescriptor from the specified Socket. The new
ParcelFileDescriptor holds a dup of the original FileDescriptor in
the Socket, so you must still close the Socket as well as the new
ParcelFileDescriptor.
FileDescriptor fd = socket.getFileDescriptor$();
return fd != null ? new ParcelFileDescriptor(fd) : null;
|
public int | getFd()Return the native fd int for this ParcelFileDescriptor. The
ParcelFileDescriptor still owns the fd, and it still must be closed
through this API.
if (mWrapped != null) {
return mWrapped.getFd();
} else {
if (mClosed) {
throw new IllegalStateException("Already closed");
}
return mFd.getInt$();
}
|
public java.io.FileDescriptor | getFileDescriptor()Retrieve the actual FileDescriptor associated with this object.
if (mWrapped != null) {
return mWrapped.getFileDescriptor();
} else {
return mFd;
}
|
private byte[] | getOrCreateStatusBuffer()
if (mStatusBuf == null) {
mStatusBuf = new byte[MAX_STATUS];
}
return mStatusBuf;
|
public long | getStatSize()Return the total size of the file representing this fd, as determined by
{@code stat()}. Returns -1 if the fd is not a file.
if (mWrapped != null) {
return mWrapped.getStatSize();
} else {
try {
final StructStat st = Os.fstat(mFd);
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
return st.st_size;
} else {
return -1;
}
} catch (ErrnoException e) {
Log.w(TAG, "fstat() failed: " + e);
return -1;
}
}
|
public static android.os.ParcelFileDescriptor | open(java.io.File file, int mode)Create a new ParcelFileDescriptor accessing a given file.
final FileDescriptor fd = openInternal(file, mode);
if (fd == null) return null;
return new ParcelFileDescriptor(fd);
|
public static android.os.ParcelFileDescriptor | open(java.io.File file, int mode, Handler handler, android.os.ParcelFileDescriptor$OnCloseListener listener)Create a new ParcelFileDescriptor accessing a given file.
if (handler == null) {
throw new IllegalArgumentException("Handler must not be null");
}
if (listener == null) {
throw new IllegalArgumentException("Listener must not be null");
}
final FileDescriptor fd = openInternal(file, mode);
if (fd == null) return null;
final FileDescriptor[] comm = createCommSocketPair();
final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]);
// Kick off thread to watch for status updates
IoUtils.setBlocking(comm[1], true);
final ListenerBridge bridge = new ListenerBridge(comm[1], handler.getLooper(), listener);
bridge.start();
return pfd;
|
private static java.io.FileDescriptor | openInternal(java.io.File file, int mode)
if ((mode & MODE_READ_WRITE) == 0) {
throw new IllegalArgumentException(
"Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
}
final String path = file.getPath();
return Parcel.openFileDescriptor(path, mode);
|
public static int | parseMode(java.lang.String mode)Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
with {@link #open}.
final int modeBits;
if ("r".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
} else if ("w".equals(mode) || "wt".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
| ParcelFileDescriptor.MODE_CREATE
| ParcelFileDescriptor.MODE_TRUNCATE;
} else if ("wa".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
| ParcelFileDescriptor.MODE_CREATE
| ParcelFileDescriptor.MODE_APPEND;
} else if ("rw".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_WRITE
| ParcelFileDescriptor.MODE_CREATE;
} else if ("rwt".equals(mode)) {
modeBits = ParcelFileDescriptor.MODE_READ_WRITE
| ParcelFileDescriptor.MODE_CREATE
| ParcelFileDescriptor.MODE_TRUNCATE;
} else {
throw new IllegalArgumentException("Bad mode '" + mode + "'");
}
return modeBits;
|
private static android.os.ParcelFileDescriptor$Status | readCommStatus(java.io.FileDescriptor comm, byte[] buf)
try {
final int n = Os.read(comm, buf, 0, buf.length);
if (n == 0) {
// EOF means they're dead
return new Status(Status.DEAD);
} else {
final int status = Memory.peekInt(buf, 0, ByteOrder.BIG_ENDIAN);
if (status == Status.ERROR) {
final String msg = new String(buf, 4, n - 4);
return new Status(status, msg);
}
return new Status(status);
}
} catch (ErrnoException e) {
if (e.errno == OsConstants.EAGAIN) {
// Remote is still alive, but no status written yet
return null;
} else {
Log.d(TAG, "Failed to read status; assuming dead: " + e);
return new Status(Status.DEAD);
}
} catch (InterruptedIOException e) {
Log.d(TAG, "Failed to read status; assuming dead: " + e);
return new Status(Status.DEAD);
}
|
public void | releaseResources()Called when the fd is being closed, for subclasses to release any other resources
associated with it, such as acquired providers.
|
public long | seekTo(long pos)This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream,
and I really don't think we want it to be public.
if (mWrapped != null) {
return mWrapped.seekTo(pos);
} else {
try {
return Os.lseek(mFd, pos, SEEK_SET);
} catch (ErrnoException e) {
throw e.rethrowAsIOException();
}
}
|
public java.lang.String | toString()
if (mWrapped != null) {
return mWrapped.toString();
} else {
return "{ParcelFileDescriptor: " + mFd + "}";
}
|
private void | writeCommStatusAndClose(int status, java.lang.String msg)
if (mCommFd == null) {
// Not reliable, or someone already sent status
if (msg != null) {
Log.w(TAG, "Unable to inform peer: " + msg);
}
return;
}
if (status == Status.DETACHED) {
Log.w(TAG, "Peer expected signal when closed; unable to deliver after detach");
}
try {
if (status == Status.SILENCE) return;
// Since we're about to close, read off any remote status. It's
// okay to remember missing here.
mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
// Skip writing status when other end has already gone away.
if (mStatus != null) return;
try {
final byte[] buf = getOrCreateStatusBuffer();
int writePtr = 0;
Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
writePtr += 4;
if (msg != null) {
final byte[] rawMsg = msg.getBytes();
final int len = Math.min(rawMsg.length, buf.length - writePtr);
System.arraycopy(rawMsg, 0, buf, writePtr, len);
writePtr += len;
}
Os.write(mCommFd, buf, 0, writePtr);
} catch (ErrnoException e) {
// Reporting status is best-effort
Log.w(TAG, "Failed to report status: " + e);
} catch (InterruptedIOException e) {
// Reporting status is best-effort
Log.w(TAG, "Failed to report status: " + e);
}
} finally {
IoUtils.closeQuietly(mCommFd);
mCommFd = null;
}
|
public void | writeToParcel(Parcel out, int flags){@inheritDoc}
If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags,
the file descriptor will be closed after a copy is written to the Parcel.
// WARNING: This must stay in sync with Parcel::readParcelFileDescriptor()
// in frameworks/native/libs/binder/Parcel.cpp
if (mWrapped != null) {
try {
mWrapped.writeToParcel(out, flags);
} finally {
releaseResources();
}
} else {
out.writeFileDescriptor(mFd);
if (mCommFd != null) {
out.writeInt(1);
out.writeFileDescriptor(mCommFd);
} else {
out.writeInt(0);
}
if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
// Not a real close, so emit no status
closeWithStatus(Status.SILENCE, null);
}
}
|