blob: 3e90dfc5e901bcd2820470daf46c0eebd5731e9b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
Jeff Sharkeye861b422012-03-01 20:59:22 -080018import java.io.Closeable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019import java.io.File;
20import java.io.FileDescriptor;
21import java.io.FileInputStream;
22import java.io.FileNotFoundException;
23import java.io.FileOutputStream;
24import java.io.IOException;
Chia-chi Yeh47f8f0f2011-05-12 16:23:44 -070025import java.net.DatagramSocket;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import java.net.Socket;
27
28/**
29 * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing
30 * you to close it when done with it.
31 */
Jeff Sharkeye861b422012-03-01 20:59:22 -080032public class ParcelFileDescriptor implements Parcelable, Closeable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033 private final FileDescriptor mFileDescriptor;
34 private boolean mClosed;
35 //this field is to create wrapper for ParcelFileDescriptor using another
36 //PartialFileDescriptor but avoid invoking close twice
37 //consider ParcelFileDescriptor A(fileDescriptor fd), ParcelFileDescriptor B(A)
38 //in this particular case fd.close might be invoked twice.
39 private final ParcelFileDescriptor mParcelDescriptor;
Elliott Hughes43907582011-04-12 14:25:23 -070040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 /**
42 * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
43 * and this file doesn't already exist, then create the file with
44 * permissions such that any application can read it.
45 */
46 public static final int MODE_WORLD_READABLE = 0x00000001;
Elliott Hughes43907582011-04-12 14:25:23 -070047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 /**
49 * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
50 * and this file doesn't already exist, then create the file with
51 * permissions such that any application can write it.
52 */
53 public static final int MODE_WORLD_WRITEABLE = 0x00000002;
Elliott Hughes43907582011-04-12 14:25:23 -070054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 /**
56 * For use with {@link #open}: open the file with read-only access.
57 */
58 public static final int MODE_READ_ONLY = 0x10000000;
Elliott Hughes43907582011-04-12 14:25:23 -070059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 /**
61 * For use with {@link #open}: open the file with write-only access.
62 */
63 public static final int MODE_WRITE_ONLY = 0x20000000;
Elliott Hughes43907582011-04-12 14:25:23 -070064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 /**
66 * For use with {@link #open}: open the file with read and write access.
67 */
68 public static final int MODE_READ_WRITE = 0x30000000;
Elliott Hughes43907582011-04-12 14:25:23 -070069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 /**
71 * For use with {@link #open}: create the file if it doesn't already exist.
72 */
73 public static final int MODE_CREATE = 0x08000000;
Elliott Hughes43907582011-04-12 14:25:23 -070074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 /**
76 * For use with {@link #open}: erase contents of file when opening.
77 */
78 public static final int MODE_TRUNCATE = 0x04000000;
Elliott Hughes43907582011-04-12 14:25:23 -070079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /**
81 * For use with {@link #open}: append to end of file while writing.
82 */
83 public static final int MODE_APPEND = 0x02000000;
Elliott Hughes43907582011-04-12 14:25:23 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 /**
86 * Create a new ParcelFileDescriptor accessing a given file.
Elliott Hughes43907582011-04-12 14:25:23 -070087 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 * @param file The file to be opened.
89 * @param mode The desired access mode, must be one of
90 * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
91 * {@link #MODE_READ_WRITE}; may also be any combination of
92 * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
93 * {@link #MODE_WORLD_READABLE}, and {@link #MODE_WORLD_WRITEABLE}.
Elliott Hughes43907582011-04-12 14:25:23 -070094 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 * @return Returns a new ParcelFileDescriptor pointing to the given
96 * file.
Elliott Hughes43907582011-04-12 14:25:23 -070097 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 * @throws FileNotFoundException Throws FileNotFoundException if the given
99 * file does not exist or can not be opened with the requested mode.
100 */
101 public static ParcelFileDescriptor open(File file, int mode)
102 throws FileNotFoundException {
103 String path = file.getPath();
104 SecurityManager security = System.getSecurityManager();
105 if (security != null) {
106 security.checkRead(path);
107 if ((mode&MODE_WRITE_ONLY) != 0) {
108 security.checkWrite(path);
109 }
110 }
Elliott Hughes43907582011-04-12 14:25:23 -0700111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 if ((mode&MODE_READ_WRITE) == 0) {
113 throw new IllegalArgumentException(
114 "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
115 }
Elliott Hughes43907582011-04-12 14:25:23 -0700116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 FileDescriptor fd = Parcel.openFileDescriptor(path, mode);
Dianne Hackborn18668392010-03-23 22:10:55 -0700118 return fd != null ? new ParcelFileDescriptor(fd) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 }
120
121 /**
Dianne Hackborne17aeb32011-04-07 15:11:57 -0700122 * Create a new ParcelFileDescriptor that is a dup of an existing
123 * FileDescriptor. This obeys standard POSIX semantics, where the
124 * new file descriptor shared state such as file position with the
125 * original file descriptor.
126 */
127 public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException {
128 FileDescriptor fd = Parcel.dupFileDescriptor(orig);
129 return fd != null ? new ParcelFileDescriptor(fd) : null;
130 }
131
132 /**
Dianne Hackborn62f20ec2011-08-15 17:40:28 -0700133 * Create a new ParcelFileDescriptor that is a dup of the existing
134 * FileDescriptor. This obeys standard POSIX semantics, where the
135 * new file descriptor shared state such as file position with the
136 * original file descriptor.
137 */
138 public ParcelFileDescriptor dup() throws IOException {
139 return dup(getFileDescriptor());
140 }
141
142 /**
Dianne Hackbornea2117bd2011-05-20 10:37:34 -0700143 * Create a new ParcelFileDescriptor from a raw native fd. The new
144 * ParcelFileDescriptor holds a dup of the original fd passed in here,
145 * so you must still close that fd as well as the new ParcelFileDescriptor.
146 *
147 * @param fd The native fd that the ParcelFileDescriptor should dup.
148 *
149 * @return Returns a new ParcelFileDescriptor holding a FileDescriptor
150 * for a dup of the given fd.
151 */
152 public static ParcelFileDescriptor fromFd(int fd) throws IOException {
153 FileDescriptor fdesc = getFileDescriptorFromFd(fd);
154 return new ParcelFileDescriptor(fdesc);
155 }
156
157 // Extracts the file descriptor from the specified socket and returns it untouched
158 private static native FileDescriptor getFileDescriptorFromFd(int fd) throws IOException;
159
160 /**
161 * Take ownership of a raw native fd in to a new ParcelFileDescriptor.
162 * The returned ParcelFileDescriptor now owns the given fd, and will be
163 * responsible for closing it. You must not close the fd yourself.
164 *
165 * @param fd The native fd that the ParcelFileDescriptor should adopt.
166 *
167 * @return Returns a new ParcelFileDescriptor holding a FileDescriptor
168 * for the given fd.
169 */
170 public static ParcelFileDescriptor adoptFd(int fd) {
171 FileDescriptor fdesc = getFileDescriptorFromFdNoDup(fd);
172 return new ParcelFileDescriptor(fdesc);
173 }
174
175 // Extracts the file descriptor from the specified socket and returns it untouched
176 private static native FileDescriptor getFileDescriptorFromFdNoDup(int fd);
177
178 /**
179 * Create a new ParcelFileDescriptor from the specified Socket. The new
180 * ParcelFileDescriptor holds a dup of the original FileDescriptor in
181 * the Socket, so you must still close the Socket as well as the new
182 * ParcelFileDescriptor.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 *
184 * @param socket The Socket whose FileDescriptor is used to create
185 * a new ParcelFileDescriptor.
186 *
187 * @return A new ParcelFileDescriptor with the FileDescriptor of the
188 * specified Socket.
189 */
190 public static ParcelFileDescriptor fromSocket(Socket socket) {
Elliott Hughes43907582011-04-12 14:25:23 -0700191 FileDescriptor fd = socket.getFileDescriptor$();
Dianne Hackborn18668392010-03-23 22:10:55 -0700192 return fd != null ? new ParcelFileDescriptor(fd) : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 }
194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 /**
Chia-chi Yeh47f8f0f2011-05-12 16:23:44 -0700196 * Create a new ParcelFileDescriptor from the specified DatagramSocket.
197 *
198 * @param datagramSocket The DatagramSocket whose FileDescriptor is used
199 * to create a new ParcelFileDescriptor.
200 *
201 * @return A new ParcelFileDescriptor with the FileDescriptor of the
202 * specified DatagramSocket.
203 */
204 public static ParcelFileDescriptor fromDatagramSocket(DatagramSocket datagramSocket) {
205 FileDescriptor fd = datagramSocket.getFileDescriptor$();
206 return fd != null ? new ParcelFileDescriptor(fd) : null;
207 }
208
209 /**
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700210 * Create two ParcelFileDescriptors structured as a data pipe. The first
211 * ParcelFileDescriptor in the returned array is the read side; the second
212 * is the write side.
213 */
214 public static ParcelFileDescriptor[] createPipe() throws IOException {
215 FileDescriptor[] fds = new FileDescriptor[2];
Dianne Hackbornea2117bd2011-05-20 10:37:34 -0700216 createPipeNative(fds);
217 ParcelFileDescriptor[] pfds = new ParcelFileDescriptor[2];
218 pfds[0] = new ParcelFileDescriptor(fds[0]);
219 pfds[1] = new ParcelFileDescriptor(fds[1]);
220 return pfds;
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700221 }
222
Dianne Hackbornea2117bd2011-05-20 10:37:34 -0700223 private static native void createPipeNative(FileDescriptor[] outFds) throws IOException;
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700224
225 /**
Dianne Hackborn540f86a2011-01-11 17:52:22 -0800226 * @hide Please use createPipe() or ContentProvider.openPipeHelper().
Bjorn Bringerta006b4722010-04-14 14:43:26 +0100227 * Gets a file descriptor for a read-only copy of the given data.
228 *
229 * @param data Data to copy.
230 * @param name Name for the shared memory area that may back the file descriptor.
231 * This is purely informative and may be {@code null}.
232 * @return A ParcelFileDescriptor.
233 * @throws IOException if there is an error while creating the shared memory area.
234 */
Dianne Hackborna2ea7472010-12-20 12:10:01 -0800235 @Deprecated
Bjorn Bringerta006b4722010-04-14 14:43:26 +0100236 public static ParcelFileDescriptor fromData(byte[] data, String name) throws IOException {
237 if (data == null) return null;
238 MemoryFile file = new MemoryFile(name, data.length);
239 if (data.length > 0) {
240 file.writeBytes(data, 0, 0, data.length);
241 }
242 file.deactivate();
243 FileDescriptor fd = file.getFileDescriptor();
244 return fd != null ? new ParcelFileDescriptor(fd) : null;
245 }
246
247 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 * Retrieve the actual FileDescriptor associated with this object.
Elliott Hughes43907582011-04-12 14:25:23 -0700249 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 * @return Returns the FileDescriptor associated with this object.
251 */
252 public FileDescriptor getFileDescriptor() {
253 return mFileDescriptor;
254 }
Elliott Hughes43907582011-04-12 14:25:23 -0700255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 /**
257 * Return the total size of the file representing this fd, as determined
258 * by stat(). Returns -1 if the fd is not a file.
259 */
260 public native long getStatSize();
Elliott Hughes43907582011-04-12 14:25:23 -0700261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 /**
263 * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream,
264 * and I really don't think we want it to be public.
265 * @hide
266 */
267 public native long seekTo(long pos);
Elliott Hughes43907582011-04-12 14:25:23 -0700268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 /**
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800270 * Return the native fd int for this ParcelFileDescriptor. The
271 * ParcelFileDescriptor still owns the fd, and it still must be closed
272 * through this API.
273 */
274 public int getFd() {
275 if (mClosed) {
276 throw new IllegalStateException("Already closed");
277 }
278 return getFdNative();
279 }
Elliott Hughes43907582011-04-12 14:25:23 -0700280
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800281 private native int getFdNative();
Elliott Hughes43907582011-04-12 14:25:23 -0700282
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800283 /**
284 * Return the native fd int for this ParcelFileDescriptor and detach it
285 * from the object here. You are now responsible for closing the fd in
286 * native code.
287 */
288 public int detachFd() {
289 if (mClosed) {
290 throw new IllegalStateException("Already closed");
291 }
292 if (mParcelDescriptor != null) {
293 int fd = mParcelDescriptor.detachFd();
294 mClosed = true;
295 return fd;
296 }
297 int fd = getFd();
298 mClosed = true;
299 Parcel.clearFileDescriptor(mFileDescriptor);
300 return fd;
301 }
Elliott Hughes43907582011-04-12 14:25:23 -0700302
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800303 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 * Close the ParcelFileDescriptor. This implementation closes the underlying
305 * OS resources allocated to represent this stream.
Elliott Hughes43907582011-04-12 14:25:23 -0700306 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 * @throws IOException
308 * If an error occurs attempting to close this ParcelFileDescriptor.
309 */
310 public void close() throws IOException {
Dianne Hackborn18668392010-03-23 22:10:55 -0700311 synchronized (this) {
312 if (mClosed) return;
313 mClosed = true;
314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 if (mParcelDescriptor != null) {
316 // If this is a proxy to another file descriptor, just call through to its
317 // close method.
318 mParcelDescriptor.close();
319 } else {
320 Parcel.closeFileDescriptor(mFileDescriptor);
321 }
322 }
Elliott Hughes43907582011-04-12 14:25:23 -0700323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 /**
325 * An InputStream you can create on a ParcelFileDescriptor, which will
326 * take care of calling {@link ParcelFileDescriptor#close
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700327 * ParcelFileDescriptor.close()} for you when the stream is closed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 */
329 public static class AutoCloseInputStream extends FileInputStream {
330 private final ParcelFileDescriptor mFd;
Elliott Hughes43907582011-04-12 14:25:23 -0700331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 public AutoCloseInputStream(ParcelFileDescriptor fd) {
333 super(fd.getFileDescriptor());
334 mFd = fd;
335 }
336
337 @Override
338 public void close() throws IOException {
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700339 try {
340 mFd.close();
341 } finally {
342 super.close();
343 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 }
345 }
Elliott Hughes43907582011-04-12 14:25:23 -0700346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 /**
348 * An OutputStream you can create on a ParcelFileDescriptor, which will
349 * take care of calling {@link ParcelFileDescriptor#close
Christopher Tatefa9e7c02010-05-06 12:07:10 -0700350 * ParcelFileDescriptor.close()} for you when the stream is closed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 */
352 public static class AutoCloseOutputStream extends FileOutputStream {
353 private final ParcelFileDescriptor mFd;
Elliott Hughes43907582011-04-12 14:25:23 -0700354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 public AutoCloseOutputStream(ParcelFileDescriptor fd) {
356 super(fd.getFileDescriptor());
357 mFd = fd;
358 }
359
360 @Override
361 public void close() throws IOException {
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700362 try {
363 mFd.close();
364 } finally {
365 super.close();
366 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 }
368 }
Elliott Hughes43907582011-04-12 14:25:23 -0700369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 @Override
371 public String toString() {
372 return "{ParcelFileDescriptor: " + mFileDescriptor + "}";
373 }
Elliott Hughes43907582011-04-12 14:25:23 -0700374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 @Override
376 protected void finalize() throws Throwable {
377 try {
378 if (!mClosed) {
379 close();
380 }
381 } finally {
382 super.finalize();
383 }
384 }
Elliott Hughes43907582011-04-12 14:25:23 -0700385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
387 super();
388 mParcelDescriptor = descriptor;
389 mFileDescriptor = mParcelDescriptor.mFileDescriptor;
390 }
Elliott Hughes43907582011-04-12 14:25:23 -0700391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 /*package */ParcelFileDescriptor(FileDescriptor descriptor) {
393 super();
Dianne Hackborn18668392010-03-23 22:10:55 -0700394 if (descriptor == null) {
395 throw new NullPointerException("descriptor must not be null");
396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 mFileDescriptor = descriptor;
398 mParcelDescriptor = null;
399 }
Elliott Hughes43907582011-04-12 14:25:23 -0700400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 /* Parcelable interface */
402 public int describeContents() {
403 return Parcelable.CONTENTS_FILE_DESCRIPTOR;
404 }
405
Dan Egnorb3e4ef32010-07-20 09:03:35 -0700406 /**
407 * {@inheritDoc}
408 * If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags,
409 * the file descriptor will be closed after a copy is written to the Parcel.
410 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 public void writeToParcel(Parcel out, int flags) {
412 out.writeFileDescriptor(mFileDescriptor);
413 if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
414 try {
415 close();
416 } catch (IOException e) {
417 // Empty
418 }
419 }
420 }
421
422 public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR
423 = new Parcelable.Creator<ParcelFileDescriptor>() {
424 public ParcelFileDescriptor createFromParcel(Parcel in) {
425 return in.readFileDescriptor();
426 }
427 public ParcelFileDescriptor[] newArray(int size) {
428 return new ParcelFileDescriptor[size];
429 }
430 };
431
432}