audio 通话中切换扬声器流程详解

从UI 开始讲解:

说起通话,就避免不了谈起InCallActivity.java, 这是通话中的UI 主界面,通过解析其布局文件

Incall_screen.xml

    <fragment android:name="com.android.incallui.CallCardFragment"
        android:id="@+id/callCardFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

使用自定义fragment     CallCardFragment, fragment ui 创建接口onCreateView

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.call_card_content, container, false);
    }

分析call_card_content.xml

    <fragment android:name="com.android.incallui.CallButtonFragment"
            android:layout_alignParentBottom="true"
            android:id="@+id/callButtonFragment"
             android:layout_width="match_parent"
            android:layout_height="wrap_content" /> 

再次使用自定义fragment    CallButtonFragment

其布局文件

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View parent = inflater.inflate(R.layout.call_button_fragment, container, false);
call_button_fragment.xml

        <com.android.incallui.LeuiCallButton
            android:id="@+id/audioButton"
            style="@style/InCallCompoundButton"
            android:layout_marginLeft="@dimen/call_button_margin_side"
            android:layout_marginRight="@dimen/call_button_margin_center"
            leui:ButtonSelecter="@drawable/leui_ic_call_audio"
            leui:ButtonText="@string/audio"
            leui:contentDescription="@string/onscreenAudioText" />

ok,  到这了就能看到通话ui中的音频切换的button,切换流程将从这里的onclick事件开始分析:回头CallButtonFragment

    public void onClick(View view) {
        int id = view.getId();
        int mode = AudioState.ROUTE_WIRED_OR_EARPIECE;
        Log.d(this, "onClick(View " + view + ", id " + id + ")...");

        switch(id) {
            case R.id.audioButton:
                onAudioButtonClicked();

}

    private void onAudioButtonClicked() {
        if (isSupported(AudioState.ROUTE_BLUETOOTH)) {
            showAudioModePopup();
        } else {
            getPresenter().toggleSpeakerphone();
        }
    }

CallButtonPresenter.java

    public void toggleSpeakerphone() {
        setAudioMode(newMode);
    }

    public void setAudioMode(int mode) {
        TelecomAdapter.getInstance().setAudioRoute(mode);
    }
Phone.java

    public final void setAudioRoute(int route) {
        mInCallAdapter.setAudioRoute(route);
    }

InCallAdapter.java

    public void setAudioRoute(int route) {
        mHandler.obtainMessage(MSG_SET_AUDIO_ROUTE, route, 0).sendToTarget();
    }

    private final class InCallAdapterHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
           case MSG_SET_AUDIO_ROUTE:
                    mCallsManager.setAudioRoute(msg.arg1);
                    break;

}

CallsManager.java

    void setAudioRoute(int route) {
        mCallAudioManager.setAudioRoute(route);
    }

ok, 经过系列转换,终于见到曙光了。

CallAudioManager.java

void setAudioRoute(int route) {

setSystemAudioState(mAudioState.isMuted(), newRoute,
                    mAudioState.getSupportedRouteMask());

}

    private void turnOnSpeaker(boolean on) {
        // Wired headset and earpiece work the same way
        if (mAudioManager.isSpeakerphoneOn() != on) {
            Log.i(this, "turning speaker phone %s", on);
            mAudioManager.setSpeakerphoneOn(on);
        }
    }

终于调用到AudioManager.  这才是系统提供的api。

audiomanager 通过binder 机制调用Audioservice。省去中间简单传递过程,直接从audioservice分析

        private void setForceUse(int usage, int config) {
            AudioSystem.setForceUse(usage, config);
        }

通过audiosystem 以jni 机制调用native方法。 android_media_AudioSystem.cpp

static jint
android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
{
    return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
                                                           static_cast <audio_policy_forced_cfg_t>(config)));
}

AudioSystem.cpp

status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->setForceUse(usage, config);
}

IAudioPolicyService.cpp

    virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
        data.writeInt32(static_cast <uint32_t>(usage));
        data.writeInt32(static_cast <uint32_t>(config));
        remote()->transact(SET_FORCE_USE, data, &reply);
        return static_cast <status_t> (reply.readInt32());
    }

AudioPolicyInterfaceImpl.cpp

status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
                                         audio_policy_forced_cfg_t config)
{
 
    Mutex::Autolock _l(mLock);
    mAudioPolicyManager->setForceUse(usage, config);
    return NO_ERROR;
}
AudioPolicyManager.cpp
void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
                                         audio_policy_forced_cfg_t config)
{

applyStreamVolumes(output, newDevice, 0, true);

}

void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
                                                audio_devices_t device,
                                                int delayMs,
                                                bool force)
{

        checkAndSetVolume((audio_stream_type_t)stream,
                          mStreams[stream].getVolumeIndex(device),
                          output,
                          device,
                          delayMs,
                          force);
    }
}


status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
                                                   int index,
                                                   audio_io_handle_t output,
                                                   audio_devices_t device,
                                                   int delayMs,
                                                   bool force)
{

}

后续基本流程

AudioPolicyClientImpl.cpp

AudioPolicyService.cpp

AudioFlinger.cpp

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值