Add tests for java.nio.channels.FileChannel lock methods

lock()
lock(long, long, boolean)
tryLock()
tryLock(long, long, boolean)

Bug: 27186422
(cherry-picked from commit 2eff57cc1164d20f8a748f8e752ebac021476167)
Change-Id: Ia2d67993d61116e83e636e9305e40932e79d2584
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 1302c07..46a89de 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -172,6 +172,7 @@
     CtsJniTestCases \
     CtsKeystoreTestCases \
     CtsLibcoreLegacy22TestCases \
+    CtsLibcoreFileIOTestCases \
     CtsLocationTestCases \
     CtsLocation2TestCases \
     CtsMediaStressTestCases \
diff --git a/tests/tests/libcorefileio/AndroidManifest.xml b/tests/tests/libcorefileio/AndroidManifest.xml
index 4557eec..6eb1439 100644
--- a/tests/tests/libcorefileio/AndroidManifest.xml
+++ b/tests/tests/libcorefileio/AndroidManifest.xml
@@ -26,7 +26,7 @@
                  android:process=":lockHoldingService"
                  android:permission="android.permission.WRITE_EXTERNAL_STORAGE"
         />
-        <receiver android:name="android.cts.FileChannelTryLockTest$IntentReceiver">
+        <receiver android:name="android.cts.FileChannelInterProcessLockTest$IntentReceiver">
 
             <intent-filter>
                 <action android:name="android.cts.CtsLibcoreFileIOTestCases">
@@ -43,4 +43,3 @@
     </instrumentation>
 
 </manifest>
