ART: Add three Timer functions

Add support for GetAvailableProcessors, GetTimerInfo and GetTime.
Add tests.

Bug: 31455788
Test: m test-art-host-run-test-926-timers
Change-Id: I9629654349787e27dee686284567b5de70e138f2
diff --git a/test/927-timers/build b/test/927-timers/build
new file mode 100755
index 0000000..898e2e5
--- /dev/null
+++ b/test/927-timers/build
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+./default-build "$@" --experimental agents
diff --git a/test/927-timers/expected.txt b/test/927-timers/expected.txt
new file mode 100644
index 0000000..a4ef442
--- /dev/null
+++ b/test/927-timers/expected.txt
@@ -0,0 +1,3 @@
+availableProcessors OK
+[-1, true, true, 32]
+Time OK
diff --git a/test/927-timers/info.txt b/test/927-timers/info.txt
new file mode 100644
index 0000000..875a5f6
--- /dev/null
+++ b/test/927-timers/info.txt
@@ -0,0 +1 @@
+Tests basic functions in the jvmti plugin.
diff --git a/test/927-timers/run b/test/927-timers/run
new file mode 100755
index 0000000..4379349
--- /dev/null
+++ b/test/927-timers/run
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+./default-run "$@" --experimental agents \
+                   --experimental runtime-plugins \
+                   --jvmti
diff --git a/test/927-timers/src/Main.java b/test/927-timers/src/Main.java
new file mode 100644
index 0000000..2f5c85c
--- /dev/null
+++ b/test/927-timers/src/Main.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+import java.util.Arrays;
+
+public class Main {
+  public static void main(String[] args) throws Exception {
+    System.loadLibrary(args[1]);
+
+    doTest();
+  }
+
+  private static void doTest() {
+    int all1 = Runtime.getRuntime().availableProcessors();
+    int all2 = getAvailableProcessors();
+    if (all1 != all2) {
+      throw new RuntimeException("Available processors doesn't match: " + all1 + " vs " + all2);
+    }
+    System.out.println("availableProcessors OK");
+
+    Object info[] = getTimerInfo();
+    System.out.println(Arrays.toString(info));
+
+    // getTime checks.
+    // Note: there isn't really much to check independent from the implementation. So we check
+    //       a few details of the ART implementation. This may fail on other runtimes.
+    long time1 = getTime();
+    long time2 = getTime();
+
+    // Under normal circumstances, time1 <= time2.
+    if (time2 < time1) {
+      throw new RuntimeException("Time unexpectedly decreased: " + time1 + " vs " + time2);
+    }
+
+    long time3 = System.nanoTime();
+    long time4 = getTime();
+
+    final long MINUTE = 60l * 1000 * 1000 * 1000;
+    if (time4 < time3 || (time4 - time3 > MINUTE)) {
+      throw new RuntimeException("Time unexpectedly divergent: " + time3 + " vs " + time4);
+    }
+
+    System.out.println("Time OK");
+  }
+
+  private static native int getAvailableProcessors();
+  private static native Object[] getTimerInfo();
+  private static native long getTime();
+}
diff --git a/test/927-timers/timers.cc b/test/927-timers/timers.cc
new file mode 100644
index 0000000..58d5c27
--- /dev/null
+++ b/test/927-timers/timers.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <inttypes.h>
+
+#include "android-base/stringprintf.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "jni.h"
+#include "openjdkjvmti/jvmti.h"
+
+#include "ti-agent/common_helper.h"
+#include "ti-agent/common_load.h"
+
+namespace art {
+namespace Test926Timers {
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getAvailableProcessors(
+    JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
+  jint count;
+  jvmtiError result = jvmti_env->GetAvailableProcessors(&count);
+  if (JvmtiErrorToException(env, result)) {
+    return -1;
+  }
+  return count;
+}
+
+extern "C" JNIEXPORT jlong JNICALL Java_Main_getTime(
+    JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
+  jlong time;
+  jvmtiError result = jvmti_env->GetTime(&time);
+  if (JvmtiErrorToException(env, result)) {
+    return -1;
+  }
+  return time;
+}
+
+extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getTimerInfo(
+    JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) {
+  jvmtiTimerInfo info;
+  jvmtiError result = jvmti_env->GetTimerInfo(&info);
+  if (JvmtiErrorToException(env, result)) {
+    return nullptr;
+  }
+
+  auto callback = [&](jint index) -> jobject {
+    switch (index) {
+      // Max value.
+      case 0:
+        return env->NewStringUTF(android::base::StringPrintf("%" PRId64, info.max_value).c_str());
+
+      // Skip forward.
+      case 1:
+        return env->NewStringUTF(info.may_skip_forward == JNI_TRUE ? "true" : "false");
+      // Skip backward.
+      case 2:
+        return env->NewStringUTF(info.may_skip_forward == JNI_TRUE ? "true" : "false");
+
+      // The kind.
+      case 3:
+        return env->NewStringUTF(
+            android::base::StringPrintf("%d", static_cast<jint>(info.kind)).c_str());
+    }
+    LOG(FATAL) << "Should not reach here";
+    UNREACHABLE();
+  };
+  return CreateObjectArray(env, 4, "java/lang/Object", callback);
+}
+
+}  // namespace Test926Timers
+}  // namespace art
diff --git a/test/Android.bp b/test/Android.bp
index b0f0e5a..1ea1252 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -265,6 +265,7 @@
         "922-properties/properties.cc",
         "923-monitors/monitors.cc",
         "924-threads/threads.cc",
+        "927-timers/timers.cc",
     ],
     shared_libs: [
         "libbase",
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 6068876..55cef97 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -304,6 +304,7 @@
   923-monitors \
   924-threads \
   926-multi-obsolescence \
+  927-timers \
 
 ifneq (,$(filter target,$(TARGET_TYPES)))
   ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUILD_TYPES), \