ARC1.2-ARC设备音量控制--安卓系统AudioService音量控制接口代码

代码路径:base/services/core/java/com/android/server/audio/AudioService.java

1、基本参数
1-1、streamType(音频流类型)

![[音频流.png]]

/frameworks/base/media/java/android/media/AudioSystem.java/
public static final int STREAM_VOICE_ CALL = 0; /通话声音/
public static final int STREAM SYSTEM = 1; /* 系统声音*/
public static final int STREAM RING = 2; /电话铃声和短信提示/
public static final int STREAM MUSIC = 3; /音乐播放/
Public static final int STREAM ALARM = 4; /闹铃/
public static final int STREAM_NOTIFICATION = 5; /* 通知声音*/

/下面几个是隐藏类型,不对上层应用开放/
public static final int STREAM BLUETOOTH SCO = 6; /蓝牙通话/
public static final int STREAM SYSTEM ENEORCED = 7; /* 强制的系统声音。比如有的国家强制要求摄像头拍照时有声音,以防止偷拍*/
public static final int STREAM_DTMF = 8; /* DTMF声音*/
public static final int STREAM TTS = 9; /* 即text to speech (TTS)

1-2、index(音量值)
_/** Maximum volume index values for audio streams */_
 protected static int[] MAX_STREAM_VOLUME = new int[] {
     5,  // STREAM_VOICE_CALL
     7,  // STREAM_SYSTEM
     7,  // STREAM_RING            // configured by config_audio_ring_vol_steps
     com.skg.services.manager.SkgVoiceManager.VOLUME_VALUE_MAX, 
     // STREAM_MUSIC
     7,  // STREAM_ALARM
     7,  // STREAM_NOTIFICATION    // configured by config_audio_notif_vol_steps
     15, // STREAM_BLUETOOTH_SCO
     7,  // STREAM_SYSTEM_ENFORCED
     15, // STREAM_DTMF
     15, // STREAM_TTS
     15, // STREAM_ACCESSIBILITY
     15  // STREAM_ASSISTANT
 };

 _/** Minimum volume index values for audio streams */_
 protected static int[] MIN_STREAM_VOLUME = new int[] {
     1,  // STREAM_VOICE_CALL
     0,  // STREAM_SYSTEM
     0,  // STREAM_RING
     0,  // STREAM_MUSIC
     1,  // STREAM_ALARM
     0,  // STREAM_NOTIFICATION
     0,  // STREAM_BLUETOOTH_SCO
     0,  // STREAM_SYSTEM_ENFORCED
     0,  // STREAM_DTMF
     0,  // STREAM_TTS
     1,  // STREAM_ACCESSIBILITY
     0   // STREAM_ASSISTANT
 };
1-3、device(声音输入输出设备)
// input devices
public static final int DEVICE_IN_COMMUNICATION = DEVICE_BIT_IN | 0x1;

public static final int DEVICE_IN_AMBIENT = DEVICE_BIT_IN | 0x2;

public static final int DEVICE_IN_BUILTIN_MIC = DEVICE_BIT_IN | 0x4;

public static final int DEVICE_IN_BLUETOOTH_SCO_HEADSET = DEVICE_BIT_IN | 0x8;

public static final int DEVICE_IN_WIRED_HEADSET = DEVICE_BIT_IN | 0x10;

public static final int DEVICE_IN_AUX_DIGITAL = DEVICE_BIT_IN | 0x20;

public static final int DEVICE_IN_HDMI = DEVICE_IN_AUX_DIGITAL;

public static final int DEVICE_IN_HDMI_1 = DEVICE_BIT_IN | 0x21;
public static final int DEVICE_IN_VOICE_CALL = DEVICE_BIT_IN | 0x40;
//output device
// audio device definitions: must be kept in sync with values in system/core/audio.h
public static final int DEVICE_NONE = 0x0;

public static final int DEVICE_OUT_SPEAKER = 0x2;

public static final int DEVICE_OUT_WIRED_HEADSET = 0x4;

public static final int DEVICE_OUT_WIRED_HEADPHONE = 0x8;

public static final int DEVICE_OUT_BLUETOOTH_SCO = 0x10;

