Home | History | Annotate | Download | only in src
      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