-
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
deleted file mode 100644
index 9baa713..0000000
--- a/tests/tests/libcorefileio/AndroidTest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!-- Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for CTS Legacy Libcore test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsLibcoreFileIOTestCases.apk" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.libcorefileio.cts" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
new file mode 100644
index 0000000..05894d5
--- /dev/null
+++ b/tests/tests/libcorefileio/src/android/cts/FileChannelInterProcessLockTest.java
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileLock;
+import java.util.concurrent.CountDownLatch;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+@SuppressWarnings("deprecation")
+public class FileChannelInterProcessLockTest extends AndroidTestCase {
+
+    /** The directory where file locks are created */
+    final static String DIR_NAME = "CtsFileIOTest";
+
+    /** The name of the file used when acquiring a lock. */
+    final static String FILE_NAME = "file";
+
+    /** The position in the lock file used when acquiring a region lock. */
+    final static int LOCK_POSITION = 10;
+
+    /** The extent of the lock file locked when acquiring a region lock. */
+    final static int LOCK_SIZE = 10;
+
+    /**
+     * This is the maximum waiting time in seconds for the test to wait for a response from
+     * the service. This provides ample amount of time for the service to receive the request from
+     * the test, then act, and respond back.
+     */
+    final static int MAX_WAIT_TIME = 7;
+
+    @Override
+    public void tearDown() throws Exception {
+        stopService();
+        super.tearDown();
+    }
+
+    /**
+     * java.nio.channels.FileChannel#tryLock()
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if the returned lock should be valid,
+     * {@code false} otherwise.
+     */
+    public void test_tryLock() throws Exception {
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.TRY_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.LOCK_ON_REGION_WITH_LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.TRY_LOCK, LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                false /* expectToGetLock */);
+    }
+
+    /**
+     * java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if the returned lock should be valid,
+     * {@code false} otherwise.
+     */
+    public void test_tryLockJJZ_Exclusive() throws Exception {
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK, LockType.TRY_LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_REGION_WITH_TRY_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+                true /* expectToGetLock */);
+
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK, LockType.LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_REGION_WITH_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK ,
+                true /* expectToGetLock */);
+    }
+
+    /**
+     * java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if the returned lock should be valid,
+     * {@code false} otherwise.
+     */
+    public void test_tryLockJJZ_Shared() throws Exception {
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, LockType.TRY_LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_REGION_WITH_TRY_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+                true /* expectToGetLock */);
+
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, LockType.LOCK,
+                false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_REGION_WITH_LOCK, false /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, true /* expectToGetLock */);
+        checkTryLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK,
+                true /* expectToGetLock */);
+    }
+
+    /**
+     * java.nio.channels.FileChannel#lock()
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if it blocks the local thread, {@code false} otherwise.
+     */
+    public void test_lock() throws Exception {
+        checkLockBehavior(LockType.LOCK, LockType.LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK, LockType.LOCK_ON_REGION_WITH_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK, LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                true /* expectToWait */);
+
+        checkLockBehavior(LockType.LOCK, LockType.TRY_LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK, LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK, LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+                true /* expectToWait */);
+    }
+
+    /**
+     * java.nio.channels.FileChannel#lock(long, long, boolean)
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if blocks the local thread, {@code false} otherwise.
+     */
+    public void test_lockJJZ_Exclusive() throws Exception {
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK, LockType.LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK, LockType.LOCK_ON_REGION_WITH_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, false /* expectToWait */);
+
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK, LockType.TRY_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK, LockType.LOCK_ON_REGION_WITH_TRY_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+                false /* expectToWait */);
+    }
+
+    /**
+     * java.nio.channels.FileChannel#lock(long, long, boolean)
+     *
+     * Obtains a remote lock, then attempts to acquire a local lock on the same file,
+     * and checks the behavior.
+     * checkTryLockBehavior(localLockType, remoteLockType, expectedLocalLockResult)
+     * expectedLockLockResult: {@code true} if blocks the local thread, {@code false} otherwise.
+     */
+    public void test_lockJJZ_Shared() throws Exception {
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, LockType.LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_REGION_WITH_LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK, false /* expectToWait */);
+
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK, LockType.TRY_LOCK,
+                true /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_REGION_WITH_TRY_LOCK, true /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_REGION_WITH_TRY_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK, false /* expectToWait */);
+        checkLockBehavior(LockType.SHARED_LOCK_ON_REGION_WITH_LOCK,
+                LockType.SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+                false /* expectToWait */);
+    }
+
+    /**
+     * Checks the behavior of java.nio.Channels.FileChannel#tryLock() and #tryLock(J, J, Z)
+     *
+     * @param localLockType the type of lock to be acquired by the test
+     * @param remoteLockType the type of lock to be acquired by the remote service
+     * @param expectToGetLock {@code true}, if the lock should be acquired even when the
+     *         service holds a {@code remoteLockType} lock, false otherwise.
+     */
+    private void checkTryLockBehavior(LockType localLockType, LockType remoteLockType,
+            boolean expectToGetLock) throws Exception {
+        IntentReceiver.resetReceiverState();
+
+        // Request that the remote lock be obtained.
+        getContext().startService(new Intent(getContext(), LockHoldingService.class)
+                .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType));
+
+        // Wait for a signal that the remote lock is definitely held.
+        assertTrue(IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+
+        // Try to acquire the local lock in all cases and check whether it could be acquired or
+        // not as expected.
+        if (expectToGetLock) {
+            FileLock fileLock = acquire(localLockType);
+            assertNotNull(fileLock);
+            assertTrue(fileLock.isValid());
+        } else {
+            assertNull(acquire(localLockType));
+        }
+        // Release the remote lock.
+        stopService();
+    }
+
+    /**
+     * Checks the java.nio.channels.FileChannel.lock()/lock(J, J, Z) behavior.
+     *
+     * @param localLockType type of lock to be acquired by the test
+     * @param remoteLockType type of lock to be acquired by the remote service.
+     * @param expectToWait {@code true}, if the local thread must wait for the remote
+     *         service to release the lock, {@code false} otherwise.
+     */
+    private void checkLockBehavior(LockType localLockType, LockType remoteLockType,
+            boolean expectToWait) throws Exception {
+        IntentReceiver.resetReceiverState();
+
+        // The amount of time the remote service should hold lock.
+        long remoteLockHoldTimeMillis = 5000;
+
+        // The amount of time test should get to try to acquire the lock.
+        long sufficientOverlappingTimeInMillis = 2000;
+
+        // This is the allowable delta in the time between the time recorded after the service
+        // released the lock and the time recorded after the test obtained the lock.
+        long lockReleasedAndReacquiredTimeDeltaInMillis = 500;
+
+        // Tell the service to acquire a remote lock.
+        Intent sendIntent = new Intent(getContext(), LockHoldingService.class)
+                .putExtra(LockHoldingService.TIME_TO_HOLD_LOCK_KEY, remoteLockHoldTimeMillis)
+                .putExtra(LockHoldingService.LOCK_TYPE_KEY, remoteLockType)
+                .putExtra(LockHoldingService.LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, true);
+
+        getContext().startService(sendIntent);
+
+        // Wait for the service to hold the lock and notify for the same.
+        assertTrue(IntentReceiver.lockHeldLatch.await(MAX_WAIT_TIME, SECONDS));
+
+        long localLockNotObtainedTime = System.currentTimeMillis();
+
+        // Acquire the lock locally.
+        FileLock fileLock = acquire(localLockType);
+        long localLockObtainedTime = System.currentTimeMillis();
+
+        // Wait until the remote lock has definitely been released.
+        assertTrue(IntentReceiver.lockReleasedLatch.await(MAX_WAIT_TIME, SECONDS));
+
+        Bundle remoteLockReleasedBundle = IntentReceiver.lockReleasedBundle;
+        long remoteLockNotReleasedTime =
+                remoteLockReleasedBundle.getLong(LockHoldingService.LOCK_NOT_YET_RELEASED_TIMESTAMP);
+        long remoteLockReleasedTime =
+                remoteLockReleasedBundle.getLong(LockHoldingService.LOCK_DEFINITELY_RELEASED_TIMESTAMP);
+
+        // We want the test to be notified well before the service releases the lock, so that
+        // we can be sure that it tried obtaining the lock before the service actually released it.
+        // Therefore, a two seconds time interval provides the test to get prepare and try to obtain
+        // the lock. If this fails, it doesn't mean they definitely didn't overlap
+        // but we can't be sure and the test may not be valid. This is why we hold the lock
+        // remotely for a long time compared to the delays we expect for intents to propagate
+        // between processes.
+        assertTrue(remoteLockNotReleasedTime - localLockNotObtainedTime >
+                sufficientOverlappingTimeInMillis);
+
+        if (expectToWait) {
+
+            // The remoteLockReleaseTime is captured after the lock was released by the
+            // service. The localLockObtainedTime is captured after the lock was obtained by this
+            // thread. Therefore, there is a degree of slop inherent in the two times. We assert
+            // that they are "close" to each other, but we cannot assert any ordering.
+            assertTrue(Math.abs(localLockObtainedTime - remoteLockReleasedTime) <
+                    lockReleasedAndReacquiredTimeDeltaInMillis);
+        } else {
+            // The remoteLockNotReleaseTime is captured before the lock was released by the
+            // service. The localLockObtainedTime is captured after the lock was obtained by this
+            // thread. The local thread should be able to get the lock before the remote thread
+            // definitely release it. If this test fails it may not indicate a problem, but it
+            // indicates we cannot be sure the test was successful the local lock attempt and the
+            // remote lock attempt did not overlap.
+            assertTrue(localLockObtainedTime < remoteLockNotReleasedTime);
+        }
+
+        // Asserting if the fileLock is valid.
+        assertTrue(fileLock.isValid());
+        stopService();
+    }
+
+    /**
+     * Requests and waits for the service to stop
+     */
+    void stopService() throws Exception {
+        getContext().stopService(new Intent(getContext(), LockHoldingService.class));
+        assertTrue(IntentReceiver.onStopLatch.await(MAX_WAIT_TIME, SECONDS));
+        deleteDir();
+    }
+
+    enum LockType {
+
+        /** Equivalent to {@code tryLock()} */
+        TRY_LOCK,
+
+        /** Equivalent to  {@code tryLock({@link #LOCK_POSITION}, {@link #LOCK_SIZE}, false)} */
+        LOCK_ON_REGION_WITH_TRY_LOCK,
+
+        /**
+         * Equivalent to  {@code tryLock({@code {@link #LOCK_POSITION} + {@link #LOCK_SIZE}},
+         * {@link #LOCK_SIZE}, false)}
+         */
+        LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+
+        /** Equivalent to  {@code tryLock({@link #LOCK_POSITION}, {@link #LOCK_SIZE}, true)} */
+        SHARED_LOCK_ON_REGION_WITH_TRY_LOCK,
+
+        /**
+         * Equivalent to  {@code tryLock({@code {@link #LOCK_POSITION} + {@link #LOCK_SIZE}},
+         * {@link #LOCK_SIZE}, true)}
+         */
+        SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK,
+
+        /** Equivalent to  {@code lock()} */
+        LOCK,
+
+        /** Equivalent to  {code lock({@link #LOCK_POSITION}, {@link #LOCK_SIZE}, false)} */
+        LOCK_ON_REGION_WITH_LOCK,
+
+        /**
+         * Equivalent to  {@code lock({@code {@link #LOCK_POSITION} + {@link #LOCK_SIZE}},
+         * {@link #LOCK_SIZE}, false)}
+         */
+        LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK,
+
+        /** Equivalent to  {@code lock({@link #LOCK_POSITION}, {@link #LOCK_SIZE}, true)} */
+        SHARED_LOCK_ON_REGION_WITH_LOCK,
+
+        /**
+         * Equivalent to {@code lock({@code {@link #LOCK_POSITION} + {@link #LOCK_SIZE}},
+         * {@link #LOCK_SIZE}, true)}
+         */
+        SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK,
+    }
+
+    /**
+     * Tries to acquire a lock of {@code lockType} on the file returned by
+     * {@link #createFileInDir()} method.
+     *
+     * @param lockType a {@link LockType} enum.
+     *         Permitted lock types:
+     *         {@link LockType#TRY_LOCK}
+     *         {@link LockType#LOCK_ON_REGION_WITH_TRY_LOCK}
+     *         {@link LockType#LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK}
+     *         {@link LockType#SHARED_LOCK_ON_REGION_WITH_TRY_LOCK}
+     *         {@link LockType#SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK}
+     *         {@link LockType#LOCK}
+     *         {@link LockType#LOCK_ON_REGION_WITH_LOCK}
+     *         {@link LockType#LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK}
+     *         {@link LockType#SHARED_LOCK_ON_REGION_WITH_LOCK}
+     *         {@link LockType#SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK}
+     * @return Returns the lock returned by the lock method.
+     * @throws UnsupportedOperationException
+     *         If the {@code lockType} is of non recognized type.
+     */
+    static FileLock acquire(LockType lockType) throws IOException {
+        File file = createFileInDir();
+        file.createNewFile();
+        switch (lockType) {
+            case TRY_LOCK:
+                return new FileOutputStream(file).getChannel().tryLock();
+            case LOCK_ON_REGION_WITH_TRY_LOCK:
+                return new FileOutputStream(file).getChannel()
+                        .tryLock(LOCK_POSITION, LOCK_SIZE, false /*isShared*/);
+            case LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK:
+                return new FileOutputStream(file).getChannel()
+                        .tryLock(LOCK_POSITION + LOCK_SIZE, LOCK_SIZE, false /*isShared*/);
+            case SHARED_LOCK_ON_REGION_WITH_TRY_LOCK:
+                return new FileInputStream(file).getChannel()
+                        .tryLock(LOCK_POSITION, LOCK_SIZE, true /*isShared*/);
+            case SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_TRY_LOCK:
+                return new FileInputStream(file).getChannel()
+                        .tryLock(LOCK_POSITION + LOCK_SIZE, LOCK_SIZE, true /*isShared*/);
+            case LOCK:
+                return new FileOutputStream(file).getChannel().lock();
+            case LOCK_ON_REGION_WITH_LOCK:
+                return new FileOutputStream(file).getChannel()
+                        .lock(LOCK_POSITION, LOCK_SIZE, false /*isShared*/);
+            case LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK:
+                return new FileOutputStream(file).getChannel()
+                        .lock(LOCK_POSITION + LOCK_SIZE, LOCK_SIZE, false /*isShared*/);
+            case SHARED_LOCK_ON_REGION_WITH_LOCK:
+                return new FileInputStream(file).getChannel()
+                        .lock(LOCK_POSITION, LOCK_SIZE, true /*isShared*/);
+            case SHARED_LOCK_ON_NON_OVERLAPPING_REGION_WITH_LOCK:
+                return new FileInputStream(file).getChannel()
+                        .lock(LOCK_POSITION + LOCK_SIZE, LOCK_SIZE, true /*isShared*/);
+            default:
+                throw new UnsupportedOperationException("Unknown lock type");
+        }
+    }
+
+    /**
+     * Creates a file named {@link #FILE_NAME} inside a directory named {@link #DIR_NAME} on
+     * the external storage directory.
+     */
+    static File createFileInDir() throws IOException {
+        File dir = new File(Environment.getExternalStorageDirectory(), DIR_NAME);
+        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            throw new IOException("External storage is not mounted");
+        } else if (!dir.mkdirs() && !dir.isDirectory()) {
+            throw new IOException("Cannot create directory for device info files");
+        } else {
+            return new File(dir, FILE_NAME);
+        }
+    }
+
+    /**
+     * Deletes the folder {@link #DIR_NAME} on the external storage directory along with all the
+     * files inside it.
+     */
+    static void deleteDir() {
+        File dir = new File(Environment.getExternalStorageDirectory(), DIR_NAME);
+        if (dir.isDirectory()) {
+            String[] children = dir.list();
+            for (String child : children) {
+                new File(dir, child).delete();
+            }
+            dir.delete();
+        }
+    }
+
+    /**
+     * Listens to broadcasts sent by the LockHoldingService and records information / provides
+     * latches so the test code can synchronize until it is informed the service has acted on
+     * requests it has sent.
+     */
+    public static class IntentReceiver extends BroadcastReceiver {
+
+        static CountDownLatch onStartLatch;
+
+        static CountDownLatch onStopLatch;
+
+        static CountDownLatch lockHeldLatch;
+
+        static volatile Bundle lockHeldBundle;
+
+        static CountDownLatch lockReleasedLatch;
+
+        static volatile Bundle lockReleasedBundle;
+
+        /**
+         * Reset the IntentReceiver for a new test. Assumes no intents will be received from prior
+         *  tests.
+         */
+        public static synchronized void resetReceiverState() {
+            onStartLatch = new CountDownLatch(1);
+            onStopLatch = new CountDownLatch(1);
+            lockHeldLatch = new CountDownLatch(1);
+            lockReleasedLatch = new CountDownLatch(1);
+            lockHeldBundle = null;
+            lockReleasedBundle = null;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String msg = intent.getStringExtra(LockHoldingService.NOTIFICATION_KEY);
+            switch (msg) {
+                case LockHoldingService.NOTIFICATION_START:
+                    onStartLatch.countDown();
+                    break;
+                case LockHoldingService.NOTIFICATION_STOP:
+                    onStopLatch.countDown();
+                    break;
+                case LockHoldingService.NOTIFICATION_LOCK_HELD:
+                    lockHeldBundle = intent.getExtras();
+                    lockHeldLatch.countDown();
+                    break;
+                case LockHoldingService.NOTIFICATION_LOCK_RELEASED:
+                    lockReleasedBundle = intent.getExtras();
+                    lockReleasedLatch.countDown();
+                    break;
+            }
+        }
+    }
+}
+
diff --git a/tests/tests/libcorefileio/src/android/cts/FileChannelTryLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelTryLockTest.java
deleted file mode 100644
index 61a59ca..0000000
--- a/tests/tests/libcorefileio/src/android/cts/FileChannelTryLockTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.cts;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Environment;
-import android.test.AndroidTestCase;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.channels.FileLock;
-import java.nio.channels.OverlappingFileLockException;
-
-@SuppressWarnings("deprecation")
-public class FileChannelTryLockTest extends AndroidTestCase {
-
-    final static String dirName = "CtsFIleIOTest";
-
-    final static String sharedFileName = "sharedFile";
-
-    public void testFileLockWithMultipleProcess() throws InterruptedException, IOException {
-        IntentReceiver receiver = new IntentReceiver();
-        getContext().startService(new Intent(getContext(), LockHoldingService.class));
-        synchronized (receiver.notifier) {
-            receiver.notifier.wait(10000);
-        }
-        File sharedFile = createFileInDir(dirName, sharedFileName);
-        assertNull(new FileOutputStream(sharedFile).getChannel().tryLock());
-        getContext().stopService(new Intent(getContext(), LockHoldingService.class));
-    }
-
-    public void testFileLockWithSingleProcess() throws IOException {
-        File file = createFileInDir(dirName, "sharedFileForSingleProcess");
-        FileLock fileLock1 = new FileOutputStream(file).getChannel().tryLock();
-        try {
-            new FileOutputStream(file).getChannel().tryLock();
-            fail();
-        } catch (OverlappingFileLockException expected) {
-        }
-    }
-
-    static File createFileInDir(String dirName, String fileName) throws IOException {
-        File dir = new File(Environment.getExternalStorageDirectory(), dirName);
-        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-            throw new IOException("External storage is not mounted");
-        } else if (!dir.mkdirs() && !dir.isDirectory()) {
-            throw new IOException("Cannot create directory for device info files");
-        } else {
-            return new File(dir, fileName);
-        }
-    }
-
-    static void deleteDir() {
-        File dir = new File(Environment.getExternalStorageDirectory(), dirName);
-        if (dir.isDirectory()) {
-            String[] children = dir.list();
-            for (int i = 0; i < children.length; i++) {
-                new File(dir, children[i]).delete();
-            }
-            dir.delete();
-        }
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        getContext().stopService(new Intent(getContext(), LockHoldingService.class));
-        deleteDir();
-    }
-
-    public static class IntentReceiver extends BroadcastReceiver {
-
-        public final static Object notifier = new Object();
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            synchronized (notifier) {
-                notifier.notify();
-            }
-        }
-    }
-}
-
diff --git a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
index be6a352..6ac73b0 100644
--- a/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
+++ b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
@@ -21,18 +21,74 @@
 import android.os.IBinder;
 import android.util.Log;
 
