Merge "java/io/RandomAccessFile: do not nullify FileChannel when closing the RAF"
diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java
index da99765..0e4fa4f 100644
--- a/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/luni/src/main/java/java/io/RandomAccessFile.java
@@ -160,7 +160,6 @@
         synchronized (this) {
             if (channel != null && channel.isOpen()) {
                 channel.close();
-                channel = null;
             }
             IoBridge.closeAndSignalBlockedThreads(fd);
         }
@@ -185,6 +184,10 @@
      * changes made to this file's file pointer offset are also visible in the
      * file channel's position and vice versa.
      *
+     * Closing the channel closes the RandomAccessFile as well. The instance
+     * of FileChannel returned is always the same even if the RandomAccessFile
+     * or the FileChannel have been closed.
+     *
      * @return this file's file channel instance.
      */
     public final synchronized FileChannel getChannel() {
diff --git a/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java b/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java
index afe49b7..8d99457 100644
--- a/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java
+++ b/luni/src/test/java/libcore/java/io/RandomAccessFileTest.java
@@ -20,6 +20,8 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+
 import junit.framework.TestCase;
 import libcore.java.lang.ref.FinalizationTester;
 
@@ -73,6 +75,61 @@
             FinalizationTester.induceFinalization();
         }
     }
+
+    // http://b/19892782
+    public void testCloseRaf_sameChannelReturned() throws Exception {
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
+
+        FileChannel fileChannelBeforeClosing = raf.getChannel();
+        raf.close();
+        FileChannel fileChannelAfterClosing = raf.getChannel();
+        assertSame(fileChannelBeforeClosing, fileChannelAfterClosing);
+    }
+
+    // http://b/19892782
+    public void testCloseRaf_channelIsClosed() throws Exception {
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
+
+        FileChannel fileChannelBeforeClosing = raf.getChannel();
+        raf.close();
+        FileChannel fileChannelAfterClosing = raf.getChannel();
+        assertFalse(fileChannelBeforeClosing.isOpen());
+    }
+
+    // http://b/19892782
+    public void testCloseFileChannel_sameChannelReturned() throws Exception {
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
+
+        FileChannel fileChannelBeforeClosing = raf.getChannel();
+        fileChannelBeforeClosing.close();
+
+        FileChannel fileChannelAfterClosing = raf.getChannel();
+        assertSame(fileChannelBeforeClosing, fileChannelAfterClosing);
+    }
+
+    // http://b/19892782
+    public void testCloseFileChannel_returnedFileChannelIsClosed() throws Exception {
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
+
+        FileChannel fileChannelBeforeClosing = raf.getChannel();
+        // This should close the Raf, and previous implementations wrongly returned a new
+        // open (but useless) channel in this case.
+        fileChannelBeforeClosing.close();
+        FileChannel fileChannelAfterClosing = raf.getChannel();
+        assertFalse(fileChannelBeforeClosing.isOpen());
+    }
+
+    // http://b/19892782
+    public void testCloseRafBeforeGetChannel_returnChannelWithCloseFdAfterClose() throws Exception {
+        RandomAccessFile raf = new RandomAccessFile(file, "rw");
+        raf.close();
+        try {
+            raf.getChannel().size();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
     private void createRandomAccessFile(File file) throws Exception {
         // TODO: fix our register maps and remove this otherwise unnecessary
         // indirection! (http://b/5412580)