/***************************************************************************** * FUNCTION * mmi_opp_scr_recv_obj_ind * DESCRIPTION * This function is to display popup sceren when receiving file * PARAMETERS * cause [IN] * RETURNS * void *****************************************************************************/ void mmi_opp_scr_recv_obj_ind(void) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ static BOOL previousInVdoApp=0; if (opp_suppress_popup_flag == MMI_TRUE || (isInCall() && !GetWapCallPresent())) { /* * If the applications won't want to show the WAP/MMS popup or * the handset has the voice call, * we return here directly. */ g_NeedRecheckOppRecv = 1; return ; } MMI_OPP_RECV_IND_STR() ; if ((isInCall() != MMI_TRUE) || (IsWapCallPresent()) ||opp_suppress_popup_flag==MMI_FALSE) { #if defined(__MMI_VIDEO_PLAYER__) /* Play warning tone to notify file saved */ if (mmi_vdoply_is_in_app()) { DisplayPopup(mmi_opp_recv_notify_str, IMG_GLOBAL_ACTIVATED, 1, UI_POPUP_NOTIFYDURATION_TIME, WARNING_TONE); g_NeedRecheckOppRecv = 1; previousInVdoApp = 1; } else #endif { if (previousInVdoApp) { previousInVdoApp = 0; mmi_opp_entry_idle_notify_scr(); } else DisplayPopupCallBack(mmi_opp_recv_notify_str, IMG_GLOBAL_ACTIVATED, 1, UI_POPUP_NOTIFYDURATION_TIME, WARNING_TONE,mmi_opp_entry_idle_notify_scr); MMI_OPP_CTX(cur_recv_file_cnt) = 0; } } /* if (g_idle_context.IsOnIdleScreen || GetActiveScreenId() == SCR_OPP_NOTY_FILE_RECV) { EntryIdleScreen(); } else { // mmi_opp_entry_idle_notify_scr(); } */ TurnOnBacklight(1); }
int main() { printf("endeavoru - in call volume adjustment - t3_calld starting.\n"); printf("(c) 2012 Illes Pal Zoltan aka tbalden\n"); int fbfd = 0; int keyfd = 0; int backlightfd = 0; struct input_event event; keyfd = open("/dev/input/event2", O_RDWR); if (!keyfd) { printf("Error: cannot open gpio-event input device.\n"); exit(1); } int volumeNeedReset = 0; char buffer [50]; static const char vol_filename[] = "/data/misc/in_call_vol"; //static const char filename[] = "/proc/asound/card1/pcm0p/sub0/status"; while(1) { FILE *vol_file = fopen ( vol_filename, "r" ); if ( vol_file != NULL ) { if (isInCall()) { volumeNeedReset = 1; char line [ 128 ]; if ( fgets ( line, sizeof line, vol_file ) != NULL ) { sprintf(buffer, "/system/bin/snd3008 -v %s", line); printf("set volume to: %s\n",buffer); system(buffer); } } else { if (volumeNeedReset) { // no call, but vol_file present: delete it and set overall volume to max printf("call ended, overall volume back to max\n"); volumeNeedReset = 0; sleep(1); system("/system/bin/snd3008 -v 15"); } } fclose ( vol_file ); } else { printf("no /data/misc/in_call_vol file. sleep."); } sleep(2-volumeNeedReset); // if volume might need reset (in call or just ended), lets sleep only 1 sec } return 0; }
status_t AudioPolicyManager::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { LOGV("stopOutput() output %d, stream %d", output, stream); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("stopOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); routing_strategy strategy = AudioPolicyManagerBase::getStrategy((AudioSystem::stream_type)stream); // handle special case for sonification while in call if (isInCall()) { AudioPolicyManagerBase::handleIncallSonification(stream, false, false); } if (outputDesc->mRefCount[stream] > 0) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); // store time at which the last music track was stopped - see computeVolume() if (stream == AudioSystem::MUSIC) { outputDesc->mStopTime[stream] = systemTime(); // mMusicStopTime = systemTime(); } #ifdef WITH_QCOM_LPA uint32_t newDevice = AudioPolicyManagerBase::getNewDevice(mHardwareOutput, false); if(newDevice == 0 && mLPADecodeOutput != -1) { newDevice = AudioPolicyManagerBase::getNewDevice(mLPADecodeOutput, false); } setOutputDevice(output, newDevice); #else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #ifdef WITH_A2DP if (mA2dpOutput != 0 && !a2dpUsedForSonification() && (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) { setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2); } #endif if (output != mHardwareOutput) { setOutputDevice(mHardwareOutput, AudioPolicyManagerBase::getNewDevice(mHardwareOutput), true); } return NO_ERROR; } else { LOGW("stopOutput() refcount is already 0 for output %d", output); return INVALID_OPERATION; } }
status_t AudioPolicyManager::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { LOGV("startOutput() output %d, stream %d", output, stream); ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { LOGW("startOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); #ifdef WITH_A2DP if (mA2dpOutput != 0 && !a2dpUsedForSonification() && (strategy == STRATEGY_SONIFICATION || strategy == STRATEGY_ENFORCED_AUDIBLE)) { setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); } #endif // incremenent usage count for this stream on the requested output: // NOTE that the usage count is the same for duplicated output and hardware output which is // necassary for a correct control of hardware output routing by startOutput() and stopOutput() outputDesc->changeRefCount(stream, 1); #ifdef FM_RADIO #ifdef WITH_QCOM_LPA if ((stream == AudioSystem::FM && output == mA2dpOutput) || output == mLPADecodeOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #else if (stream == AudioSystem::FM && output == mA2dpOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #else #ifdef WITH_QCOM_LPA if (output == mLPADecodeOutput) setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output), true); else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #else setOutputDevice(output, AudioPolicyManagerBase::getNewDevice(output)); #endif #endif // handle special case for sonification while in call if (isInCall()) { AudioPolicyManagerBase::handleIncallSonification(stream, true, false); } // apply volume rules for current stream and device if necessary checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device()); return NO_ERROR; }
void jWap_PopupCallBack() { INT iErr ; ST_BE_PAGE_CONTENT stPageCont ; jc_memset (&stPageCont, 0, sizeof (ST_BE_PAGE_CONTENT)) ; mmi_trace (1, "JDD_LOG: jWap_PopupCallBack starts") ; if((!isInWapApp())||isInCall()) { GoBackHistory(); mmi_trace (1, "JDD_LOG: go back screen ignoring") ; return; } if (E_WAP_EXIT_KEY_END == g_pstJWapAppInfo->stWapState.eWapExitKeyPressed) { mmi_trace (1, "JDD_LOG: aborting screen ignoring") ; return; } iErr = jdi_BEGetPageContent (g_pstJWapAppInfo->hBECore, &stPageCont) ; if (iErr) { // There is no content displayed on Primary MMI jWap_options_quit_handler () ; } else { if (!jWap_isBack ()) { //ChangeRightSoftkey (STR_GLOBAL_QUIT, 0) ; //This is the first page. Remove RSK ClearKeyHandler (KEY_RSK, KEY_EVENT_DOWN) ; } else { // There are more than 1 page. Set to "Back" ChangeRightSoftkey (STR_GLOBAL_BACK, 0) ; SetRightSoftkeyFunction (jWap_back, KEY_EVENT_UP) ; } ChangeLeftSoftkey (STR_GLOBAL_OPTIONS, 0) ; SetLeftSoftkeyFunction (jWap_options_handler, KEY_EVENT_UP) ; ChangeTitleIcon (IMG_ID_JATAAYU_WAP_END_ANIMATION_GIF) ; //setup_scrolling_title () ; draw_title () ; jmms_goto_primaryMMI(); } mmi_trace (1, "@@@ jWap_PopupCallBack end @@@") ; }
routing_strategy Engine::getStrategyForUsage(audio_usage_t usage) { const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); // usage to strategy mapping switch (usage) { case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: if (outputs.isStreamActive(AUDIO_STREAM_RING) || outputs.isStreamActive(AUDIO_STREAM_ALARM)) { return STRATEGY_SONIFICATION; } if (isInCall()) { return STRATEGY_PHONE; } return STRATEGY_ACCESSIBILITY; case AUDIO_USAGE_MEDIA: case AUDIO_USAGE_GAME: case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: case AUDIO_USAGE_ASSISTANCE_SONIFICATION: return STRATEGY_MEDIA; case AUDIO_USAGE_VOICE_COMMUNICATION: return STRATEGY_PHONE; case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING: return STRATEGY_DTMF; case AUDIO_USAGE_ALARM: case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE: return STRATEGY_SONIFICATION; case AUDIO_USAGE_NOTIFICATION: case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST: case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT: case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED: case AUDIO_USAGE_NOTIFICATION_EVENT: return STRATEGY_SONIFICATION_RESPECTFUL; case AUDIO_USAGE_UNKNOWN: default: return STRATEGY_MEDIA; } }
/***************************************************************************** * FUNCTION * mmi_java_is_in_voice_call * DESCRIPTION * this function use to detect taht current have voice call or not * PARAMETERS * void * RETURNS * MMI_TRUE or MMI_FALSE *****************************************************************************/ BOOL mmi_java_is_in_voice_call(void) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ if( AlmIsTonePlaying()) { return MMI_TRUE; } if ( isInCall() == MMI_TRUE ) { /* wap call connecting => true wap call connected => false other call connecting/connected => true */ if( GetWapCallPresent() ) { return MMI_FALSE; } else { return MMI_TRUE; } } else { if (GetActiveScreenId()==GetCmMarkerScrnID() || IsScreenPresent(GetCmMarkerScrnID())) { /* special case here, sometimes CM change state too early but still have call marker in the history */ return MMI_TRUE; } return MMI_FALSE; } }
float AudioPolicyManager::computeVolume(int stream, int index, audio_io_handle_t output, /*uint32_t*/ audio_devices_t device) { // if requested volume index is the minimum possible value, we must honor this value as this // means the stream is muted. This overrides condition-specific modifications to the volume // computed in the generic APM if (index == mStreams[stream].mIndexMin) { return AudioPolicyManagerBase::computeVolume(stream, index, output, device); } // force volume on A2DP output to maximum if playing through car dock speakers // as volume is applied on the car dock and controlled via car dock keys. #ifdef WITH_A2DP if (output == getA2dpOutput() && mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) { return 1.0; } #endif float volume = AudioPolicyManagerBase::computeVolume(stream, index, output, device); // limit stream volume when in call and playing over bluetooth SCO device to // avoid saturation if (isInCall() && AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) { if (volume > IN_CALL_SCO_VOLUME_MAX) { ALOGV("computeVolume limiting SYSTEM volume %f to %f",volume, IN_CALL_SCO_VOLUME_MAX); volume = IN_CALL_SCO_VOLUME_MAX; } } // in car dock: when using the 3.5mm jack to play media, set a minimum volume as access to the // physical volume keys is blocked by the car dock frame. if ((mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) && (volume < CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN) && (stream == AudioSystem::MUSIC) && (device & (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_WIRED_HEADSET))) { volume = CAR_DOCK_MUSIC_MINI_JACK_VOLUME_MIN; } return volume; }
void mmi_bth_simap_authroize_hdler(void* msg) { /* Check MS's call state */ bt_simap_auth_rsp_struct* bt_simap_auth_rsp = NULL; kal_bool incall = isInCall(); bt_simap_auth_rsp = construct_local_para (sizeof(bt_simap_auth_rsp_struct),TD_UL); if(incall) { bt_simap_auth_rsp->result = KAL_FALSE; /* Not accept SAP connection */ //PRINT_INFORMATION("MS has an call detected in mmi_bth_simap_authroize_hdler()"); } else { bt_simap_auth_rsp->result = KAL_TRUE; /* Accept SAP connection */ //PRINT_INFORMATION("MS has no call detected in mmi_bth_simap_authroize_hdler()"); } mmi_bth_send_msg(MOD_BT, BT_APP_SAP, MSG_ID_BT_SIMAP_AUTH_RSP, (local_para_struct*)bt_simap_auth_rsp, NULL); }
/***************************************************************************** * FUNCTION * mmi_syncml_finish_sync_ind * DESCRIPTION * Protocol event handler * PARAMETERS * info [IN] message content * RETURNS * void *****************************************************************************/ void mmi_syncml_finish_sync_ind(void *info) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ mmi_syncml_finish_sync_ind_struct *local_data = (mmi_syncml_finish_sync_ind_struct*) info; U16 string_id = STR_ID_SYNC_DEFAULT_FAIL; U16 image_id = IMG_GLOBAL_UNFINISHED; U8 tone_id = ERROR_TONE; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ if (!mmi_syncml_is_phb_sync_now() && !mmi_syncml_is_tdl_sync_now()) { return; } g_syncml_context.contact_sync_state = 0; g_syncml_context.calendar_sync_state = 0; g_syncml_context.abort_state = 0; g_syncml_context.sync_progress = 0xFF; g_syncml_context.contact_send_noc = 0; g_syncml_context.contact_send_current = 0; g_syncml_context.contact_recv_noc = 0; g_syncml_context.contact_recv_current = 0; g_syncml_context.calendar_send_noc = 0; g_syncml_context.calendar_send_current = 0; g_syncml_context.calendar_recv_noc = 0; g_syncml_context.calendar_recv_current = 0; mmi_syncml_free_vobj_buffer(); switch (local_data->result) { /* process local err */ case SYNCML_LOCAL_DB_FULL: string_id = STR_ID_SYNC_LOCALDB_FULL; break; /* process server err */ case SYNCML_OK: /* 200 */ string_id = STR_ID_SYNC_DONE; image_id = IMG_GLOBAL_ACTIVATED; tone_id = SUCCESS_TONE; break; case SYNCML_INVALID_CREDENTIAL: /* 401 */ string_id = STR_ID_SYNC_INVALID_CREDENTIAL; break; case SYNCML_MISSING_CREDENTIAL: /* 407 */ string_id = STR_ID_SYNC_MISSING_CREDENTIAL; break; case SYNCML_PAYMENT_REQUIRED: /* 402 */ string_id = STR_ID_SYNC_PAYMENT_REQUIRED; image_id = IMG_GLOBAL_WARNING; tone_id = WARNING_TONE; break; case SYNCML_CODE_FORBIDDEN: /* 403 */ string_id = STR_ID_SYNC_CODE_FORBIDDEN; break; case SYNCML_INCOMPLETE_CMD: /* 412 */ string_id = STR_ID_SYNC_INCOMPLETE_CMD; break; case SYNCML_DEVICE_FULL: /* 420 */ string_id = STR_ID_SYNC_SVR_DEVICE_FULL; break; case SYNCML_SERVICE_UNAVAILABLE: /* 503 */ string_id = STR_ID_SYNC_SERVICE_UNAVAILABLE; break; case SYNCML_DATASTORE_FAIL: /* 510 */ string_id = STR_ID_SYNC_DATASTORE_FAIL; break; case SYNCML_SVR_FAIL: /* 511 */ string_id = STR_ID_SYNC_SVR_FAIL; break; case SYNCML_ERR_OCCUR: /* 512 */ string_id = STR_ID_SYNC_ERR_OCCUR; break; case SYNCML_PROTOCOL_UNSUPPORT: /* 513 */ string_id = STR_ID_SYNC_PROTOCOL_UNSUPPORT; break; case SYNCML_FAIL: /* 500 */ string_id = STR_ID_SYNC_FAIL; break; case SYNCML_ABORT_SYNC: default: break; } DisplayPopup( (U8*) GetString(string_id), image_id, 1, UI_POPUP_NOTIFYDURATION_TIME, tone_id); SetDelScrnIDCallbackHandler(SCR_ID_SYNC_NOW, NULL); DeleteScreenIfPresent(SCR_ID_SYNC_ABORT); DeleteScreenIfPresent(SCR_ID_SYNC_BACKGROUND_QUERY); if (local_data->result == SYNCML_OK) { /* update the last anchor because of sync completion */ if (g_syncml_context.applications_to_sync & SYNCML_DB_PHONEBOOK) { g_syncml_context.last_phb_anchor[g_syncml_context.active_profile - 1] = g_syncml_context.next_phb_anchor; memcpy(g_syncml_context.svr_contact_ok_cnt, local_data->svr_contact_ok_cnt, sizeof(g_syncml_context.svr_contact_ok_cnt)); g_syncml_context.svr_contact_ng_cnt = local_data->svr_contact_ng_cnt; } if (g_syncml_context.applications_to_sync & SYNCML_DB_TODOLIST) { g_syncml_context.last_tdl_anchor[g_syncml_context.active_profile - 1] = g_syncml_context.next_tdl_anchor; memcpy(g_syncml_context.svr_calendar_ok_cnt, local_data->svr_calendar_ok_cnt, sizeof(g_syncml_context.svr_calendar_ok_cnt)); g_syncml_context.svr_calendar_ng_cnt = local_data->svr_calendar_ng_cnt; } mmi_syncml_update_settings_to_nvram(); /* sync report */ if (g_syncml_context.sync_report_status) { if (IsScreenPresent(SCR_ID_SYNC_NOW)) { HistoryReplace(SCR_ID_SYNC_NOW, SCR_ID_SYNC_REPORT, mmi_syncml_entry_sync_report); } else if (isInCall()) { mmi_frm_add_history_before_cm_marker(SCR_ID_SYNC_REPORT, mmi_syncml_entry_sync_report); } else { GenericExitScreen(SCR_ID_SYNC_REPORT, mmi_syncml_entry_sync_report); } } else { DeleteScreenIfPresent(SCR_ID_SYNC_NOW); } } else { DeleteScreenIfPresent(SCR_ID_SYNC_NOW); if (g_syncml_context.applications_to_sync & SYNCML_DB_PHONEBOOK) { g_syncml_context.next_phb_anchor = g_syncml_context.last_phb_anchor[g_syncml_context.active_profile - 1]; } if (g_syncml_context.applications_to_sync & SYNCML_DB_TODOLIST) { g_syncml_context.next_tdl_anchor = g_syncml_context.last_tdl_anchor[g_syncml_context.active_profile - 1]; } } if (g_syncml_context.applications_to_sync & SYNCML_DB_TODOLIST) { AlmEnableExpiryHandler(); /* enable alarm */ } #ifdef __MMI_SYNCML_SERVER_ALERT_SYNC_SUPPORT__ mmi_syncml_sas_finish(); #endif }
audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const { const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices(); const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices(); const SwAudioOutputCollection &outputs = mApmObserver->getOutputs(); uint32_t device = AUDIO_DEVICE_NONE; uint32_t availableOutputDevicesType = availableOutputDevices.types(); switch (strategy) { case STRATEGY_TRANSMITTED_THROUGH_SPEAKER: device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; if (!device) { ALOGE("getDeviceForStrategy() no device found for "\ "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"); } break; case STRATEGY_SONIFICATION_RESPECTFUL: if (isInCall()) { device = getDeviceForStrategy(STRATEGY_SONIFICATION); } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { // while media is playing on a remote device, use the the sonification behavior. // Note that we test this usecase before testing if media is playing because // the isStreamActive() method only informs about the activity of a stream, not // if it's for local playback. Note also that we use the same delay between both tests device = getDeviceForStrategy(STRATEGY_SONIFICATION); //user "safe" speaker if available instead of normal speaker to avoid triggering //other acoustic safety mechanisms for notification if ((device & AUDIO_DEVICE_OUT_SPEAKER) && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; device &= ~AUDIO_DEVICE_OUT_SPEAKER; } } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { // while media is playing (or has recently played), use the same device device = getDeviceForStrategy(STRATEGY_MEDIA); } else { // when media is not playing anymore, fall back on the sonification behavior device = getDeviceForStrategy(STRATEGY_SONIFICATION); //user "safe" speaker if available instead of normal speaker to avoid triggering //other acoustic safety mechanisms for notification if ((device & AUDIO_DEVICE_OUT_SPEAKER) && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) { device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE; device &= ~AUDIO_DEVICE_OUT_SPEAKER; } } break; case STRATEGY_DTMF: if (!isInCall()) { // when off call, DTMF strategy follows the same rules as MEDIA strategy device = getDeviceForStrategy(STRATEGY_MEDIA); break; } // when in call, DTMF and PHONE strategies follow the same rules // FALL THROUGH case STRATEGY_PHONE: // Force use of only devices on primary output if: // - in call AND // - cannot route from voice call RX OR // - audio HAL version is < 3.0 and TX device is on the primary HW module if (getPhoneState() == AUDIO_MODE_IN_CALL) { audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION); sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput(); audio_devices_t availPrimaryInputDevices = availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle()); audio_devices_t availPrimaryOutputDevices = primaryOutput->supportedDevices() & availableOutputDevices.types(); if (((availableInputDevices.types() & AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) || (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) && (primaryOutput->getAudioPort()->getModuleVersion() < AUDIO_DEVICE_API_VERSION_3_0))) { availableOutputDevicesType = availPrimaryOutputDevices; } } // for phone strategy, we first consider the forced use and then the available devices by order // of priority switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) { case AUDIO_POLICY_FORCE_BT_SCO: if (!isInCall() || strategy != STRATEGY_DTMF) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; if (device) break; // if SCO device is requested but no SCO device is available, fall back to default case // FALL THROUGH default: // FORCE_NONE // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP if (!isInCall() && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (outputs.getA2dpOutput() != 0)) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; if (device) break; } device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; if (!isInCall()) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE; if (device) break; device = mApmObserver->getDefaultOutputDevice()->type(); if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); } break; case AUDIO_POLICY_FORCE_SPEAKER: // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to // A2DP speaker when forcing to speaker output if (!isInCall() && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (outputs.getA2dpOutput() != 0)) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; if (device) break; } if (!isInCall()) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; if (device) break; device = mApmObserver->getDefaultOutputDevice()->type(); if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); } break; } break; case STRATEGY_SONIFICATION: // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by // handleIncallSonification(). if (isInCall()) { device = getDeviceForStrategy(STRATEGY_PHONE); break; } // FALL THROUGH case STRATEGY_ENFORCED_AUDIBLE: // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION // except: // - when in call where it doesn't default to STRATEGY_PHONE behavior // - in countries where not enforced in which case it follows STRATEGY_MEDIA if ((strategy == STRATEGY_SONIFICATION) || (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) { device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); } } // The second device used for sonification is the same as the device used by media strategy // FALL THROUGH // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now case STRATEGY_ACCESSIBILITY: if (strategy == STRATEGY_ACCESSIBILITY) { // do not route accessibility prompts to a digital output currently configured with a // compressed format as they would likely not be mixed and dropped. for (size_t i = 0; i < outputs.size(); i++) { sp<AudioOutputDescriptor> desc = outputs.valueAt(i); audio_devices_t devices = desc->device() & (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC); if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) && devices != AUDIO_DEVICE_NONE) { availableOutputDevicesType = availableOutputDevices.types() & ~devices; } } } // FALL THROUGH case STRATEGY_REROUTING: case STRATEGY_MEDIA: { uint32_t device2 = AUDIO_DEVICE_NONE; if (strategy != STRATEGY_SONIFICATION) { // no sonification on remote submix (e.g. WFD) if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) { device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; } } if (isInCall() && (strategy == STRATEGY_MEDIA)) { device = getDeviceForStrategy(STRATEGY_PHONE); break; } if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (outputs.getA2dpOutput() != 0)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } } if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; } if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { // no sonification on aux digital (e.g. HDMI) device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; } if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; } int device3 = AUDIO_DEVICE_NONE; if (strategy == STRATEGY_MEDIA) { // ARC, SPDIF and AUX_LINE can co-exist with others. device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC; device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF); device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE); } device2 |= device3; // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise device |= device2; // If hdmi system audio mode is on, remove speaker out of output list. if ((strategy == STRATEGY_MEDIA) && (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] == AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { device &= ~AUDIO_DEVICE_OUT_SPEAKER; } if (device) break; device = mApmObserver->getDefaultOutputDevice()->type(); if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA"); } } break; default: ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); break; } ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return device; }
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache) { uint32_t device = 0; if (fromCache) { device = mDeviceForStrategy[strategy]; ALOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, device); return (audio_devices_t)device; } switch (strategy) { case STRATEGY_DTMF: if (!isInCall()) { // when off call, DTMF strategy follows the same rules as MEDIA strategy device = getDeviceForStrategy(STRATEGY_MEDIA, false); break; } // when in call, DTMF and PHONE strategies follow the same rules // FALL THROUGH case STRATEGY_PHONE: // for phone strategy, we first consider the forced use and then the available devices by order // of priority switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { case AudioSystem::FORCE_BT_SCO: if (!isInCall() || strategy != STRATEGY_DTMF) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } // otherwise (not docked) continue with selection device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO; if (device) break; // if SCO device is requested but no SCO device is available, fall back to default case // FALL THROUGH default: // FORCE_NONE device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; if (device) break; // when not in call: if (!isInCall()) { // - if we are docked to a BT CAR dock, give A2DP preference over earpiece // - if we are docked to a BT DESK dock, give speaker preference over earpiece if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; } else if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_DESK_DOCK) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; } if (device) break; // - phone strategy should route STREAM_VOICE_CALL to A2DP device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; if (device) break; } /* device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; if (device == 0) { ALOGE ("getDeviceForStrategy() earpiece device not found"); } */ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { ALOGE ("getDeviceForStrategy() speaker device not found"); } break; case AudioSystem::FORCE_SPEAKER: if (!isInCall() || strategy != STRATEGY_DTMF) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } // when not in call: if (!isInCall()) { // - if we are docked to a BT CAR dock, give A2DP preference over phone spkr if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; } // - phone strategy should route STREAM_VOICE_CALL to A2DP speaker // when forcing to speaker output device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; if (device) break; } device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { ALOGE ("getDeviceForStrategy() speaker device not found"); } break; } break; case STRATEGY_SONIFICATION: // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by // handleIncallSonification(). if (isInCall()) { device = getDeviceForStrategy(STRATEGY_PHONE, false); break; } // If not incall: // - if we are docked to a BT CAR dock, don't duplicate for the sonification strategy // - if we are docked to a BT DESK dock, use only speaker for the sonification strategy if (mForceUse[AudioSystem::FOR_DOCK] != AudioSystem::FORCE_BT_CAR_DOCK) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { ALOGE ("getDeviceForStrategy() speaker device not found"); } if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_DESK_DOCK) { if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) { device |= AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; } else if (mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) { device |= AudioSystem::DEVICE_OUT_WIRED_HEADSET; } break; } } else { device = 0; } // The second device used for sonification is the same as the device used by media strategy // Note that when docked, we pick the device below (no duplication) // FALL THROUGH case STRATEGY_MEDIA: { uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; #ifdef WITH_A2DP if (mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { if (device2 == 0) { // play ringtone over speaker (or speaker + headset) if in car dock // because A2DP is suspended in this case if (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_BT_CAR_DOCK && strategy == STRATEGY_SONIFICATION && mPhoneState == AudioSystem::MODE_RINGTONE) { device2 = mAvailableOutputDevices & (AudioSystem::DEVICE_OUT_SPEAKER | AudioSystem::DEVICE_OUT_WIRED_HEADPHONE | AudioSystem::DEVICE_OUT_WIRED_HEADSET); } } } #endif if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; } #ifdef WITH_A2DP if (mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } } #endif if (device2 == 0) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; } // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise device |= device2; if (device == 0) { ALOGE ("getDeviceForStrategy() speaker device not found"); } // Do not play media stream if in call and the requested device would change the hardware // output routing if (isInCall() && !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) && device != getDeviceForStrategy(STRATEGY_PHONE, false)) { device = 0; ALOGV("getDeviceForStrategy() incompatible media and phone devices"); } } break; case STRATEGY_ENFORCED_AUDIBLE: // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION // except: // - when in call where it doesn't default to STRATEGY_PHONE behavior // - in countries where not enforced in which case it follows STRATEGY_MEDIA if (strategy == STRATEGY_SONIFICATION || !mStreams[AUDIO_STREAM_ENFORCED_AUDIBLE].mCanBeMuted) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); } } case STRATEGY_SONIFICATION_RESPECTFUL: if (isInCall()) { device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } else if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { // while media is playing (or has recently played), use the same device device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); } else { // when media is not playing anymore, fall back on the sonification behavior device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } break; default: ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); break; } ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return (audio_devices_t)device; }
void AudioPolicyManager::setPhoneState(int state) { ALOGV("setPhoneState() state %d", state); audio_devices_t newDevice = AUDIO_DEVICE_NONE; if (state < 0 || state >= AudioSystem::NUM_MODES) { ALOGW("setPhoneState() invalid state %d", state); return; } if (state == mPhoneState) { ALOGW("setPhoneState() setting same state %d", state); return; } // if leaving call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isInCall()) { ALOGV("setPhoneState() in call state management: new state is %d", state); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { handleIncallSonification(stream, false, true); } } // store previous phone state for management of sonification strategy below int oldState = mPhoneState; mPhoneState = state; bool force = false; // are we entering or starting a call if (!isStateInCall(oldState) && isStateInCall(state)) { ALOGV(" Entering call in setPhoneState()"); // force routing command to audio hardware when starting a call // even if no device change is needed force = true; } else if (isStateInCall(oldState) && !isStateInCall(state)) { ALOGV(" Exiting call in setPhoneState()"); // force routing command to audio hardware when exiting a call // even if no device change is needed force = true; } else if (isStateInCall(state) && (state != oldState)) { ALOGV(" Switching between telephony and VoIP in setPhoneState()"); // force routing command to audio hardware when switching between telephony and VoIP // even if no device change is needed force = true; } // check for device and output changes triggered by new phone state newDevice = getNewDevice(mPrimaryOutput, false /*fromCache*/); checkA2dpSuspend(); checkOutputForAllStrategies(); updateDevicesAndOutputs(); AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mPrimaryOutput); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && newDevice == AUDIO_DEVICE_NONE) { newDevice = hwOutputDesc->device(); } // when changing from ring tone to in call mode, mute the ringing tone // immediately and delay the route change to avoid sending the ring tone // tail into the earpiece or headset. int delayMs = 0; if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { // delay the device change command by twice the output latency to have some margin // and be sure that audio buffers not yet affected by the mute are out when // we actually apply the route change delayMs = hwOutputDesc->mLatency*2; setStreamMute(AudioSystem::RING, true, mPrimaryOutput); } if (isStateInCall(state)) { for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueAt(i); //take the biggest latency for all outputs if (delayMs < desc->mLatency*2) { delayMs = desc->mLatency*2; } //mute STRATEGY_MEDIA on all outputs if (desc->strategyRefCount(STRATEGY_MEDIA) != 0) { setStrategyMute(STRATEGY_MEDIA, true, mOutputs.keyAt(i)); setStrategyMute(STRATEGY_MEDIA, false, mOutputs.keyAt(i), MUTE_TIME_MS, getDeviceForStrategy(STRATEGY_MEDIA, true /*fromCache*/)); } } } // Ignore the delay to enable voice call on this target as the enabling the // voice call has enough delay to make sure the ringtone audio completely // played out if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) { delayMs = 40; } // change routing is necessary setOutputDevice(mPrimaryOutput, newDevice, force, delayMs); // if entering in call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isStateInCall(state)) { ALOGV("setPhoneState() in call state management: new state is %d", state); // unmute the ringing tone after a sufficient delay if it was muted before // setting output device above if (oldState == AudioSystem::MODE_RINGTONE) { setStreamMute(AudioSystem::RING, false, mPrimaryOutput, MUTE_TIME_MS); } for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { handleIncallSonification(stream, true, true); } } // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && isStreamActive(AudioSystem::MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; } }
uint32_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy, bool fromCache) { uint32_t device = 0; if (fromCache) { LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]); return mDeviceForStrategy[strategy]; } switch (strategy) { case STRATEGY_DTMF: if (!isInCall()) { // when off call, DTMF strategy follows the same rules as MEDIA strategy device = getDeviceForStrategy(STRATEGY_MEDIA, false); break; } // when in call, DTMF and PHONE strategies follow the same rules // FALL THROUGH case STRATEGY_PHONE: // for phone strategy, we first consider the forced use and then the available devices by order // of priority switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { case AudioSystem::FORCE_BT_SCO: if (!isInCall() || strategy != STRATEGY_DTMF) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO; if (device) break; // if SCO device is requested but no SCO device is available, fall back to default case // FALL THROUGH default: // FORCE_NONE device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; if (device) break; #ifdef WITH_A2DP // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP if (!isInCall()) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; if (device) break; } #endif if (mPhoneState == AudioSystem::MODE_RINGTONE) device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device) break; device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; if (device == 0) { LOGE("getDeviceForStrategy() earpiece device not found"); } break; case AudioSystem::FORCE_SPEAKER: if (!isInCall() || strategy != STRATEGY_DTMF) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } #ifdef WITH_A2DP // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to // A2DP speaker when forcing to speaker output if (!isInCall()) { device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; if (device) break; } #endif device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { LOGE("getDeviceForStrategy() speaker device not found"); } break; } break; case STRATEGY_SONIFICATION: device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; if (device == 0) { LOGE("getDeviceForStrategy() speaker device not found"); } // The second device used for sonification is the same as the device used by media strategy // FALL THROUGH case STRATEGY_ENFORCED_AUDIBLE: // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by // handleIncallSonification(). if (isInCall()) { device = getDeviceForStrategy(STRATEGY_PHONE, false); break; } case STRATEGY_MEDIA: { uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; #ifdef WITH_A2DP if (mA2dpOutput != 0) { if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) { break; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } } #endif if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; } if (device2 == 0) { device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; } // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise device |= device2; // Do not play media stream if in call and the requested device would change the hardware // output routing if (isInCall() && !AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device) && device != getDeviceForStrategy(STRATEGY_PHONE)) { device = 0; LOGV("getDeviceForStrategy() incompatible media and phone devices"); } } break; default: LOGW("getDeviceForStrategy() unknown strategy: %d", strategy); break; } LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return device; }
void AudioPolicyManager::setPhoneState(int state) { LOGD("setPhoneState() state %d", state); uint32_t newDevice = 0; if (state < 0 || state >= AudioSystem::NUM_MODES) { LOGW("setPhoneState() invalid state %d", state); return; } if (state == mPhoneState ) { LOGW("setPhoneState() setting same state %d", state); return; } // if leaving call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isInCall()) { LOGV("setPhoneState() in call state management: new state is %d", state); for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { AudioPolicyManagerBase::handleIncallSonification(stream, false, true); } } // store previous phone state for management of sonification strategy below int oldState = mPhoneState; mPhoneState = state; // force routing command to audio hardware when starting call // even if no device change is needed bool force = (mPhoneState == AudioSystem::MODE_IN_CALL); // are we entering or starting a call if (!isStateInCall(oldState) && isStateInCall(state)) { LOGV(" Entering call in setPhoneState()"); // force routing command to audio hardware when starting a call // even if no device change is needed force = true; } else if (isStateInCall(oldState) && (state == AudioSystem::MODE_NORMAL)) { LOGV(" Exiting call in setPhoneState()"); // force routing command to audio hardware when exiting a call // even if no device change is needed force = true; } else if (isStateInCall(state) && (state != oldState)) { LOGV(" Switching between telephony and VoIP in setPhoneState()"); // force routing command to audio hardware when switching between telephony and VoIP // even if no device change is needed force = true; } // check for device and output changes triggered by new phone state newDevice = AudioPolicyManagerBase::getNewDevice(mHardwareOutput, false); #ifdef WITH_QCOM_LPA if (newDevice == 0 && (mLPADecodeOutput != -1 && mOutputs.valueFor(mLPADecodeOutput)->isUsedByStrategy(STRATEGY_MEDIA))) { newDevice = getDeviceForStrategy(STRATEGY_MEDIA, false); } #endif #ifdef WITH_A2DP AudioPolicyManagerBase::checkOutputForAllStrategies(); // suspend A2DP output if a SCO device is present. if (mA2dpOutput != 0 && mScoDeviceAddress != "") { if (oldState == AudioSystem::MODE_NORMAL) { mpClientInterface->suspendOutput(mA2dpOutput); } else if (state == AudioSystem::MODE_NORMAL) { mpClientInterface->restoreOutput(mA2dpOutput); } } #endif AudioPolicyManagerBase::updateDeviceForStrategy(); AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); // force routing command to audio hardware when ending call // even if no device change is needed if (isStateInCall(oldState) && newDevice == 0) { newDevice = hwOutputDesc->device(); if(state == AudioSystem::MODE_NORMAL) { force = true; } } // when changing from ring tone to in call mode, mute the ringing tone // immediately and delay the route change to avoid sending the ring tone // tail into the earpiece or headset. int delayMs = 0; if (isStateInCall(state) && oldState == AudioSystem::MODE_RINGTONE) { // delay the device change command by twice the output latency to have some margin // and be sure that audio buffers not yet affected by the mute are out when // we actually apply the route change delayMs = hwOutputDesc->mLatency*2; setStreamMute(AudioSystem::RING, true, mHardwareOutput); } // change routing is necessary setOutputDevice(mHardwareOutput, newDevice, force, delayMs); // if entering in call state, handle special case of active streams // pertaining to sonification strategy see handleIncallSonification() if (isStateInCall(state)) { LOGV("setPhoneState() in call state management: new state is %d", state); // unmute the ringing tone after a sufficient delay if it was muted before // setting output device above if (oldState == AudioSystem::MODE_RINGTONE) { setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS); } for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { AudioPolicyManagerBase::handleIncallSonification(stream, true, true); } } // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE if (state == AudioSystem::MODE_RINGTONE && (hwOutputDesc->mRefCount[AudioSystem::MUSIC] || (systemTime() - hwOutputDesc->mStopTime[AudioSystem::MUSIC]) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { // (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) { mLimitRingtoneVolume = true; } else { mLimitRingtoneVolume = false; } }