public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20;

public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40;

public static final int DEVICE_OUT_BLUETOOTH_A2DP = 0x80;

public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100;

public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200;

public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;

public static final int DEVICE_OUT_HDMI = DEVICE_OUT_AUX_DIGITAL;

public static final int DEVICE_OUT_HDMI_1 = 0x401;

public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;

public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;

public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;

public static final int DEVICE_OUT_USB_DEVICE = 0x4000;

public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000;

public static final int DEVICE_OUT_TELEPHONY_TX = 0x10000;

public static final int DEVICE_OUT_LINE = 0x20000;

public static final int DEVICE_OUT_HDMI_ARC = 0x40000;

public static final int DEVICE_OUT_HDMI_EARC = 0x40001;

public static final int DEVICE_OUT_SPDIF = 0x80000;

public static final int DEVICE_OUT_SPDIF_1 = 0x80001;
1-4、flags(是否显示音量条UI)
FLAG_SHOW_UI
1-5、direction(声音调节方向)
public static final int ADJUST_RAISE = 1;

public static final int ADJUST_LOWER = -1;

public static final int ADJUST_SAME = 0;

public static final int ADJUST_MUTE = -100;

public static final int ADJUST_UNMUTE = 100;

public static final int ADJUST_TOGGLE_MUTE = 101;
1-6、mStreamVolumeAlias[]

设置的是同一组stream音量,分组在Android源码中称之为"别名",即alias。比如在电话中,5种stream(STREAM_SYSTEM、STREAM_RING、STREAM_NOTIFICATION、STREAM_SYSTEM_ENFORCED、STREAM_DTMF)的alias都是STREAM_RING,那么对应的滑动条即可控制这5种stream的音量
白板对应的是STREAM_VOLUME_ALIAS_DEFAULT

private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {  
    AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL  
    AudioSystem.STREAM_RING,            // STREAM_SYSTEM  
    AudioSystem.STREAM_RING,            // STREAM_RING  
    AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC  
    AudioSystem.STREAM_ALARM,           // STREAM_ALARM  
    AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION  
    AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO  
    AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED  
    AudioSystem.STREAM_RING,            // STREAM_DTMF  
    AudioSystem.STREAM_MUSIC,           // STREAM_TTS  
    AudioSystem.STREAM_MUSIC,           // STREAM_ACCESSIBILITY  
    AudioSystem.STREAM_MUSIC            // STREAM_ASSISTANT  
};  
private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {  
    AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL  
    AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM  
    AudioSystem.STREAM_MUSIC,       // STREAM_RING  
    AudioSystem.STREAM_MUSIC,       // STREAM_MUSIC  
    AudioSystem.STREAM_MUSIC,       // STREAM_ALARM  
    AudioSystem.STREAM_MUSIC,       // STREAM_NOTIFICATION  
    AudioSystem.STREAM_BLUETOOTH_SCO,       // STREAM_BLUETOOTH_SCO  
    AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED  
    AudioSystem.STREAM_MUSIC,       // STREAM_DTMF  
    AudioSystem.STREAM_MUSIC,       // STREAM_TTS  
    AudioSystem.STREAM_MUSIC,       // STREAM_ACCESSIBILITY  
    AudioSystem.STREAM_MUSIC        // STREAM_ASSISTANT  
};  
private final int[] STREAM_VOLUME_ALIAS_NONE = new int[] {  
    AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL  
    AudioSystem.STREAM_SYSTEM,          // STREAM_SYSTEM  
    AudioSystem.STREAM_RING,            // STREAM_RING  
    AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC  
    AudioSystem.STREAM_ALARM,           // STREAM_ALARM  
    AudioSystem.STREAM_NOTIFICATION,    // STREAM_NOTIFICATION  
    AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO  
    AudioSystem.STREAM_SYSTEM_ENFORCED, // STREAM_SYSTEM_ENFORCED  
    AudioSystem.STREAM_DTMF,            // STREAM_DTMF  
    AudioSystem.STREAM_TTS,             // STREAM_TTS  
    AudioSystem.STREAM_ACCESSIBILITY,   // STREAM_ACCESSIBILITY  
    AudioSystem.STREAM_ASSISTANT        // STREAM_ASSISTANT  
};  
private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {  
    AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL  
    AudioSystem.STREAM_RING,            // STREAM_SYSTEM  
    AudioSystem.STREAM_RING,            // STREAM_RING  
    AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC  
    AudioSystem.STREAM_ALARM,           // STREAM_ALARM  
    AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION  
    AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO  
    AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED  
    AudioSystem.STREAM_RING,            // STREAM_DTMF  
    AudioSystem.STREAM_MUSIC,           // STREAM_TTS  
    AudioSystem.STREAM_MUSIC,           // STREAM_ACCESSIBILITY  
    AudioSystem.STREAM_MUSIC            // STREAM_ASSISTANT  
};
2、adjustStreamVolume(已当前音量为基础逐级调节)

