Revert "Revert "Make Bluetooth audio threads use RT scheduling""

This reverts commit feb2d84f4b69392b5f37ae1ec9d53ac728514275.

Bluetooth threads that are used in audio have deadline
requirements for glitchless playback.  Those threads need to be
scheduled as RT tasks to ensure that they can meet the deadline even if
there is high system load.

Bug 37518404

Test:  play Bluetooth audio, check for RT with systrace
(cherry picked from commit 96c42e70f5c6a74a737739aa9c297cd93540f43e)
diff --git a/btif/src/btif_av.cc b/btif/src/btif_av.cc
index 7e4ad4e..4e78fbf 100644
--- a/btif/src/btif_av.cc
+++ b/btif/src/btif_av.cc
@@ -929,17 +929,9 @@
        * see update_audio_focus_state()
        */
       btif_report_audio_state(BTAV_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
-
-      /* increase the a2dp consumer task priority temporarily when start
-      ** audio playing, to avoid overflow the audio packet queue. */
-      adjust_priority_a2dp(true);
-
       break;
 
     case BTIF_SM_EXIT_EVT:
-      /* restore the a2dp consumer task priority when stop audio playing. */
-      adjust_priority_a2dp(false);
-
       break;
 
     case BTIF_AV_START_STREAM_REQ_EVT:
diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc
index 1b875b2..e3223ac 100644
--- a/hci/src/hci_layer.cc
+++ b/hci/src/hci_layer.cc
@@ -63,6 +63,9 @@
 #define DEFAULT_STARTUP_TIMEOUT_MS 8000
 #define STRING_VALUE_OF(x) #x
 
+// RT priority for HCI thread
+static const int BT_HCI_RT_PRIORITY = 1;
+
 // Abort if there is no response to an HCI command.
 static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000;
 
@@ -188,6 +191,9 @@
     LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__);
     goto error;
   }
+  if (!thread_set_rt_priority(thread, BT_HCI_RT_PRIORITY)) {
+    LOG_ERROR(LOG_TAG, "%s unable to make thread RT.", __func__);
+  }
 
   commands_pending_response = list_new(NULL);
   if (!commands_pending_response) {
diff --git a/osi/include/thread.h b/osi/include/thread.h
index de359f7..c8da381 100644
--- a/osi/include/thread.h
+++ b/osi/include/thread.h
@@ -65,6 +65,13 @@
 // Returns true on success.
 bool thread_set_priority(thread_t* thread, int priority);
 
+// Attempts to set |thread| to the real-time SCHED_FIFO |priority|.
+// The |thread| has to be running for this call to succeed.
+// Priority values are valid in the range sched_get_priority_max(SCHED_FIFO)
+// to sched_get_priority_min(SCHED_FIFO).  Larger values are higher priority.
+// Returns true on success.
+bool thread_set_rt_priority(thread_t* thread, int priority);
+
 // Returns true if the current thread is the same as the one represented by
 // |thread|.
 // |thread| may not be NULL.
diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc
index 620e352..684a078 100644
--- a/osi/src/alarm.cc
+++ b/osi/src/alarm.cc
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <malloc.h>
+#include <pthread.h>
 #include <signal.h>
 #include <string.h>
 #include <time.h>
@@ -44,12 +45,9 @@
 #include "osi/include/thread.h"
 #include "osi/include/wakelock.h"
 
-// Make callbacks run at high thread priority. Some callbacks are used for audio
-// related timer tasks as well as re-transmissions etc. Since we at this point
-// cannot differentiate what callback we are dealing with, assume high priority
-// for now.
-// TODO(eisenbach): Determine correct thread priority (from parent?/per alarm?)
-static const int CALLBACK_THREAD_PRIORITY_HIGH = -19;
+// Callback and timer threads should run at RT priority in order to ensure they
+// meet audio deadlines.  Use this priority for all audio/timer related thread.
+static const int THREAD_RT_PRIORITY = 1;
 
 typedef struct {
   size_t count;
@@ -314,7 +312,7 @@
               __func__);
     goto error;
   }
