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