1f859444a27667fc152cdbfd25dd7a67aedeaa8c0Shubham Ajmera/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.channels.FileChannel;
305873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath
31e31b37859051d3902e06e4ba384995df7188917fHans Boehmimport dalvik.annotation.optimization.ReachabilitySensitive;
325873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamathimport dalvik.system.BlockGuard;
339bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamathimport dalvik.system.CloseGuard;
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.nio.ch.FileChannelImpl;
3502df4b384e42969ad6f9e211989698e4f9fcde6ePrzemyslaw Szczepaniakimport libcore.io.IoBridge;
36118de16ee0529955eaca8cc5ce864cac49598c86Shubham Ajmeraimport libcore.io.IoTracker;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A file output stream is an output stream for writing data to a
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a file is available or may be created depends upon the underlying
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * platform.  Some platforms, in particular, allow a file to be opened
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for writing by only one <tt>FileOutputStream</tt> (or other
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * file-writing object) at a time.  In such situations the constructors in
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this class will fail if the file involved is already open.
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * such as image data. For writing streams of characters, consider using
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>FileWriter</code>.
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author  Arthur van Hoff
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see     java.io.File
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see     java.io.FileDescriptor
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see     java.io.FileInputStream
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see     java.nio.file.Files#newOutputStream
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since   JDK1.0
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass FileOutputStream extends OutputStream
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The system dependent file descriptor.
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
64e31b37859051d3902e06e4ba384995df7188917fHans Boehm    // Android-added: @ReachabilitySensitive
65e31b37859051d3902e06e4ba384995df7188917fHans Boehm    @ReachabilitySensitive
66e59e4c9b59318851e4366ecc732db45ac9e061b0Yi Kong    private final FileDescriptor fd;
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * True if the file is opened for append.
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final boolean append;
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
744c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * The associated channel, initialized lazily.
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private FileChannel channel;
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
784c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    /**
794c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * The path of the referenced file
804c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * (null if the stream is created with a file descriptor)
814c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     */
824c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    private final String path;
834c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak
84c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private final Object closeLock = new Object();
85c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private volatile boolean closed = false;
86c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
87c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-added: CloseGuard support: Log if the stream is not closed.
88e31b37859051d3902e06e4ba384995df7188917fHans Boehm    @ReachabilitySensitive
899bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath    private final CloseGuard guard = CloseGuard.get();
90c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
91c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-added: Field for tracking whether the stream owns the underlying FileDescriptor.
92b5738be1ca73734ab71a62b537e67bcbbf502f09Przemyslaw Szczepaniak    private final boolean isFdOwner;
93c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
94c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-added: Tracking of unbuffered I/O.
95118de16ee0529955eaca8cc5ce864cac49598c86Shubham Ajmera    private final IoTracker tracker = new IoTracker();
969bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a file output stream to write to the file with the
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * specified name. A new <code>FileDescriptor</code> object is
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * created to represent this file connection.
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * First, if there is a security manager, its <code>checkWrite</code>
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with <code>name</code> as its argument.
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the file exists but is a directory rather than a regular file, does
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not exist but cannot be created, or cannot be opened for any other
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reason then a <code>FileNotFoundException</code> is thrown.
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      name   the system-dependent filename
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  FileNotFoundException  if the file exists but is a directory
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   rather than a regular file, does not exist but cannot
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   be created, or cannot be opened for any other reason
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException  if a security manager exists and its
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               <code>checkWrite</code> method denies write access
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               to the file.
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileOutputStream(String name) throws FileNotFoundException {
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(name != null ? new File(name) : null, false);
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a file output stream to write to the file with the specified
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * name.  If the second argument is <code>true</code>, then
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * bytes will be written to the end of the file rather than the beginning.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * A new <code>FileDescriptor</code> object is created to represent this
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * file connection.
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * First, if there is a security manager, its <code>checkWrite</code>
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with <code>name</code> as its argument.
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the file exists but is a directory rather than a regular file, does
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not exist but cannot be created, or cannot be opened for any other
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reason then a <code>FileNotFoundException</code> is thrown.
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param     name        the system-dependent file name
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param     append      if <code>true</code>, then bytes will be written
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   to the end of the file rather than the beginning
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  FileNotFoundException  if the file exists but is a directory
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   rather than a regular file, does not exist but cannot
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   be created, or cannot be opened for any other reason.
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException  if a security manager exists and its
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               <code>checkWrite</code> method denies write access
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               to the file.
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since     JDK1.1
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileOutputStream(String name, boolean append)
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws FileNotFoundException
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(name != null ? new File(name) : null, append);
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a file output stream to write to the file represented by
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the specified <code>File</code> object. A new
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>FileDescriptor</code> object is created to represent this
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * file connection.
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * First, if there is a security manager, its <code>checkWrite</code>
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with the path represented by the <code>file</code>
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * argument as its argument.
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the file exists but is a directory rather than a regular file, does
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not exist but cannot be created, or cannot be opened for any other
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reason then a <code>FileNotFoundException</code> is thrown.
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      file               the file to be opened for writing.
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  FileNotFoundException  if the file exists but is a directory
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   rather than a regular file, does not exist but cannot
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   be created, or cannot be opened for any other reason
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException  if a security manager exists and its
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               <code>checkWrite</code> method denies write access
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               to the file.
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.io.File#getPath()
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityException
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileOutputStream(File file) throws FileNotFoundException {
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(file, false);
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a file output stream to write to the file represented by
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the specified <code>File</code> object. If the second argument is
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>true</code>, then bytes will be written to the end of the file
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * rather than the beginning. A new <code>FileDescriptor</code> object is
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * created to represent this file connection.
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * First, if there is a security manager, its <code>checkWrite</code>
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with the path represented by the <code>file</code>
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * argument as its argument.
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If the file exists but is a directory rather than a regular file, does
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not exist but cannot be created, or cannot be opened for any other
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * reason then a <code>FileNotFoundException</code> is thrown.
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      file               the file to be opened for writing.
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param     append      if <code>true</code>, then bytes will be written
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   to the end of the file rather than the beginning
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  FileNotFoundException  if the file exists but is a directory
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   rather than a regular file, does not exist but cannot
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                   be created, or cannot be opened for any other reason
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  SecurityException  if a security manager exists and its
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               <code>checkWrite</code> method denies write access
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *               to the file.
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.io.File#getPath()
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityException
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileOutputStream(File file, boolean append)
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws FileNotFoundException
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String name = (file != null ? file.getPath() : null);
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SecurityManager security = System.getSecurityManager();
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (security != null) {
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            security.checkWrite(name);
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (name == null) {
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (file.isInvalid()) {
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new FileNotFoundException("Invalid file path");
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fd = new FileDescriptor();
227c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
228c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: Tracking mechanism for FileDescriptor sharing.
229c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // fd.attach(this);
230c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        this.isFdOwner = true;
231c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.append = append;
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.path = name;
2345873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath
235c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: BlockGuard support.
2365873edf853a48362e8ee4e75181f654d0b88b8efNarayan Kamath        BlockGuard.getThreadPolicy().onWriteToDisk();
237c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        open(name, append);
239c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
240c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: CloseGuard support.
2419bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath        guard.open("close");
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
244c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-removed: Documentation around SecurityException. Not thrown on Android.
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a file output stream to write to the specified file
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * descriptor, which represents an existing connection to an actual
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * file in the file system.
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * First, if there is a security manager, its <code>checkWrite</code>
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * method is called with the file descriptor <code>fdObj</code>
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * argument as its argument.
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If <code>fdObj</code> is null then a <code>NullPointerException</code>
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is thrown.
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This constructor does not throw an exception if <code>fdObj</code>
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is {@link java.io.FileDescriptor#valid() invalid}.
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * However, if the methods are invoked on the resulting stream to attempt
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * I/O on the stream, an <code>IOException</code> is thrown.
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      fdObj   the file descriptor to be opened for writing
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileOutputStream(FileDescriptor fdObj) {
265c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: Delegate to added hidden constructor.
266e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath        this(fdObj, false /* isOwner */);
267e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath    }
268e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath
269c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-added: Internal/hidden constructor for specifying FileDescriptor ownership.
270c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-removed: SecurityManager calls.
271e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath    /**
272e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath     * Internal constructor for {@code FileOutputStream} objects where the file descriptor
273e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath     * is owned by this tream.
274e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath     *
275e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath     * @hide
276e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath     */
277e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath    public FileOutputStream(FileDescriptor fdObj, boolean isFdOwner) {
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fdObj == null) {
279c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller            // Android-changed: Improved NullPointerException message.
280e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath            throw new NullPointerException("fdObj == null");
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
282e9d215bb0811633791ca53199922a8d5512de224Narayan Kamath
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.fd = fdObj;
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.append = false;
285c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        this.path = null;
286c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
287c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: FileDescriptor ownership tracking mechanism.
288c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // fd.attach(this);
289b5738be1ca73734ab71a62b537e67bcbbf502f09Przemyslaw Szczepaniak        this.isFdOwner = isFdOwner;
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Opens a file, with the specified name, for overwriting or appending.
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param name name of file to be opened
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param append whether the file is to be opened in append mode
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
2974c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    private native void open0(String name, boolean append)
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws FileNotFoundException;
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3004c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    // wrap native call to allow instrumentation
3014c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    /**
3024c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * Opens a file, with the specified name, for overwriting or appending.
3034c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * @param name name of file to be opened
3044c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * @param append whether the file is to be opened in append mode
3054c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     */
3064c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    private void open(String name, boolean append)
3074c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak        throws FileNotFoundException {
3084c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak        open0(name, append);
3094c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak    }
3104c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak
311c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-removed: write(int, boolean), use IoBridge instead.
312c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    /*
313c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    /**
314c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * Writes the specified byte to this file output stream.
315c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     *
316c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param   b   the byte to be written.
317c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param   append   {@code true} if the write operation first
318c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     *     advances the position to the end of file
319c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     *
320c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private native void write(int b, boolean append) throws IOException;
321c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    */
322c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Writes the specified byte to this file output stream. Implements
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the <code>write</code> method of <code>OutputStream</code>.
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      b   the byte to be written.
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void write(int b) throws IOException {
331c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: Write methods delegate to write(byte[],int,int) to share Android logic.
33202df4b384e42969ad6f9e211989698e4f9fcde6ePrzemyslaw Szczepaniak        write(new byte[] { (byte) b }, 0, 1);
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
335c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // Android-removed: Write methods delegate to write(byte[],int,int) to share Android logic.
336c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    /*
337c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    /**
338c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * Writes a sub array as a sequence of bytes.
339c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param b the data to be written
340c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param off the start offset in the data
341c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param len the number of bytes that are written
342c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @param append {@code true} to first advance the position to the
343c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     *     end of file
344c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     * @exception IOException If an I/O error has occurred.
345c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller     *
346c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private native void writeBytes(byte b[], int off, int len, boolean append)
347c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        throws IOException;
348c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    */
349c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Writes <code>b.length</code> bytes from the specified byte array
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to this file output stream.
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      b   the data.
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void write(byte b[]) throws IOException {
358c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: Write methods delegate to write(byte[],int,int) to share Android logic.
35902df4b384e42969ad6f9e211989698e4f9fcde6ePrzemyslaw Szczepaniak        write(b, 0, b.length);
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Writes <code>len</code> bytes from the specified byte array
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * starting at offset <code>off</code> to this file output stream.
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      b     the data.
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      off   the start offset in the data.
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      len   the number of bytes to write.
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void write(byte b[], int off, int len) throws IOException {
372c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: close() check before I/O.
37350164c3602af46021e434ff5047352299a36e0f0Yi Kong        if (closed && len > 0) {
37450164c3602af46021e434ff5047352299a36e0f0Yi Kong            throw new IOException("Stream Closed");
37550164c3602af46021e434ff5047352299a36e0f0Yi Kong        }
376c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
377c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: Tracking of unbuffered I/O.
378118de16ee0529955eaca8cc5ce864cac49598c86Shubham Ajmera        tracker.trackIo(len);
379c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
380c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-changed: Use IoBridge instead of calling native method.
381118de16ee0529955eaca8cc5ce864cac49598c86Shubham Ajmera        IoBridge.write(fd, b, off, len);
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Closes this file output stream and releases any system resources
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with this stream. This file output stream may no longer
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * be used for writing bytes.
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> If this stream has an associated channel then the channel is closed
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * as well.
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @revised 1.4
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @spec JSR-51
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void close() throws IOException {
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (closeLock) {
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (closed) {
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            closed = true;
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
405c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: CloseGuard support.
4069bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath        guard.close();
4079bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (channel != null) {
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            channel.close();
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
412c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // BEGIN Android-changed: Close handling / notification of blocked threads.
413b5738be1ca73734ab71a62b537e67bcbbf502f09Przemyslaw Szczepaniak        if (isFdOwner) {
41402df4b384e42969ad6f9e211989698e4f9fcde6ePrzemyslaw Szczepaniak            IoBridge.closeAndSignalBlockedThreads(fd);
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
416c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // END Android-changed: Close handling / notification of blocked threads.
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the file descriptor associated with this stream.
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the <code>FileDescriptor</code> object that represents
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          the connection to the file in the file system being used
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          by this <code>FileOutputStream</code> object.
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.io.FileDescriptor
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
429e31b37859051d3902e06e4ba384995df7188917fHans Boehm     // Android-added: @ReachabilitySensitive
430e31b37859051d3902e06e4ba384995df7188917fHans Boehm     @ReachabilitySensitive
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     public final FileDescriptor getFD()  throws IOException {
4324c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak        if (fd != null) {
4334c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak            return fd;
4344c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak        }
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throw new IOException();
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     }
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
4404c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * object associated with this file output stream.
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p> The initial {@link java.nio.channels.FileChannel#position()
4434c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak     * position} of the returned channel will be equal to the
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * number of bytes written to the file so far unless this stream is in
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * append mode, in which case it will be equal to the size of the file.
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Writing bytes to this stream will increment the channel's position
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * accordingly.  Changing the channel's position, either explicitly or by
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * writing, will change this stream's file position.
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return  the file channel associated with this file output stream
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @spec JSR-51
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public FileChannel getChannel() {
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        synchronized (this) {
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (channel == null) {
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                channel = FileChannelImpl.open(fd, path, false, true, append, this);
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return channel;
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Cleans up the connection to the file, and ensures that the
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>close</code> method of this file output stream is
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * called when there are no more references to this stream.
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see        java.io.FileInputStream#close()
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void finalize() throws IOException {
473c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        // Android-added: CloseGuard support.
4749bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath        if (guard != null) {
4759bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath            guard.warnIfOpen();
4769bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath        }
4779bd6371468aac3ddaa7057127d5ef152aea1227dNarayan Kamath
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fd != null) {
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                flush();
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
482c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller                // Android-removed: Obsoleted comment about shared FileDescriptor handling.
4839c3a641e294abdaadda9299a2e1b49863de45ed9Narayan Kamath                close();
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
487c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
488c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // BEGIN Android-removed: Unused code.
489c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    /*
490c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private native void close0() throws IOException;
491c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
492c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    private static native void initIDs();
493c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
494c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    static {
495c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller        initIDs();
496c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    }
497c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    */
498c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller    // END Android-removed: Unused code.
499c52f3fe3ba9e1d31e27c06f45bfc44c2aa8a8f96Neil Fuller
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
501