| /****************************************************************************** |
| * |
| * Copyright (C) 2012 Broadcom Corporation |
| * |
| * 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. |
| * |
| ******************************************************************************/ |
| |
| /************************************************************************************ |
| * |
| * Filename: bt_utils.c |
| * |
| * Description: Miscellaneous helper functions |
| * |
| * |
| ***********************************************************************************/ |
| |
| #define LOG_TAG "BT_UTILS" |
| |
| #include <cutils/properties.h> |
| #include <cutils/sched_policy.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include <sys/resource.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <utils/ThreadDefs.h> |
| |
| #include "bt_types.h" |
| #include "bt_utils.h" |
| #include "module.h" |
| #include "osi/include/log.h" |
| |
| /******************************************************************************* |
| ** Type definitions for callback functions |
| ********************************************************************************/ |
| static pthread_once_t g_DoSchedulingGroupOnce[TASK_HIGH_MAX]; |
| static BOOLEAN g_DoSchedulingGroup[TASK_HIGH_MAX]; |
| static pthread_mutex_t gIdxLock; |
| static int g_TaskIdx; |
| static int g_TaskIDs[TASK_HIGH_MAX]; |
| #define INVALID_TASK_ID (-1) |
| |
| static future_t *init(void) { |
| int i; |
| pthread_mutexattr_t lock_attr; |
| |
| for(i = 0; i < TASK_HIGH_MAX; i++) { |
| g_DoSchedulingGroupOnce[i] = PTHREAD_ONCE_INIT; |
| g_DoSchedulingGroup[i] = TRUE; |
| g_TaskIDs[i] = INVALID_TASK_ID; |
| } |
| |
| pthread_mutexattr_init(&lock_attr); |
| pthread_mutex_init(&gIdxLock, &lock_attr); |
| return NULL; |
| } |
| |
| static future_t *clean_up(void) { |
| pthread_mutex_destroy(&gIdxLock); |
| return NULL; |
| } |
| |
| const module_t bt_utils_module = { |
| .name = BT_UTILS_MODULE, |
| .init = init, |
| .start_up = NULL, |
| .shut_down = NULL, |
| .clean_up = clean_up, |
| .dependencies = { |
| NULL |
| } |
| }; |
| |
| |
| /***************************************************************************** |
| ** |
| ** Function check_do_scheduling_group |
| ** |
| ** Description check if it is ok to change schedule group |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| static void check_do_scheduling_group(void) { |
| char buf[PROPERTY_VALUE_MAX]; |
| int len = property_get("debug.sys.noschedgroups", buf, ""); |
| if (len > 0) { |
| int temp; |
| if (sscanf(buf, "%d", &temp) == 1) { |
| g_DoSchedulingGroup[g_TaskIdx] = temp == 0; |
| } |
| } |
| } |
| |
| /***************************************************************************** |
| ** |
| ** Function raise_priority_a2dp |
| ** |
| ** Description Raise task priority for A2DP streaming |
| ** |
| ** Returns void |
| ** |
| *******************************************************************************/ |
| void raise_priority_a2dp(tHIGH_PRIORITY_TASK high_task) { |
| int rc = 0; |
| int tid = gettid(); |
| int priority = ANDROID_PRIORITY_AUDIO; |
| |
| pthread_mutex_lock(&gIdxLock); |
| g_TaskIdx = high_task; |
| |
| pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group); |
| if (g_DoSchedulingGroup[g_TaskIdx]) { |
| // set_sched_policy does not support tid == 0 |
| rc = set_sched_policy(tid, SP_AUDIO_SYS); |
| } |
| g_TaskIDs[high_task] = tid; |
| pthread_mutex_unlock(&gIdxLock); |
| |
| if (rc) { |
| LOG_WARN("failed to change sched policy, tid %d, err: %d", tid, 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() |
| |
| if (high_task == TASK_HIGH_HCI_WORKER) |
| priority = ANDROID_PRIORITY_URGENT_AUDIO; |
| |
| if (setpriority(PRIO_PROCESS, tid, priority) < 0) { |
| LOG_WARN("failed to change priority tid: %d to %d", tid, priority); |
| } |
| } |
| |
| /***************************************************************************** |
| ** |
| ** Function adjust_priority_a2dp |
| ** |
| ** Description increase the a2dp consumer task priority temporarily when start |
| ** audio playing, to avoid overflow the audio packet queue, restore |
| ** the a2dp consumer task priority when stop audio 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("failed to change priority tid: %d to %d", tid, priority); |
| } |
| } |
| } |
| } |