1 /****************************************************************************** 2 * 3 * Copyright 2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /******************************************************************************* 20 * 21 * Filename: bt_utils.cc 22 * 23 * Description: Miscellaneous helper functions 24 * 25 * 26 ******************************************************************************/ 27 28 #define LOG_TAG "bt_utils" 29 30 #include "bt_utils.h" 31 32 #include <errno.h> 33 #include <pthread.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <sys/resource.h> 37 #include <unistd.h> 38 #include <mutex> 39 40 #define A2DP_RT_PRIORITY 1 41 #ifndef OS_GENERIC 42 #include <cutils/sched_policy.h> 43 #endif 44 45 #include "bt_types.h" 46 #include "btcore/include/module.h" 47 #include "osi/include/compat.h" 48 #include "osi/include/log.h" 49 #include "osi/include/properties.h" 50 51 /******************************************************************************* 52 * Type definitions for callback functions 53 ******************************************************************************/ 54 static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX]; 55 static bool g_DoSchedulingGroup[TASK_HIGH_MAX]; 56 static std::mutex gIdxLock; 57 static int g_TaskIdx; 58 static int g_TaskIDs[TASK_HIGH_MAX]; 59 #define INVALID_TASK_ID (-1) 60 61 static future_t* init(void) { 62 int i; 63 64 for (i = 0; i < TASK_HIGH_MAX; i++) { 65 g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT; 66 g_DoSchedulingGroup[i] = true; 67 g_TaskIDs[i] = INVALID_TASK_ID; 68 } 69 70 return NULL; 71 } 72 73 static future_t* clean_up(void) { 74 return NULL; 75 } 76 77 EXPORT_SYMBOL extern const module_t bt_utils_module = {.name = BT_UTILS_MODULE, 78 .init = init, 79 .start_up = NULL, 80 .shut_down = NULL, 81 .clean_up = clean_up, 82 .dependencies = {NULL}}; 83 84 /***************************************************************************** 85 * 86 * Function check_do_scheduling_group 87 * 88 * Description check if it is ok to change schedule group 89 * 90 * Returns void 91 * 92 ******************************************************************************/ 93 static void check_do_scheduling_group(void) { 94 char buf[PROPERTY_VALUE_MAX]; 95 int len = osi_property_get("debug.sys.noschedgroups", buf, ""); 96 if (len > 0) { 97 int temp; 98 if (sscanf(buf, "%d", &temp) == 1) { 99 g_DoSchedulingGroup[g_TaskIdx] = temp == 0; 100 } 101 } 102 } 103 104 /***************************************************************************** 105 * 106 * Function raise_priority_a2dp 107 * 108 * Description Raise task priority for A2DP streaming 109 * 110 * Returns void 111 * 112 ******************************************************************************/ 113 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { 114 int rc = 0; 115 int tid = gettid(); 116 117 { 118 std::lock_guard<std::mutex> lock(gIdxLock); 119 g_TaskIdx = high_task; 120 121 // TODO(armansito): Remove this conditional check once we find a solution 122 // for system/core on non-Android platforms. 123 #if defined(OS_GENERIC) 124 rc = -1; 125 #else // !defined(OS_GENERIC) 126 pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], 127 check_do_scheduling_group); 128 if (g_DoSchedulingGroup[g_TaskIdx]) { 129 // set_sched_policy does not support tid == 0 130 rc = set_sched_policy(tid, SP_AUDIO_SYS); 131 } 132 #endif // defined(OS_GENERIC) 133 134 g_TaskIDs[high_task] = tid; 135 } 136 137 if (rc) { 138 LOG_WARN(LOG_TAG, "failed to change sched policy, tid %d, err: %d", tid, 139 errno); 140 } 141 142 // make A2DP threads use RT scheduling policy since they are part of the 143 // audio pipeline 144 { 145 struct sched_param rt_params; 146 rt_params.sched_priority = A2DP_RT_PRIORITY; 147 148 const int rc = sched_setscheduler(tid, SCHED_FIFO, &rt_params); 149 if (rc != 0) { 150 LOG_ERROR(LOG_TAG, 151 "%s unable to set SCHED_FIFO priority %d for tid %d, error %s", 152 __func__, A2DP_RT_PRIORITY, tid, strerror(errno)); 153 } 154 } 155 } 156