-import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.channels.FileLock;
 
+/**
+ * A Service that listens for commands from the FileChannelInterProcessLockTest to acquire locks of
+ * different types. It exists to test the behavior when file locks are acquired/released across
+ * multiple processes.
+ */
 public class LockHoldingService extends Service {
 
-    final String TAG = "CtsLibcoreFileIOTestCases";
+    /**
+     *  The key of the Bundle extra used to record a time after a lock is released by the service.
+     */
+    static final String LOCK_DEFINITELY_RELEASED_TIMESTAMP = "lockReleasedTimestamp";
 
-    File file = null;
+    /**
+     * The key of the Bundle extra used to record just before the lock is released by the service.
+     */
+    static final String LOCK_NOT_YET_RELEASED_TIMESTAMP = "lockNotReleasedTimestamp";
 
-    FileLock fileLock = null;
+    /**
+     * The key of the Bundle extra used to send general notifications to the test.
+     */
+    static final String NOTIFICATION_KEY = "notification";
+
+    /**
+     * The value for the notification sent to the test after the service starts.
+     */
+    static final String NOTIFICATION_START = "onStart";
+
+    /**
+     * The value for the notification sent to the test just before the service stops.
+     */
+    static final String NOTIFICATION_STOP = "onStop";
+
+    /**
+     * The value for the notification sent to the test after the lock is acquired.
+     */
+    static final String NOTIFICATION_LOCK_HELD = "lockHeld";
+
+    /**
+     * The value for the notification sent to the test after the lock is released
+     */
+    static final String NOTIFICATION_LOCK_RELEASED = "lockReleased";
+
+    /**
+     * The key of the Bundle extra used to send time for which the service should wait before
+     * releasing the lock.
+     */
+    static final String TIME_TO_HOLD_LOCK_KEY = "timeToHoldLock";
+
+    /**
+     * The key of the Bundle extra used for the type of lock to be held.
+     */
+    static final String LOCK_TYPE_KEY = "lockType";
+
+    /**
+     * The key of the Bundle extra used to let he service know whether to release the lock after
+     * some time.
+     */
+    static final String LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY = "releaseAndNotify";
+
+    static final String ACTION_TYPE_FOR_INTENT_COMMUNICATION
+            = "android.cts.CtsLibcoreFileIOTestCases";
+
+    final String LOG_MESSAGE_TAG = "CtsLibcoreFileIOTestCases";
+
+    private FileLock fileLock = null;
 
     public IBinder onBind(Intent intent) {
         return null;
@@ -41,27 +97,81 @@
     @Override
     public int onStartCommand(Intent intent, int flags, int startID) {
         try {
-            this.file = FileChannelTryLockTest.createFileInDir(FileChannelTryLockTest.dirName,
-                    FileChannelTryLockTest.sharedFileName);
-            try {
-                this.fileLock = new FileOutputStream(file).getChannel().tryLock();
-            } catch (IOException e) {
-                Log.e(TAG, e.getMessage());
+            if (intent.getBooleanExtra(LOCK_BEHAVIOR_RELEASE_AND_NOTIFY_KEY, false)) {
+                acquireLockAndThenWaitThenRelease(intent);
+            } else {
+                acquireLock(intent);
             }
-        } catch (IOException e) {
-            Log.e(TAG, e.getMessage());
+        } catch (Exception e) {
+            Log.e(LOG_MESSAGE_TAG, e.getMessage());
         }
-        sendBroadcast(new Intent().setAction("android.cts.CtsLibcoreFileIOTestCases"));
         return START_STICKY;
     }
 
+    /**
+     * Acquires the lock asked by the test indefinitely.
+     */
+    private void acquireLock(Intent intent) throws IOException {
+        FileChannelInterProcessLockTest.LockType lockType =
+                (FileChannelInterProcessLockTest.LockType)intent.getSerializableExtra(
+                        LOCK_TYPE_KEY);
+
+        // Acquire the lock based on the information contained in the intent received.
+        this.fileLock = FileChannelInterProcessLockTest.acquire(lockType);
+        Intent responseIntent = new Intent().putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
+                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
+        sendBroadcast(responseIntent);
+    }
+
+    /**
+     * Acquires and holds the lock for a time specified by the test. Sends a broadcast message after
+     * releasing the lock.
+     */
+    private void acquireLockAndThenWaitThenRelease(Intent intent)
+            throws IOException, InterruptedException {
+        long lockHoldTimeMillis = intent.getLongExtra(TIME_TO_HOLD_LOCK_KEY, 0);
+
+        // Acquire the lock.
+        FileChannelInterProcessLockTest.LockType lockType =
+                (FileChannelInterProcessLockTest.LockType)intent.getSerializableExtra(
+                        LOCK_TYPE_KEY);
+        this.fileLock = FileChannelInterProcessLockTest.acquire(lockType);
+
+        // Signal the lock is now held.
+        Intent heldIntent = new Intent()
+                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_HELD)
+                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
+        sendBroadcast(heldIntent);
+
+        Thread.sleep(lockHoldTimeMillis);
+
+        long lockNotReleasedTimestamp = System.currentTimeMillis();
+
+        // Release the lock
+        fileLock.release();
+
+        long lockReleasedTimestamp = System.currentTimeMillis();
+
+        // Signal the lock is released and some information about timing.
+        Intent releaseIntent = new Intent()
+                .putExtra(NOTIFICATION_KEY, NOTIFICATION_LOCK_RELEASED)
+                .putExtra(LOCK_NOT_YET_RELEASED_TIMESTAMP, lockNotReleasedTimestamp)
+                .putExtra(LOCK_DEFINITELY_RELEASED_TIMESTAMP, lockReleasedTimestamp)
+                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
+        sendBroadcast(releaseIntent);
+    }
+
     @Override
     public void onDestroy() {
         try {
-            fileLock.close();
+            if (fileLock != null) {
+                fileLock.release();
+            }
         } catch (IOException e) {
-            Log.e(TAG, e.getMessage());
+            Log.e(LOG_MESSAGE_TAG, e.getMessage());
         }
-        FileChannelTryLockTest.deleteDir();
+        Intent intent = new Intent().putExtra(NOTIFICATION_KEY, NOTIFICATION_STOP)
+                .setAction(ACTION_TYPE_FOR_INTENT_COMMUNICATION);
+        sendBroadcast(intent);
     }
 }