編輯:關於Android編程
Android底層開發之耳機插拔與音頻通道切換實例
由於使用的是耳機 麥克分離式的耳機,所以要分別上報事件。在Android系統層耳機插孔的檢測是基於/sys/class/switch/h2w/state的值來判斷的(以4.4.4_r2為例子位於WiredAccessoryManager.java)。
只要在內核中實現一個「或真或假」的基於switch類的h2w開關。Android系統就可以監聽到插拔信息。
在播放音樂的時候插入耳機,使用tinymix(參考:Android音頻底層調試-基於tinyalsa)命令可以查找到Playback Path的值從SPK變為HP_NO_MIC,就可以說明耳機插拔軟件檢測正常了。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PHN0cm9uZz4jIHRpbnltaXggPC9zdHJvbmc+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvcD4KPHA+TWl4ZXIgbmFtZTog"RK_RK616_TINY'
Number of controls: 7
ctl type num name value
0 ENUM 1 Playback Path HP_NO_MIC
1 ENUM 1 Capture MIC Path MIC OFF
2 ENUM 1 Voice Call Path OFF
3 ENUM 1 Voip Path OFF
4 INT 2 Speaker Playback Volume 24 24
5 INT 2 Headphone Playback Volume 24 24
6 ENUM 1 Modem Input Enable ON
#
但是喇叭還在響,說明沒有被關閉。查查原理圖「功放上的控制腳」是在哪個GPIO上接著呢。
根據手冊得出只要GPIO2_D7可以輸出低電平就能實現喇叭的關閉,使用萬用表測得在插入耳機後該管腳仍然為高電平,查看代碼修改記錄在上一個版本同事是直接在rk_headset.c耳機插拔程序中修改將其拉低的,這樣可以實現但是覺得不妥,Android上層應該也是有音頻通道切換的,根據上層來控制比較好。這樣插入耳機的時候也可以強制開啟喇叭,把「使用哪個音頻通信的決定權」交給給用戶。
這個應該是在內核中實現的,因為Alsa已經正常切換了,就說明上層已經調用相應的接口了。從驅動中來分析。
設備資源:可以看到Speak和handphone的使能GPIO都給的是RK30_PIN2_PD7。
static struct rk616_platform_data rk616_pdata = {
.power_init = rk616_power_on_init,
.power_deinit = rk616_power_deinit,
.scl_rate = RK616_SCL_RATE,
.lcd0_func = INPUT, //port lcd0 as input
.lcd1_func = INPUT, //port lcd1 as input
.lvds_ch_nr = 1, //the number of used lvds channel
.hdmi_irq = RK30_PIN2_PD6,
.spk_ctl_gpio = RK30_PIN2_PD7,
.hp_ctl_gpio = RK30_PIN2_PD7,
};
設備驅動中控制音頻輸出通道的函數:
static int rk616_playback_path_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
......
case HP_PATH:
case HP_NO_MIC:
case RING_HP:
case RING_HP_NO_MIC:
rk616_set_gpio(RK616_CODEC_SET_SPK, GPIO_LOW);
if (pre_path == OFF)
rk616_codec_power_up(RK616_CODEC_PLAYBACK);
snd_soc_update_bits(codec, RK616_SPKL_CTL,
RK616_VOL_MASK, HPOUT_VOLUME); //, volume (bit 0-4)
snd_soc_update_bits(codec, RK616_SPKR_CTL,
RK616_VOL_MASK, HPOUT_VOLUME);
rk616_set_gpio(RK616_CODEC_SET_HP, GPIO_HIGH);
break;
......
}
可見在輸出到耳機通道時,禁用 SPEAKER和使能HP都是設置的GPIO_HIGH,最後RK30_PIN2_PD7仍然為高電平,沒有禁用SPEAKER。原理圖並沒有單獨的耳機的使能管腳。在資源中將hp_ctl_gpio設置為INVALID_GPIO,問題得以解決。
額外收獲:原理耳機那裡一直都是有音頻輸出的,無論插入不插入耳機;插入耳機時僅僅是將SPEAKER禁止了。
誤入的歧途:
1.誤以為要去看Android上層代碼在各種類中追尋了很久,真是浪費時間,如果使用tinymix查看音頻通道切換正常,說明內核以上的都沒有問題了,出問題也是出在了內核以及硬件上。
總結:龐大的Android系統容不得你每一塊都了解的很細致,但是如果會很好的劃分層次,問題就會很好解決。記錄的重點不在於具體的型號版本等等比較虛的方面,而是在遇到此類問題分析的思路。
Matrix的數學原理在Android中,如果你用Matrix進行過圖像處理,那麼一定知道Matrix這個類。Android中的Matrix是一個3 x 3的矩陣,其內容
2.1.5 android_media_MediaScanner.cpp對於android_media_MediaScanner.cpp來說,主要分析三個函數native
1.采用PUSCH跳頻時需要注意的問題在上行子幀中,PUCCH信道處於帶寬的高低兩側,或者說位於頻帶的邊緣,PUSCH信道則位於帶寬的中間。PUCCH信道也以RB對為基本
Android基礎入門教程——8.2.2 Bitmap引起的OOM問題標簽(空格分隔): Android基礎入門教程本節引言: 上節,我們已經學習