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