Fix setting/getting the native priority of a thread.

Bug: 138415922
Test: 720-thread-priority
Change-Id: I6e1f34fce3838b7904281be00f315e5b7ade0c78
(cherry picked from commit fa595885339140c3507f26d93cdc6b99081e23c5)
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 70ed7c8..be0e30a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1833,8 +1833,11 @@
           group_name_field->GetObject(thread_group)->AsString();
       group_name = (group_name_string != nullptr) ? group_name_string->ToModifiedUtf8() : "<null>";
     }
+  } else if (thread != nullptr) {
+    priority = thread->GetNativePriority();
   } else {
-    priority = GetNativePriority();
+    PaletteStatus status = PaletteSchedGetPriority(tid, &priority);
+    CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
   }
 
   std::string scheduler_group_name(GetSchedulerGroupName(tid));
@@ -4266,15 +4269,13 @@
 }
 
 void Thread::SetNativePriority(int new_priority) {
-  // ART tests on JVM can reach this code path, use tid = 0 as shorthand for current thread.
-  PaletteStatus status = PaletteSchedSetPriority(0, new_priority);
+  PaletteStatus status = PaletteSchedSetPriority(GetTid(), new_priority);
   CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
 }
 
-int Thread::GetNativePriority() {
+int Thread::GetNativePriority() const {
   int priority = 0;
-  // ART tests on JVM can reach this code path, use tid = 0 as shorthand for current thread.
-  PaletteStatus status = PaletteSchedGetPriority(0, &priority);
+  PaletteStatus status = PaletteSchedGetPriority(GetTid(), &priority);
   CHECK(status == PaletteStatus::kOkay || status == PaletteStatus::kCheckErrno);
   return priority;
 }
diff --git a/runtime/thread.h b/runtime/thread.h
index dd483c1..ae04600 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -375,12 +375,12 @@
   void SetNativePriority(int newPriority);
 
   /*
-   * Returns the thread priority for the current thread by querying the system.
+   * Returns the priority of this thread by querying the system.
    * This is useful when attaching a thread through JNI.
    *
    * Returns a value from 1 to 10 (compatible with java.lang.Thread values).
    */
-  static int GetNativePriority();
+  int GetNativePriority() const;
 
   // Guaranteed to be non-zero.
   uint32_t GetThreadId() const {
diff --git a/test/720-thread-priority/expected.txt b/test/720-thread-priority/expected.txt
new file mode 100644
index 0000000..6a5618e
--- /dev/null
+++ b/test/720-thread-priority/expected.txt
@@ -0,0 +1 @@
+JNI_OnLoad called
diff --git a/test/720-thread-priority/info.txt b/test/720-thread-priority/info.txt
new file mode 100644
index 0000000..0122261
--- /dev/null
+++ b/test/720-thread-priority/info.txt
@@ -0,0 +1,2 @@
+Regression test for Thread.setPriority, which used to always set the priority
+to the main thread, instead of the passed one.
diff --git a/test/720-thread-priority/src/Main.java b/test/720-thread-priority/src/Main.java
new file mode 100644
index 0000000..9ea5cfc
--- /dev/null
+++ b/test/720-thread-priority/src/Main.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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.concurrent.CountDownLatch;
+
+public class Main {
+   static final CountDownLatch processStarted = new CountDownLatch(1);
+   static final CountDownLatch prioritySet = new CountDownLatch(1);
+
+   static int initialPlatformPriority = 0;
+   static int maxPlatformPriority = 0;
+
+   static class MyThread extends Thread {
+        public void run() {
+            try {
+                int priority = getThreadPlatformPriority();
+                if (priority != initialPlatformPriority) {
+                    throw new Error("Expected " + initialPlatformPriority + ", got " + priority);
+                }
+                processStarted.countDown();
+                prioritySet.await();
+                priority = getThreadPlatformPriority();
+                if (priority != maxPlatformPriority) {
+                    throw new Error("Expected " + maxPlatformPriority + ", got " + priority);
+                }
+            } catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.loadLibrary(args[0]);
+
+        // Fetch priorities from the main thread to know what to compare against.
+        int javaPriority = Thread.currentThread().getPriority();
+        initialPlatformPriority = getThreadPlatformPriority();
+        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
+        maxPlatformPriority = getThreadPlatformPriority();
+        Thread.currentThread().setPriority(javaPriority);
+
+        MyThread t1 = new MyThread();
+        t1.start();
+        processStarted.await();
+
+        t1.setPriority(Thread.MAX_PRIORITY);
+        prioritySet.countDown();
+        t1.join();
+    }
+
+    private static native int getThreadPlatformPriority();
+}
diff --git a/test/720-thread-priority/thread_priority.cc b/test/720-thread-priority/thread_priority.cc
new file mode 100644
index 0000000..db4a2b2
--- /dev/null
+++ b/test/720-thread-priority/thread_priority.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 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 <sys/time.h>
+#include <sys/resource.h>
+
+#include "base/macros.h"
+#include "base/utils.h"
+#include "jni.h"
+
+extern "C" JNIEXPORT jint JNICALL Java_Main_getThreadPlatformPriority(
+    JNIEnv* env ATTRIBUTE_UNUSED,
+    jclass clazz ATTRIBUTE_UNUSED) {
+  return getpriority(PRIO_PROCESS, art::GetTid());
+}
diff --git a/test/Android.bp b/test/Android.bp
index 9cf5606..cb9f612 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -496,6 +496,7 @@
         "674-hiddenapi/hiddenapi.cc",
         "692-vdex-inmem-loader/vdex_inmem_loader.cc",
         "708-jit-cache-churn/jit.cc",
+        "720-thread-priority/thread_priority.cc",
         "800-smali/jni.cc",
         "909-attach-agent/disallow_debugging.cc",
         "1001-app-image-regions/app_image_regions.cc",