天天看點

【Android系統源碼修改】如何修改frameworks實作音量統一調節

文章目錄

源碼為MTK的MT8735平台源碼,android 5

###1 修改音量最大值和預設音量

源碼位置:frameworks/base/media/java/android/media/AudioService.java 約266行

MAX_STREAM_VOLUME為最大值,DEFAULT_STREAM_VOLUME為預設值

為了統一調節音量,把預設音量和最大音量,所有STREAM都保持一緻。

如果采用Master音量調節,就不需要設定了,因為Master音量調節最大都是100

/** @hide Maximum volume index values for audio streams */
   /// M: Modify the max stream volume @{
    private static final int[] MAX_STREAM_VOLUME = new int[] {
        20,  // STREAM_VOICE_CALL
        20,  // STREAM_SYSTEM
        20,  // STREAM_RING
        20,  // STREAM_MUSIC
        20,  // STREAM_ALARM
        20,  // STREAM_NOTIFICATION
        20,  // STREAM_BLUETOOTH_SCO
        20,  // STREAM_SYSTEM_ENFORCED
        20,  // STREAM_DTMF
        20,  // STREAM_TTS
    };
    /// @}

    /**
     * @hide Default volume index values for audio streams
     * M: modify the default stream volume @{
     */
    public static int[] DEFAULT_STREAM_VOLUME = new int[] {
        9,  // STREAM_VOICE_CALL
        9,  // STREAM_SYSTEM
        9,  // STREAM_RING
        9,  // STREAM_MUSIC
        9,  // STREAM_ALARM
        9,  // STREAM_NOTIFICATION
        9,  // STREAM_BLUETOOTH_SCO
        9,  // STREAM_SYSTEM_ENFORCED
        9,  // STREAM_DTMF
        9,  // STREAM_TTS
    };
    /** @ */
           

###2 攔截音量鍵分發

源碼位置:frameworks/base/policy/src/com/android/internel/policy/impl/PhoneWindowManager.java 約2607行

方法名:public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)

作用:在分發之前攔截按鍵事件。是否分發給應用自己處理,根據傳回值:return -1 不傳回,自己處理了。return 0 傳回給應用自己處理

攔截音量鍵

音量鍵碼:KeyEvent.KEYCODE_VOLUME_DOWN KeyEvent.KEYCODE_VOLUME_UP

if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
     // TODO: 這裡添加你需要音量鍵按下後做什麼事
     return -1;
}
           

我們需要音量鍵按下後,發出按下廣播。(來電鈴聲響起時,音量鍵起到靜音作用,是以來電話的時候不攔截音量鍵,讓系統處理)

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
    TelecomManager telecomManager = getTelecommService();
    if (telecomManager == null || !(telecomManager.isRinging() || telecomManager.isInCall())) {
        if (down) {
            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                intent.setAction("xxx.ACTION_VOLUME_DOWN");
                mContext.sendBroadcast(intent);
            } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
                intent.setAction("xxx.ACTION_VOLUME_UP");
                mContext.sendBroadcast(intent);
            }
            return -1;
        }
    }            
}

           

###3 在其他應用中添加廣播接收者處理音量加減廣播

public class VolumeEventReceiver extends BroadcastReceiver {
    Context mContext;
    AudioManager manager;
    int[] stream = {
            AudioManager.STREAM_RING,
            AudioManager.STREAM_ALARM,
            AudioManager.STREAM_NOTIFICATION,
            AudioManager.STREAM_DTMF,
            AudioManager.STREAM_VOICE_CALL,
            AudioManager.STREAM_SYSTEM,
            AudioManager.STREAM_MUSIC,
    };

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            mContext = context;
            manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

            String action = intent.getAction();
            if ("xxx.ACTION_VOLUME_DOWN".equals(action)) {
                controlVolume(AudioManager.ADJUST_LOWER);

            } else if ("xxx.ACTION_VOLUME_UP".equals(action)) {
                controlVolume(AudioManager.ADJUST_RAISE);
            }

        } catch (Exception e) {
            Log.i("VolumeEvent", "*** Exception: " + e.getMessage());
        }
    }

    void controlVolume(int direction) {
        for (int i = 0; i < stream.length - 1; i++) {
            manager.adjustStreamVolume(stream[i], direction, 0);
        }
        // 顯示媒體音量調節的圖示,其他音量圖示不顯示
        manager.adjustStreamVolume(AudioManager.STREAM_MUSIC, direction,
                AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
    }

}
           

注冊廣播:

<receiver android:name=".VolumeEventReceiver" 
        android:exported="false">
      <intent-filter>
          <action android:name="xxx.ACTION_VOLUME_DOWN" />
          <action android:name="xxx.ACTION_VOLUME_UP" />
      </intent-filter>
  </receiver>

           

###4 打開主音量調節功能,設定音量加減步長

源碼位置:frameworks/base/core/res/res/values/config.xml 約71行

将config_useMasterVolume設定為true。

<!-- Flag indicating that the media framework should allow changing
    master volume stream and nothing else . -->
<bool name="config_useMasterVolume">true</bool>
           

約86行,第二個item根據調試設定步長。預設是5, 這裡改成1。根據測試,調節音量時,從最小到最大,需要按+鍵16下左右

<integer-array name="config_masterVolumeRamp">
   <item>0</item>  <item>1</item>  <!-- default: always increase volume by 5% -->
</integer-array>
           

當使用者調用adjustStreamVolume的時候,mUseMasterVolume是上面config_useMasterVolume的值。

public void adjustStreamVolume(int streamType, int direction, int flags) {
    IAudioService service = getService();
    Log.d(TAG, "adjustStreamVolume: StreamType = " + streamType + ", direction = " + direction);
    try {
        if (mUseMasterVolume) {
            service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
        } else {
            service.adjustStreamVolume(streamType, direction, flags,
                    mContext.getOpPackageName());
        }
    } catch (RemoteException e) {
        Log.e(TAG, "Dead object in adjustStreamVolume", e);
    }
}
           

由Master調節音量,所有音量最大為100,發出音量調節廣播為:

"android.media.MASTER_VOLUME_CHANGED_ACTION"

而普通的音量調節,最大音量根據AudioService.java中MAX_STREAM_VOLUME定義的,預設音量DEFAULT_STREAM_VOLUME

廣播為:"android.media.VOLUME_CHANGED_ACTION"

###5 測試

寫一個測試程式測試

【Android系統源碼修改】如何修改frameworks實作音量統一調節
【Android系統源碼修改】如何修改frameworks實作音量統一調節
【Android系統源碼修改】如何修改frameworks實作音量統一調節
【Android系統源碼修改】如何修改frameworks實作音量統一調節