```java
protected void adjustStreamVolume(int streamType, int direction, int flags,  
        String callingPackage, String caller, int uid, int pid, String attributionTag,  
        boolean hasModifyAudioSettings, int keyEventMode) {  
    if (mUseFixedVolume) {  
        return;  
    }  
    if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction  
            + ", flags=" + flags + ", caller=" + caller);  
  
    ensureValidDirection(direction);  
    ensureValidStreamType(streamType);  
  
    boolean isMuteAdjust = isMuteAdjust(direction);  
  
    if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {  
        return;  
    }  
  
    // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure  
    // that the calling app have the MODIFY_PHONE_STATE permission.    
    if (isMuteAdjust &&  
        (streamType == AudioSystem.STREAM_VOICE_CALL ||  
            streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&  
            mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)  
                != PackageManager.PERMISSION_GRANTED) {  
        Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="  
                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());  
        return;    
    }  
  
    // If the stream is STREAM_ASSISTANT,  
    // make sure that the calling app have the MODIFY_AUDIO_ROUTING permission.    
    if (streamType == AudioSystem.STREAM_ASSISTANT &&  
            mContext.checkPermission(  
            android.Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid)  
                != PackageManager.PERMISSION_GRANTED) {  
        Log.w(TAG, "MODIFY_AUDIO_ROUTING Permission Denial: adjustStreamVolume from pid="  
                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());  
        return;    
    }  
  
    // 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);  
  
    int aliasIndex = streamState.getIndex(device);  
    boolean adjustVolume = true;  
    int step;  
  
    // skip a2dp absolute volume control request when the device  
    // is neither an a2dp device nor BLE device    
    if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)  
            && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))  
            && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {  
        return;  
    }  
  
    // If we are being called by the system (e.g. hardware keys) check for current user  
    // so we handle user restrictions correctly.    
    if (uid == android.os.Process.SYSTEM_UID) {  
        uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));  
    }  
    // validate calling package and app op  
    if (!checkNoteAppOp(  
            STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage, attributionTag)) {  
        return;  
    }  
  
    // reset any pending volume command  
    synchronized (mSafeMediaVolumeStateLock) {  
        mPendingVolumeCommand = null;  
    }  
  
    flags &= ~AudioManager.FLAG_FIXED_VOLUME;  
    if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {  
        flags |= AudioManager.FLAG_FIXED_VOLUME;  
  
        // Always toggle between max safe volume and 0 for fixed volume devices where safe  
        // volume is enforced, and max and 0 for the others.        
        // This is simulated by stepping by the full allowed volume range        
        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&  
                mSafeMediaVolumeDevices.contains(device)) {  
            step = safeMediaVolumeIndex(device);  
        } else {  
            step = streamState.getMaxIndex();  
        }  
        if (aliasIndex != 0) {  
            aliasIndex = step;  
        }  
    } else {  
        // convert one UI step (+/-1) into a number of internal units on the stream alias  
        step = rescaleStep(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) ||  
            (isUiSoundsStreamType(streamTypeAlias))) {  
        int ringerMode = getRingerModeInternal();  
        // do not vibrate if already in vibrate mode  
        if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {  
            flags &= ~AudioManager.FLAG_VIBRATE;  
        }  
        // Check if the ringer mode handles this adjustment. If it does we don't  
        // need to adjust the volume further.        
        final int result = checkForRingerModeChange(aliasIndex, direction, step,  
                streamState.mIsMuted, callingPackage, flags);  
        adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;  
        // If suppressing a volume adjustment in silent mode, display the UI hint  
        if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {  
            flags |= AudioManager.FLAG_SHOW_SILENT_HINT;  
        }  
        // If suppressing a volume down adjustment in vibrate mode, display the UI hint  
        if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {  
            flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;  
        }  
    }  
  
    // If the ringer mode or zen is muting the stream, do not change stream unless  
    // it'll cause us to exit dnd    if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {  
        adjustVolume = false;  
    }  
    int oldIndex = mStreamStates[streamType].getIndex(device);  
    Log.d(TAG,"zfp#device = " + device);  
    // Check if the volume adjustment should be handled by an absolute volume controller instead  
    if (isAbsoluteVolumeDevice(device)  
            && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {  
        if (device == AudioSystem.DEVICE_OUT_HDMI_ARC || device == AudioSystem.DEVICE_OUT_HDMI_EARC){  
            Log.d(TAG,"zfp#device is arc device = ");  
        }else {  
            AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);  
            if (info.mHandlesVolumeAdjustment) {  
                dispatchAbsoluteVolumeAdjusted(streamType, info, oldIndex, direction,  
                        keyEventMode);  
                return;            }  
        }  
    }  
    Log.d(TAG,"zfp#adjustVolume = " + adjustVolume);  
    if (adjustVolume && (direction != AudioManager.ADJUST_SAME)  
            && (keyEventMode != AudioDeviceVolumeManager.ADJUST_MODE_END)) {  
        mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);  
        if (isMuteAdjust) {  
            boolean state;  
            if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {  
                state = !streamState.mIsMuted;  
            } else {  
                state = direction == AudioManager.ADJUST_MUTE;  
            }  
            for (int stream = 0; stream < mStreamStates.length; stream++) {  
                if (streamTypeAlias == mStreamVolumeAlias[stream]) {  
                    if (!(readCameraSoundForced()  
                                && (mStreamStates[stream].getStreamType()  
                                    == AudioSystem.STREAM_SYSTEM_ENFORCED))) {  
                        mStreamStates[stream].mute(state);  
                    }  
                }  
            }  
        } else if ((direction == AudioManager.ADJUST_RAISE) &&  
                !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {  
            Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);  
            mVolumeController.postDisplaySafeVolumeWarning(flags);  
        } else if ((streamState.adjustIndex(direction * step, device, caller,  
                        hasModifyAudioSettings)  
                        || streamState.mIsMuted)) {  
            // Post message to set system volume (it in turn will post a  
            // message to persist).            if (streamState.mIsMuted) {  
                // Unmute the stream if it was previously muted  
                if (direction == AudioManager.ADJUST_RAISE) {  
                    // unmute immediately for volume up  
                    streamState.mute(false);  
                } else if (direction == AudioManager.ADJUST_LOWER) {  
                    if (mIsSingleVolume) {  
                        sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,  
                                streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);  
                    }  
                }  
            }  
            sendMsg(mAudioHandler,  
                    MSG_SET_DEVICE_VOLUME,  
                    SENDMSG_QUEUE,  
                    device,  
                    0,  
                    streamState,  
                    0);  
        }  
  
        int newIndex = mStreamStates[streamType].getIndex(device);  
  
        // Check if volume update should be send to AVRCP  
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC  
                && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)  
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {  
            if (DEBUG_VOL) {  
                Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="  
                        + newIndex + "stream=" + streamType);  
            }  
            mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);  
        } else if (isAbsoluteVolumeDevice(device)  
                && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {  
            AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);  
            dispatchAbsoluteVolumeChanged(streamType, info, newIndex);  
        }  
  
        if (AudioSystem.isLeAudioDeviceType(device)  
                && streamType == getBluetoothContextualVolumeStream()  
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {  
            if (DEBUG_VOL) {  
                Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="  
                        + newIndex + " stream=" + streamType);  
            }  
            mDeviceBroker.postSetLeAudioVolumeIndex(newIndex,  
                mStreamStates[streamType].getMaxIndex(), streamType);  
        }  
  
        // Check if volume update should be send to Hearing Aid  
        if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {  
            // only modify the hearing aid attenuation when the stream to modify matches  
            // the one expected by the hearing aid            
            if (streamType == getBluetoothContextualVolumeStream()) {  
                if (DEBUG_VOL) {  
                    Log.d(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index="  
                            + newIndex + " stream=" + streamType);  
                }  
                mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);  
            }  
        }  
    }  
  
    final int newIndex = mStreamStates[streamType].getIndex(device);  
    if (adjustVolume) {  
        synchronized (mHdmiClientLock) {  
            if (mHdmiManager != null) {  
                // At most one of mHdmiPlaybackClient and mHdmiTvClient should be non-null  
                HdmiClient fullVolumeHdmiClient = mHdmiPlaybackClient;  
                if (mHdmiTvClient != null) {  
                    fullVolumeHdmiClient = mHdmiTvClient;  
                }  
                if (fullVolumeHdmiClient != null  
                        && mHdmiCecVolumeControlEnabled  
                        && streamTypeAlias == AudioSystem.STREAM_MUSIC  
                        // vol change on a full volume device  
                        && isFullVolumeDevice(device)) {  
                    int keyCode = KeyEvent.KEYCODE_UNKNOWN;  
                    switch (direction) {  
                        case AudioManager.ADJUST_RAISE:  
                            keyCode = KeyEvent.KEYCODE_VOLUME_UP;  
                            break;                        
                        case AudioManager.ADJUST_LOWER:  
                            keyCode = KeyEvent.KEYCODE_VOLUME_DOWN;  
                            break;                        
                        case AudioManager.ADJUST_TOGGLE_MUTE:  
                        case AudioManager.ADJUST_MUTE:  
                        case AudioManager.ADJUST_UNMUTE:  
                            // Many CEC devices only support toggle mute. Therefore, we send the  
                            // same keycode for all three mute options.                            
                            keyCode = KeyEvent.KEYCODE_VOLUME_MUTE;  
                            break;                        
                        default:  
                            break;  
                    }  
                    Log.d(TAG,"zfp#keyCode = " + keyCode);  
                    if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {  
                        final long ident = Binder.clearCallingIdentity();  
                        try {  
                            switch (keyEventMode) {  
                                case AudioDeviceVolumeManager.ADJUST_MODE_NORMAL:  
                                    fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);  
                                    fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);  
                                    break;                                
                                case AudioDeviceVolumeManager.ADJUST_MODE_START:  
                                    fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);  
                                    break;                                
                                case AudioDeviceVolumeManager.ADJUST_MODE_END:  
                                    fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);  
                                    break;                               
                                default:  
                                    Log.e(TAG, "Invalid keyEventMode " + keyEventMode);  
                            }  
                        } finally {  
                            Binder.restoreCallingIdentity(ident);  
                        }  
                    }  
                }  
  
                if (streamTypeAlias == AudioSystem.STREAM_MUSIC  
                        && (oldIndex != newIndex || isMuteAdjust)) {  
                    maybeSendSystemAudioStatusCommand(isMuteAdjust);  
                }  
            }  
        }  
    }  
    sendVolumeUpdate(streamType, oldIndex, newIndex, flags, device);  
}
#### 3、setStreamVolume(设置音量为指定的值)

private void setStreamVolume(int streamType, int index, int flags,  
        @Nullable AudioDeviceAttributes ada,  
        String callingPackage, String caller, String attributionTag, int uid,  
        boolean hasModifyAudioSettings) {  
    if (DEBUG_VOL) {  
        Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index  
                + ", dev=" + ada  
                + ", calling=" + callingPackage + ")");  
    }  
    if (mUseFixedVolume) {  
        return;  
    }  
  
    ensureValidStreamType(streamType);  
    int streamTypeAlias = mStreamVolumeAlias[streamType];  
    VolumeStreamState streamState = mStreamStates[streamTypeAlias];  
  
    final int device = (ada == null)  
            ? getDeviceForStream(streamType)  
            : ada.getInternalType();  
    int oldIndex;  
  
    // skip a2dp absolute volume control request when the device  
    // is neither an a2dp device nor BLE device    
    if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)  
            && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))  
            && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {  
        return;  
    }  
    // If we are being called by the system (e.g. hardware keys) check for current user  
    // so we handle user restrictions correctly.    
    if (uid == android.os.Process.SYSTEM_UID) {  
        uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));  
    }  
    if (!checkNoteAppOp(  
            STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage, attributionTag)) {  
        return;  
    }  
  
    if (isAndroidNPlus(callingPackage)  
            && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))  
            && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {  
        throw new SecurityException("Not allowed to change Do Not Disturb state");  
    }  
  
    if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {  
        return;  
    }  
  
    synchronized (mSafeMediaVolumeStateLock) {  
        // reset any pending volume command  
        mPendingVolumeCommand = null;  
  
        oldIndex = streamState.getIndex(device);  
  
        index = rescaleIndex(index * 10, streamType, streamTypeAlias);  
  
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC  
                && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)  
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {  
            if (DEBUG_VOL) {  
                Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index  
                        + "stream=" + streamType);  
            }  
            mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);  
        } else if (isAbsoluteVolumeDevice(device)  
                && ((flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0)) {  
            AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);  
  
            dispatchAbsoluteVolumeChanged(streamType, info, index);  
        }  
  
        if (AudioSystem.isLeAudioDeviceType(device)  
                && streamType == getBluetoothContextualVolumeStream()  
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {  
            if (DEBUG_VOL) {  
                Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="  
                        + index + " stream=" + streamType);  
            }  
            mDeviceBroker.postSetLeAudioVolumeIndex(index,  
                mStreamStates[streamType].getMaxIndex(), streamType);  
        }  
  
        if (device == AudioSystem.DEVICE_OUT_HEARING_AID  
                && streamType == getBluetoothContextualVolumeStream()) {  
            Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index  
                    + " stream=" + streamType);  
            mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);  
        }  
  
        flags &= ~AudioManager.FLAG_FIXED_VOLUME;  
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {  
            flags |= AudioManager.FLAG_FIXED_VOLUME;  
  
            // volume is either 0 or max allowed for fixed volume devices  
            if (index != 0) {  
                if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&  
                        mSafeMediaVolumeDevices.contains(device)) {  
                    index = safeMediaVolumeIndex(device);  
                } else {  
                    index = streamState.getMaxIndex();  
                }  
            }  
        }  
  
        if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {  
            mVolumeController.postDisplaySafeVolumeWarning(flags);  
            mPendingVolumeCommand = new StreamVolumeCommand(  
                                                streamType, index, flags, device);  
        } else {  
            onSetStreamVolume(streamType, index, flags, device, caller, hasModifyAudioSettings);  
            index = mStreamStates[streamType].getIndex(device);  
        }  
    }  
    synchronized (mHdmiClientLock) {  
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC  
                && (oldIndex != index)) {  
            maybeSendSystemAudioStatusCommand(false);  
        }  
    }  
    sendVolumeUpdate(streamType, oldIndex, index, flags, device);  
}
4、isStreamMute(获取当前流静音状态)

```java

```java
public boolean isStreamMute(int streamType) {  
    if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {  
        streamType = getActiveStreamType(streamType);  
    }  
    synchronized (VolumeStreamState.class) {  
        ensureValidStreamType(streamType);  
        return mStreamStates[streamType].mIsMuted;  
    }  
}

5、getStreamVolume(获取当前流音量值)
public int getStreamVolume(int streamType) {  
    ensureValidStreamType(streamType);  
    int device = getDeviceForStream(streamType);  
    synchronized (VolumeStreamState.class) {  
        int index = mStreamStates[streamType].getIndex(device);  
  
        // by convention getStreamVolume() returns 0 when a stream is muted.  
        if (mStreamStates[streamType].mIsMuted) {  
            index = 0;  
        }  
        if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&  
                isFixedVolumeDevice(device)) {  
            index = mStreamStates[streamType].getMaxIndex();  
        }  
        return (index + 5) / 10;  
    }  
}



#### 6、各接口的具体流程请参考AudioService.xmind
![[AudioService.xmind]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值