1 /****************************************************************************** 2 * 3 * Copyright (C) 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.c 22 * 23 * Description: Miscellaneous helper functions 24 * 25 * 26 ***********************************************************************************/ 27 28 #define LOG_TAG "bt_utils" 29 30 #include <cutils/properties.h> 31 #include <cutils/sched_policy.h> 32 #include <errno.h> 33 #include <pthread.h> 34 #include <sys/resource.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <utils/ThreadDefs.h> 39 40 #include "bt_types.h" 41 #include "bt_utils.h" 42 #include "btcore/include/module.h" 43 #include "osi/include/compat.h" 44 #include "osi/include/log.h" 45 46 /******************************************************************************* 47 ** Type definitions for callback functions 48 ********************************************************************************/ 49 static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX]; 50 static BOOLEAN g_DoSchedulingGroup[TASK_HIGH_MAX]; 51 static pthread_mutex_t gIdxLock; 52 static int g_TaskIdx; 53 static int g_TaskIDs[TASK_HIGH_MAX]; 54 #define INVALID_TASK_ID (-1) 55 56 static future_t *init(void) { 57 int i; 58 pthread_mutexattr_t lock_attr; 59 60 for(i = 0; i < TASK_HIGH_MAX; i++) { 61 g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT; 62 g_DoSchedulingGroup[i] = TRUE; 63 g_TaskIDs[i] = INVALID_TASK_ID; 64 } 65 66 pthread_mutexattr_init(&lock_attr); 67 pthread_mutex_init(&gIdxLock, &lock_attr); 68 return NULL; 69 } 70 71 static future_t *clean_up(void) { 72 pthread_mutex_destroy(&gIdxLock); 73 return NULL; 74 } 75 76 const module_t bt_utils_module = { 77 .name = BT_UTILS_MODULE, 78 .init = init, 79 .start_up = NULL, 80 .shut_down = NULL, 81 .clean_up = clean_up, 82 .dependencies = { 83 NULL 84 } 85 }; 86 87 88 /***************************************************************************** 89 ** 90 ** Function check_do_scheduling_group 91 ** 92 ** Description check if it is ok to change schedule group 93 ** 94 ** Returns void 95 ** 96 *******************************************************************************/ 97 static void check_do_scheduling_group(void) { 98 char buf[PROPERTY_VALUE_MAX]; 99 int len = property_get("debug.sys.noschedgroups", buf, ""); 100 if (len > 0) { 101 int temp; 102 if (sscanf(buf, "%d", &temp) == 1) { 103 g_DoSchedulingGroup[g_TaskIdx] = temp == 0; 104 } 105 } 106 } 107 108 /***************************************************************************** 109 ** 110 ** Function raise_priority_a2dp 111 ** 112 ** Description Raise task priority for A2DP streaming 113 ** 114 ** Returns void 115 ** 116 *******************************************************************************/ 117 void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { 118 int rc = 0; 119 int tid = gettid(); 120 int priority = ANDROID_PRIORITY_AUDIO; 121 122 pthread_mutex_lock(&gIdxLock); 123 g_TaskIdx = high_task; 124 125 pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group); 126 if (g_DoSchedulingGroup[g_TaskIdx]) { 127 // set_sched_policy does not support tid == 0 128 rc = set_sched_policy(tid, SP_AUDIO_SYS); 129 } 130 g_TaskIDs[high_task] = tid; 131 pthread_mutex_unlock(&gIdxLock); 132 133 if (rc) { 134 LOG_WARN("failed to change sched policy, tid %d, err: %d", tid, errno); 135 } 136 137 // always use urgent priority for HCI worker thread until we can adjust 138 // its prio individually. All other threads can be dynamically adjusted voa 139 // adjust_priority_a2dp() 140 141 if (high_task == TASK_HIGH_HCI_WORKER) 142 priority = ANDROID_PRIORITY_URGENT_AUDIO; 143 144 if (setpriority(PRIO_PROCESS, tid, priority) < 0) { 145 LOG_WARN("failed to change priority tid: %d to %d", tid, priority); 146 } 147 } 148 149 /***************************************************************************** 150 ** 151 ** Function adjust_priority_a2dp 152 ** 153 ** Description increase the a2dp consumer task priority temporarily when start 154 ** audio playing, to avoid overflow the audio packet queue, restore 155 ** the a2dp consumer task priority when stop audio playing. 156 ** 157 ** Returns void 158 ** 159 *******************************************************************************/ 160 void adjust_priority_a2dp(int start) { 161 int priority = start ? ANDROID_PRIORITY_URGENT_AUDIO : ANDROID_PRIORITY_AUDIO; 162 int tid; 163 int i; 164 165 for (i = 0; i < TASK_HIGH_MAX; i++) 166 { 167 tid = g_TaskIDs[i]; 168 if (tid != INVALID_TASK_ID) 169 { 170 if (setpriority(PRIO_PROCESS, tid, priority) < 0) 171 { 172 LOG_WARN("failed to change priority tid: %d to %d", tid, priority); 173 } 174 } 175 } 176 } 177