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