-  thread_set_priority(default_callback_thread, CALLBACK_THREAD_PRIORITY_HIGH);
+  thread_set_rt_priority(default_callback_thread, THREAD_RT_PRIORITY);
   default_callback_queue = fixed_queue_new(SIZE_MAX);
   if (default_callback_queue == NULL) {
     LOG_ERROR(LOG_TAG, "%s unable to create default alarm callbacks queue.",
@@ -330,8 +328,7 @@
     LOG_ERROR(LOG_TAG, "%s unable to create alarm callback thread.", __func__);
     goto error;
   }
-
-  thread_set_priority(dispatcher_thread, CALLBACK_THREAD_PRIORITY_HIGH);
+  thread_set_rt_priority(dispatcher_thread, THREAD_RT_PRIORITY);
   thread_post(dispatcher_thread, callback_dispatch, NULL);
   return true;
 
@@ -625,9 +622,18 @@
   CHECK(timer != NULL);
 
   struct sigevent sigevent;
+  // create timer with RT priority thread
+  pthread_attr_t thread_attr;
+  pthread_attr_init(&thread_attr);
+  pthread_attr_setschedpolicy(&thread_attr, SCHED_FIFO);
+  struct sched_param param;
+  param.sched_priority = THREAD_RT_PRIORITY;
+  pthread_attr_setschedparam(&thread_attr, &param);
+
   memset(&sigevent, 0, sizeof(sigevent));
   sigevent.sigev_notify = SIGEV_THREAD;
   sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
+  sigevent.sigev_notify_attributes = (void*)(&thread_attr);
   if (timer_create(clock_id, &sigevent, timer) == -1) {
     LOG_ERROR(LOG_TAG, "%s unable to create timer with clock %d: %s", __func__,
               clock_id, strerror(errno));
diff --git a/osi/src/thread.cc b/osi/src/thread.cc
index d218129..61b44f2 100644
--- a/osi/src/thread.cc
+++ b/osi/src/thread.cc
@@ -159,6 +159,23 @@
   return true;
 }
 
+bool thread_set_rt_priority(thread_t* thread, int priority) {
+  if (!thread) return false;
+
+  struct sched_param rt_params;
+  rt_params.sched_priority = priority;
+
+  const int rc = sched_setscheduler(thread->tid, SCHED_FIFO, &rt_params);
+  if (rc != 0) {
+    LOG_ERROR(LOG_TAG,
+              "%s unable to set SCHED_FIFO priority %d for tid %d, error %s",
+              __func__, priority, thread->tid, strerror(errno));
+    return false;
+  }
+
+  return true;
+}
+
 bool thread_is_self(const thread_t* thread) {
   CHECK(thread != NULL);
   return !!pthread_equal(pthread_self(), thread->pthread);
diff --git a/stack/btu/btu_init.cc b/stack/btu/btu_init.cc
index c7b2b2a..14612a3 100644
--- a/stack/btu/btu_init.cc
+++ b/stack/btu/btu_init.cc
@@ -36,9 +36,8 @@
 #include "sdpint.h"
 #include "smp_int.h"
 
-// Increase BTU task thread priority to avoid pre-emption
-// of audio realated tasks.
-#define BTU_TASK_THREAD_PRIORITY (-19)
+// RT priority for audio-related tasks
+#define BTU_TASK_RT_PRIORITY 1
 
 extern fixed_queue_t* btif_msg_queue;
 
@@ -130,7 +129,7 @@
   bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME);
   if (bt_workqueue_thread == NULL) goto error_exit;
 
-  thread_set_priority(bt_workqueue_thread, BTU_TASK_THREAD_PRIORITY);
+  thread_set_rt_priority(bt_workqueue_thread, BTU_TASK_RT_PRIORITY);
 
   // Continue startup on bt workqueue thread.
   thread_post(bt_workqueue_thread, btu_task_start_up, NULL);
diff --git a/utils/include/bt_utils.h b/utils/include/bt_utils.h
index 892855e..2b1a7b1 100644
--- a/utils/include/bt_utils.h
+++ b/utils/include/bt_utils.h
@@ -36,6 +36,5 @@
  ******************************************************************************/
 
 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task);
-void adjust_priority_a2dp(int start);
 
 #endif /* BT_UTILS_H */
diff --git a/utils/src/bt_utils.cc b/utils/src/bt_utils.cc
index d7b8ebd..65bd7af 100644
--- a/utils/src/bt_utils.cc
+++ b/utils/src/bt_utils.cc
@@ -37,12 +37,9 @@
 #include <unistd.h>
 #include <mutex>
 
-#ifdef OS_GENERIC
-#define ANDROID_PRIORITY_AUDIO -16
-#define ANDROID_PRIORITY_URGENT_AUDIO -19
-#else
+#define A2DP_RT_PRIORITY 1
+#ifndef OS_GENERIC
 #include <cutils/sched_policy.h>
-#include <utils/ThreadDefs.h>
 #endif
 
 #include "bt_types.h"
@@ -116,7 +113,6 @@
 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) {
   int rc = 0;
   int tid = gettid();
-  int priority = ANDROID_PRIORITY_AUDIO;
 
   {
     std::lock_guard<std::mutex> lock(gIdxLock);
@@ -143,41 +139,17 @@
              errno);
   }
 
-  // always use urgent priority for HCI worker thread until we can adjust
-  // its prio individually. All other threads can be dynamically adjusted voa
-  // adjust_priority_a2dp()
+  // make A2DP threads use RT scheduling policy since they are part of the
+  // audio pipeline
+  {
+    struct sched_param rt_params;
+    rt_params.sched_priority = A2DP_RT_PRIORITY;
 
-  priority = ANDROID_PRIORITY_URGENT_AUDIO;
-
-  if (setpriority(PRIO_PROCESS, tid, priority) < 0) {
-    LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid, priority);
-  }
-}
-
-/*****************************************************************************
- *
- * Function        adjust_priority_a2dp
- *
- * Description     Increase the a2dp consumer task priority temporarily when
- *                 audio starts playing to avoid overflowing the audio packet
- *                 queue. Restore the a2dp consumer task priority when audio
- *                 is not playing.
- *
- * Returns         void
- *
- ******************************************************************************/
-void adjust_priority_a2dp(int start) {
-  int priority = start ? ANDROID_PRIORITY_URGENT_AUDIO : ANDROID_PRIORITY_AUDIO;
-  int tid;
-  int i;
-
-  for (i = 0; i < TASK_HIGH_MAX; i++) {
-    tid = g_TaskIDs[i];
-    if (tid != INVALID_TASK_ID) {
-      if (setpriority(PRIO_PROCESS, tid, priority) < 0) {
-        LOG_WARN(LOG_TAG, "failed to change priority tid: %d to %d", tid,
-                 priority);
-      }
+    const int rc = sched_setscheduler(tid, SCHED_FIFO, &rt_params);
+    if (rc != 0) {
+      LOG_ERROR(LOG_TAG,
+                "%s unable to set SCHED_FIFO priority %d for tid %d, error %s",
+                __func__, A2DP_RT_PRIORITY, tid, strerror(errno));
     }
   }
 }