java.nio.channel.FileLock test

The tests check the behaviour of FileLock when more than one processe or
thread try to hold the file lock.

The FileLock should return null if the multiple processes try to obtain
the lock, however, it should raise OverlappingFileLockException if the
lock is already held by the same runtime.

Bug: 27186422
(cherry-picked from commit f16ac2dcde20737e2f437d5c8cd5a321c0c38273)
Change-Id: I97184d7735ad05a9b88cf8ee7dbc76177b0210d2
diff --git a/tests/tests/libcorefileio/Android.mk b/tests/tests/libcorefileio/Android.mk
new file mode 100644
index 0000000..29226bf
--- /dev/null
+++ b/tests/tests/libcorefileio/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsLibcoreFileIOTestCases
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/libcorefileio/AndroidManifest.xml b/tests/tests/libcorefileio/AndroidManifest.xml
new file mode 100644
index 0000000..4557eec
--- /dev/null
+++ b/tests/tests/libcorefileio/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.libcorefileio.cts">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+        <service android:name="android.cts.LockHoldingService"
+                 android:process=":lockHoldingService"
+                 android:permission="android.permission.WRITE_EXTERNAL_STORAGE"
+        />
+        <receiver android:name="android.cts.FileChannelTryLockTest$IntentReceiver">
+
+            <intent-filter>
+                <action android:name="android.cts.CtsLibcoreFileIOTestCases">
+                </action>
+            </intent-filter>
+
+        </receiver>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.libcorefileio.cts">
+        <meta-data android:name="listener"
+                   android:value="com.android.cts.runner.CtsTestRunListener"/>
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/libcorefileio/AndroidTest.xml b/tests/tests/libcorefileio/AndroidTest.xml
new file mode 100644
index 0000000..9baa713
--- /dev/null
+++ b/tests/tests/libcorefileio/AndroidTest.xml
@@ -0,0 +1,23 @@
+<!-- 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/FileChannelTryLockTest.java b/tests/tests/libcorefileio/src/android/cts/FileChannelTryLockTest.java
new file mode 100644
index 0000000..61a59ca
--- /dev/null
+++ b/tests/tests/libcorefileio/src/android/cts/FileChannelTryLockTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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
new file mode 100644
index 0000000..be6a352
--- /dev/null
+++ b/tests/tests/libcorefileio/src/android/cts/LockHoldingService.java
@@ -0,0 +1,67 @@
+/*
+ * 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.app.Service;
+import android.content.Intent;
+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;
+
+public class LockHoldingService extends Service {
+
+    final String TAG = "CtsLibcoreFileIOTestCases";
+
+    File file = null;
+
+    FileLock fileLock = null;
+
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @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());
+            }
+        } catch (IOException e) {
+            Log.e(TAG, e.getMessage());
+        }
+        sendBroadcast(new Intent().setAction("android.cts.CtsLibcoreFileIOTestCases"));
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        try {
+            fileLock.close();
+        } catch (IOException e) {
+            Log.e(TAG, e.getMessage());
+        }
+        FileChannelTryLockTest.deleteDir();
+    }
+}