Android FrameWork音頻管理AudioManager的一點解析(續一)

來源:互聯網
上載者:User

標籤:framework   音量大小   系統音量條顯示   源碼解析   

           上篇裡面提到了聲音調整的兩種操作,接下來就要具體分析下音量大小的大概步驟,分別涉及到兩部分:

           android\frameworks\base\media\java\android\media\AudioService.java

           android\frameworks\base\media\java\android\media\IAudioService.aidl

           其中adjustStreamVolume(int streamType, int direction, int flags)函數的聲明是在AudioService.aidl中,而函數的實現是在AudioService.java中。

          下面具體可以看源碼:

           

    /** @see AudioManager#adjustStreamVolume(int, int, int) */    public void adjustStreamVolume(int streamType, int direction, int flags) {        if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction);        ensureValidDirection(direction);        ensureValidStreamType(streamType);        // use stream type alias here so that streams with same alias have the same behavior,        // including with regard to silent mode control (e.g the use of STREAM_RING below and in        // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)        int streamTypeAlias = mStreamVolumeAlias[streamType];        VolumeStreamState streamState = mStreamStates[streamTypeAlias];        final int device = getDeviceForStream(streamTypeAlias);        // get last audible index if stream is muted, current index otherwise        final int aliasIndex = streamState.getIndex(device,                                                  (streamState.muteCount() != 0) /* lastAudible */);        boolean adjustVolume = true;        // convert one UI step (+/-1) into a number of internal units on the stream alias        int step = rescaleIndex(10, streamType, streamTypeAlias);        // If either the client forces allowing ringer modes for this adjustment,        // or the stream type is one that is affected by ringer modes        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||                (streamTypeAlias == getMasterStreamType())) {            int ringerMode = getRingerMode();            // do not vibrate if already in vibrate mode            if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {                flags &= ~AudioManager.FLAG_VIBRATE;            }            // Check if the ringer mode changes with this volume adjustment. If            // it does, it will handle adjusting the volume, so we won't below            adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);            if ((streamTypeAlias == getMasterStreamType()) &&                    (mRingerMode == AudioManager.RINGER_MODE_SILENT)) {                streamState.setLastAudibleIndex(0, device);            }        }        // If stream is muted, adjust last audible index only        int index;        final int oldIndex = mStreamStates[streamType].getIndex(device,                (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);        if (streamState.muteCount() != 0) {            if (adjustVolume) {                // Post a persist volume msg                // no need to persist volume on all streams sharing the same alias                streamState.adjustLastAudibleIndex(direction * step, device);                sendMsg(mAudioHandler,                        MSG_PERSIST_VOLUME,                        SENDMSG_QUEUE,                       PERSIST_LAST_AUDIBLE,                        device,                        streamState,                        PERSIST_DELAY);            }            index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);        } else {            if (adjustVolume && streamState.adjustIndex(direction * step, device)) {                // Post message to set system volume (it in turn will post a message                // to persist). Do not change volume if stream is muted.                sendMsg(mAudioHandler,                        MSG_SET_DEVICE_VOLUME,                        SENDMSG_QUEUE,                       device,                        0,                        streamState,                        0);            }            index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);        }        sendVolumeUpdate(streamType, oldIndex, index, flags);    }
        解析上面函數可知,函數最開始會有一個對於前兩個參數有效性的檢測,貼出具體的檢測代碼:

        

    private void ensureValidDirection(int direction) {        if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) {            throw new IllegalArgumentException("Bad direction " + direction);        }    }    private void ensureValidSteps(int steps) {        if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {            throw new IllegalArgumentException("Bad volume adjust steps " + steps);        }    }    private void ensureValidStreamType(int streamType) {        if (streamType < 0 || streamType >= mStreamStates.length) {            throw new IllegalArgumentException("Bad stream type " + streamType);        }    }
       繼續跟進源碼,可以看到

        int step = rescaleIndex(10, streamType, streamTypeAlias);

        此參數為調整步進數值的

        再下面的判斷條件if (streamState.muteCount() != 0)為判斷是否是從靜音狀態發起的音量調整以便進行不同的操作。

        在函數的最後

        sendVolumeUpdate(streamType, oldIndex, index, flags);

        此函數則是用於更新系統音量條的顯示

        

    // UI update and Broadcast Intent    private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {        if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) {            streamType = AudioSystem.STREAM_NOTIFICATION;        }        mVolumePanel.postVolumeChanged(streamType, flags);        oldIndex = (oldIndex + 5) / 10;        index = (index + 5) / 10;        Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION);        if (streamType == AudioManager.STREAM_VOICE_CALL)        streamType = AudioManager.STREAM_MUSIC;        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);        intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);        intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);        mContext.sendBroadcast(intent);    }
        可以看到源碼中調用了

        \android\frameworks\base\core\java\android\view\VolumePanel.java

       其中VolumePanel.java則用於顯示系統音量條的顯示,其中具體如何顯示可以參考代碼。同時此部分代碼中會涉及到系統所有音量相關的表徵圖顯示,需要進行修改美化等操作的可以具體找到資源檔進行修改。

      具體路徑可以在

      android\frameworks\base\core\res\res

     另一種設定音量的方法setStreamVolume(int streamType, int index, int flags)也是同樣的可以在上述代碼中找到,關於音量調整的部分解析到此基本結束,暫時可以明白的就上述的流程了。

Android FrameWork音頻管理AudioManager的一點解析(續一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.