1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
19d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson * Android Notice
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In this class the address length was changed from long to int.
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is due to performance optimizations for the device.
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Also this class was copied from a newer version of harmony.
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.nio.internal;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Closeable;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FileDescriptor;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.ByteBuffer;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.MappedByteBuffer;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.ClosedChannelException;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.FileChannel;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.FileLock;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.NonWritableChannelException;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.ReadableByteChannel;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.nio.channels.WritableByteChannel;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.platform.IFileSystem;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.platform.Platform;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.platform.PlatformAddress;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.luni.platform.PlatformAddressFactory;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.nio.internal.nls.Messages;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The file channel impl class is the bridge between the logical channels
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * described by the NIO channel framework, and the file system implementation
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * provided by the port layer.
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class is non-API, but implements the API of the FileChannel interface.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class FileChannelImpl extends FileChannel {
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Reference to the portable file system code.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final IFileSystem fileSystem = Platform.getFileSystem();
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int ALLOC_GRANULARITY;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static {
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ALLOC_GRANULARITY = fileSystem.getAllocGranularity();
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IOException e) {
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new Error(e);
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Handle to the open file
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int handle;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // The object that will track all outstanding locks on this channel.
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LockManager lockManager = new LockManager();
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson    private static class RepositioningLock {}
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Object repositioningLock = new RepositioningLock();
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Object stream;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new file channel implementation class that wraps the given file
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * handle and operates in the specified mode.
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public FileChannelImpl(Object stream, int handle) {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super();
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.handle = handle;
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.stream = stream;
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper method to throw an exception if the channel is already closed.
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that we don't bother to synchronize on this test since the file may
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * be closed by operations beyond our control anyways.
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final void openCheck() throws ClosedChannelException {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!isOpen()) {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new ClosedChannelException();
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (non-Javadoc)
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void implCloseChannel() throws IOException {
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stream instanceof Closeable) {
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((Closeable) stream).close();
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected FileLock basicLock(long position, long size, boolean shared,
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean wait) throws IOException {
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((position < 0) || (size < 0)) {
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // nio.0A=Lock position and size must be non-negative.
117d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson            throw new IllegalArgumentException(Messages.getString("nio.0A")); //$NON-NLS-1$
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lockType = shared ? IFileSystem.SHARED_LOCK_TYPE
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                : IFileSystem.EXCLUSIVE_LOCK_TYPE;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FileLock pendingLock = new FileLockImpl(this, position, size, shared);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockManager.addLock(pendingLock);
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (fileSystem.lock(handle, position, size, lockType, wait)) {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return pendingLock;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Lock acquisition failed
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockManager.removeLock(pendingLock);
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Acquire a lock on the receiver, blocks if the lock cannot be obtained
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * immediately.
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.nio.channels.FileChannel#lock(long, long, boolean)
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final FileLock lock(long position, long size, boolean shared)
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FileLock resultLock = null;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean completed = false;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                begin();
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resultLock = basicLock(position, size, shared, true);
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                completed = true;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                end(completed);
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return resultLock;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Attempts to acquire the given lock, but does not block. If the lock
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cannot be acquired the method returns null.
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.nio.channels.FileChannel#tryLock(long, long, boolean)
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final FileLock tryLock(long position, long size, boolean shared)
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return basicLock(position, size, shared, false);
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Non-API method to release a given lock on a file channel. Assumes that
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the lock will mark itself invalid after successful unlocking.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void release(FileLock lock) throws IOException {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fileSystem.unlock(handle, lock.position(), lock.size());
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        lockManager.removeLock(lock);
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Flush the contents of the file to disk, and the metadata if asked.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void force(boolean metadata) throws IOException {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Forcing data-only on a read-only file is a no-op.
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (metadata) {
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileSystem.fflush(handle, metadata);
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract MappedByteBuffer map(MapMode mode, long position, long size)
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final MappedByteBuffer mapImpl(int mapMode, long position,
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long size) throws IOException {
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (position + size > size()) {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileSystem.truncate(handle, position + size);
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long alignment = position - position % ALLOC_GRANULARITY;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int offset = (int) (position - alignment);
199d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        PlatformAddress address = PlatformAddressFactory.allocMap(handle,
200d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                alignment, size + offset, mapMode);
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MappedByteBuffer buffer = null;
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buffer = MappedByteBufferFactory.getBuffer(address, mapMode, size,
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    offset);
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IOException(e.getMessage());
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return buffer;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the current file position.
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long position() throws IOException {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return fileSystem.seek(handle, 0L, IFileSystem.SEEK_CUR);
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the file pointer.
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public FileChannel position(long newPosition) throws IOException {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newPosition < 0) {
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // nio.0B=New position must be non-negative.
226d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson            throw new IllegalArgumentException(Messages.getString("nio.0B")); //$NON-NLS-1$
227d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        }
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileSystem.seek(handle, newPosition, IFileSystem.SEEK_SET);
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return this;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read(ByteBuffer buffer, long position) throws IOException {
236d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (null == buffer) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException();
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
239d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (position < 0) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException();
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
243d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (!buffer.hasRemaining()) {
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int bytesRead = 0;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long preReadPosition = position();
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            position(position);
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                bytesRead = read(buffer);
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                position(preReadPosition);
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return bytesRead;
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read(ByteBuffer buffer) throws IOException {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
261d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (!buffer.hasRemaining()) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean completed = false;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int bytesRead = 0;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (buffer.isDirect()) {
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DirectBuffer directBuffer = (DirectBuffer) buffer;
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int address = directBuffer.getEffectiveAddress().toInt();
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    begin();
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
273d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                     * if (bytesRead <= EOF) dealt by read completed = false;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRead = (int) fileSystem.readDirect(handle, address,
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            buffer.position(), buffer.remaining());
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    completed = true;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } finally {
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    end(completed && bytesRead >= 0);
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    begin();
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
285d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                     * if (bytesRead <= EOF) dealt by read completed = false;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRead = (int) fileSystem.read(handle, buffer.array(),
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            buffer.arrayOffset() + buffer.position(), buffer
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    .remaining());
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    completed = true;
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } finally {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    end(completed && bytesRead >= 0);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bytesRead > 0) {
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer.position(buffer.position() + bytesRead);
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytesRead;
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long read(ByteBuffer[] buffers, int offset, int length)
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = 0;
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (offset < 0 || length < 0 || offset + length > buffers.length) {
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IndexOutOfBoundsException();
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = offset; i < offset + length; i++) {
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count += buffers[i].remaining();
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (0 == count) {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (size() == 0) {
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteBuffer[] directBuffers = new ByteBuffer[length];
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] handles = new int[length];
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] offsets = new int[length];
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] lengths = new int[length];
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < length; i++) {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ByteBuffer buffer = buffers[i + offset];
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!buffer.isDirect()) {
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer = ByteBuffer.allocateDirect(buffer.remaining());
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                directBuffers[i] = buffer;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                offsets[i] = 0;
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                offsets[i] = buffer.position();
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toInt();
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lengths[i] = buffer.remaining();
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long bytesRead = 0;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean completed = false;
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                begin();
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                synchronized (repositioningLock) {
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRead = fileSystem.readv(handle, handles, offsets,
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            lengths, length);
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                completed = true;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
346d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                 * if (bytesRead < EOF) //dealt by readv? completed = false;
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                end(completed);
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int end = offset + length;
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long bytesRemaining = bytesRead;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = offset; i < end && bytesRemaining > 0; i++) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (buffers[i].isDirect()) {
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (lengths[i] < bytesRemaining) {
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int pos = buffers[i].limit();
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    buffers[i].position(pos);
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRemaining -= lengths[i];
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int pos = (int) bytesRemaining;
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    buffers[i].position(pos);
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ByteBuffer buf = directBuffers[i - offset];
367d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                if (bytesRemaining < buf.remaining()) {
368d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                    // this is the last step.
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int pos = buf.position();
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    buffers[i].put(buf);
371d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                    buffers[i].position(pos + (int) bytesRemaining);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRemaining = 0;
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesRemaining -= buf.remaining();
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    buffers[i].put(buf);
376d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                }
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytesRead;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the current file size, as an integer number of bytes.
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long size() throws IOException {
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long currentPosition = fileSystem.seek(handle, 0L,
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    IFileSystem.SEEK_CUR);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long endOfFilePosition = fileSystem.seek(handle, 0L,
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    IFileSystem.SEEK_END);
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileSystem.seek(handle, currentPosition, IFileSystem.SEEK_SET);
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return endOfFilePosition;
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long transferFrom(ReadableByteChannel src, long position, long count)
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!src.isOpen()) {
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new ClosedChannelException();
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
403d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (position < 0 || count < 0 || count > Integer.MAX_VALUE) {
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException();
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
406d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (position > size()) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
409d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteBuffer buffer = null;
411d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (src instanceof FileChannel) {
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                FileChannel fileSrc = (FileChannel) src;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long size = fileSrc.size();
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long filePosition = fileSrc.position();
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                count = Math.min(count, size - filePosition);
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer = fileSrc.map(MapMode.READ_ONLY, filePosition, count);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fileSrc.position(filePosition + count);
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer = ByteBuffer.allocateDirect((int) count);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                src.read(buffer);
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer.flip();
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return write(buffer, position);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } finally {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // unmap the buffer
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (buffer != null) {
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // all children of FileChannelImpl currently returns
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // an instance of DirectBuffer from map() method
431d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson                ((DirectBuffer) buffer).free();
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long transferTo(long position, long count, WritableByteChannel target)
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!target.isOpen()) {
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new ClosedChannelException();
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (target instanceof ReadOnlyFileChannel) {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NonWritableChannelException();
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
445d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (position < 0 || count < 0) {
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException();
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
448d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count == 0 || position >= size()) {
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteBuffer buffer = null;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        count = Math.min(count, size() - position);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (target instanceof SocketChannelImpl) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // only socket can be transfered by system call
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return kernelTransfer(handle, ((SocketChannelImpl) target).getFD(),
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    position, count);
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
459d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            buffer = map(MapMode.READ_ONLY, position, count);
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return target.write(buffer);
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } finally {
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // unmap the buffer
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (buffer != null) {
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // all children of FileChannelImpl currently returns
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // an instance of DirectBuffer from map() method
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ((DirectBuffer) buffer).free();
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private long kernelTransfer(int l, FileDescriptor fd, long position,
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long count) throws IOException {
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean completed = false;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            begin();
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long ret = fileSystem.transfer(l, fd, position, count);
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            completed = true;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return ret;
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } finally {
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            end(completed);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public FileChannel truncate(long size) throws IOException {
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (size < 0) {
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException();
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (size < size()) {
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            synchronized (repositioningLock) {
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long position = position();
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fileSystem.truncate(handle, size);
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * FIXME: currently the port library always modifies the
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * position to given size. not sure it is a bug or intended
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * behaviour, so I always reset the position to proper value as
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Java Spec.
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                position(position > size ? size : position);
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return this;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (non-Javadoc)
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int write(ByteBuffer buffer, long position) throws IOException {
514d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (null == buffer) {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException();
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
517d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (position < 0) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException();
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
521d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson        if (!buffer.hasRemaining()) {
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int bytesWritten = 0;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long preWritePosition = position();
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            position(position);
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                bytesWritten = writeImpl(buffer);
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                position(preWritePosition);
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytesWritten;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int write(ByteBuffer buffer) throws IOException {
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return writeImpl(buffer);
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int writeImpl(ByteBuffer buffer) throws IOException {
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int bytesWritten;
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean completed = false;
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (buffer.isDirect()) {
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                DirectBuffer directBuffer = (DirectBuffer) buffer;
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int address = directBuffer.getEffectiveAddress().toInt();
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    begin();
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesWritten = (int) fileSystem.writeDirect(handle,
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            address, buffer.position(), buffer.remaining());
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    completed = true;
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } finally {
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    end(completed);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    begin();
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bytesWritten = (int) fileSystem.write(handle, buffer
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            .array(), buffer.arrayOffset() + buffer.position(),
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            buffer.remaining());
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    completed = true;
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } finally {
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    end(completed);
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bytesWritten > 0) {
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer.position(buffer.position() + bytesWritten);
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytesWritten;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long write(ByteBuffer[] buffers, int offset, int length)
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (offset < 0 || length < 0 || (offset + length) > buffers.length) {
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IndexOutOfBoundsException();
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        openCheck();
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = 0;
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = offset; i < offset + length; i++) {
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            count += buffers[i].remaining();
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (0 == count) {
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 0;
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] handles = new int[length];
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] offsets = new int[length];
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] lengths = new int[length];
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-changed
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // list of allocated direct ByteBuffers to prevent them from being GC-ed
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DirectBuffer[] allocatedBufs = new DirectBuffer[length];
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < length; i++) {
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ByteBuffer buffer = buffers[i + offset];
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!buffer.isDirect()) {
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ByteBuffer directBuffer = ByteBuffer.allocateDirect(buffer
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        .remaining());
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                directBuffer.put(buffer);
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                directBuffer.flip();
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer = directBuffer;
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                allocatedBufs[i] = (DirectBuffer) directBuffer;
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                offsets[i] = 0;
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                offsets[i] = buffer.position();
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                allocatedBufs[i] = null;
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toInt();
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lengths[i] = buffer.remaining();
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-changed
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long bytesWritten = 0;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean completed = false;
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (repositioningLock) {
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                begin();
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                bytesWritten = fileSystem.writev(handle, handles, offsets,
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        lengths, length);
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                completed = true;
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                end(completed);
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // BEGIN android-added
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // free temporary direct buffers
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int i = 0; i < length; ++i) {
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (allocatedBufs[i] != null) {
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        allocatedBufs[i].free();
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // END android-added
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        long bytesRemaining = bytesWritten;
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = offset; i < length + offset; i++) {
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bytesRemaining > buffers[i].remaining()) {
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int pos = buffers[i].limit();
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffers[i].position(pos);
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                bytesRemaining -= buffers[i].remaining();
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int pos = buffers[i].position() + (int) bytesRemaining;
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffers[i].position(pos);
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytesWritten;
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
649d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson
650d2510429e70ab91a04c67d5ca39b30f354eba221Jesse Wilson    public int getHandle() {
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return handle;
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
654