xref: /frameworks/base/media/java/android/media/AudioManager.java
public void setStreamVolume(int streamType, int index, int flags) {
final IAudioService service = getService();
try {
service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
当我们通过音量控制条调整音量大小的时候,会通过调用AudioManager.setStreamVolume设置音量的大小。AudioManager会通过aidl通信调用AudioService的setStreamVolume方法。
xref: /frameworks/base/services/core/java/com/android/server/audio/AudioService.java
/** @see AudioManager#setStreamVolume(int, int, int) */
public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
+ " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
return;
}
if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
(index == 0) &&
(mContext.checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED)) {
Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
+ " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
return;
}
mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
index/*val1*/, flags/*val2*/, callingPackage));
setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
Binder.getCallingUid());
}
..............................................................................................
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
String caller, int uid) {
if (DEBUG_VOL) {
Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
+ ", calling=" + callingPackage + ")");
}
if (mUseFixedVolume) {
return;
}
ensureValidStreamType(streamType);
int streamTypeAlias = mStreamVolumeAlias[streamType];
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
final int device = getDeviceForStream(streamType);
int oldIndex;
// skip a2dp absolute volume control request when the device
// is not an a2dp device
if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
(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 (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
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 (mSafeMediaVolumeState) {
// reset any pending volume command
mPendingVolumeCommand = null;
oldIndex = streamState.getIndex(device);
index = rescaleIndex(index * 10, streamType, streamTypeAlias);
if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
(device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
(flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
synchronized (mA2dpAvrcpLock) {
if (mA2dp != null && mAvrcpAbsVolSupported) {
mA2dp.setAvrcpAbsoluteVolume(index / 10);
}
}
}
if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
setHearingAidVolume(index, streamType);
}
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
}
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
((device & mFixedVolumeDevices) != 0)) {
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 &&
(device & mSafeMediaVolumeDevices) != 0) {
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);
index = mStreamStates[streamType].getIndex(device);
}
}
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
........................................................................................
private void onSetStreamVolume(int streamType, int index, int flags, int device,
String caller) {
final int stream = mStreamVolumeAlias[streamType];
setStreamVolumeInt(stream, index, device, false, caller);
// setting volume on ui sounds stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(stream == getUiSoundsStreamType())) {
setRingerMode(getNewRingerMode(stream, index, flags),
TAG + ".onSetStreamVolume", false /*external*/);
}
// setting non-zero volume for a muted stream unmutes the stream and vice versa,
// except for BT SCO stream where only explicit mute is allowed to comply to BT requirements
if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) {
mStreamStates[stream].mute(index == 0);
}
}
.........................................................................................
private void setStreamVolumeInt(int streamType,
int index,
int device,
boolean force,
String caller) {
if ((device & mFullVolumeDevices) != 0) {
return;
}
VolumeStreamState streamState = mStreamStates[streamType];
if (streamState.setIndex(index, device, caller) || force) {
// Post message to set system volume (it in turn will post a message
// to persist).
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
}
}
.........................................................................................
private class AudioHandler extends Handler {
..................................................................................
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_DEVICE_VOLUME:
setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
break;
case MSG_SET_ALL_VOLUMES:
setAllVolumes((VolumeStreamState) msg.obj);
break;
.........................................................................................
}
}
}
.........................................................................................
/*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
synchronized (VolumeStreamState.class) {
// Apply volume
streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
// Apply change to all streams using this one as alias
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
if (streamType != streamState.mStreamType &&
mStreamVolumeAlias[streamType] == streamState.mStreamType) {
// Make sure volume is also maxed out on A2DP device for aliased stream
// that may have a different device selected
int streamDevice = getDeviceForStream(streamType);
if ((device != streamDevice) && isAvrcpAbsVolSupported
&& ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
isAvrcpAbsVolSupported);
}
mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
isAvrcpAbsVolSupported);
}
}
}
// Post a persist volume msg
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
PERSIST_DELAY);
}
..................................................................................
private void setStreamVolumeIndex(int index, int device) {
// Only set audio policy BT SCO stream volume to 0 when the stream is actually muted.
// This allows RX path muting by the audio HAL only when explicitly muted but not when
// index is just set to 0 to repect BT requirements
if (mStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0 && !mIsMuted) {
index = 1;
}
AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
}
// must be called while synchronized VolumeStreamState.class
/*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
int index;
if (mIsMuted) {
index = 0;
} else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
} else if ((device & mFullVolumeDevices) != 0) {
index = (mIndexMax + 5)/10;
} else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
index = (mIndexMax + 5)/10;
} else {
index = (getIndex(device) + 5)/10;
}
setStreamVolumeIndex(index, device);
}
通过checkSafeMediaVolume来检查当前是否可设置音量,调节音量大小走else语句onSetStreamVolume方法。
在setDeviceVolume方法里面通过applyDeviceVolume_syncVSS设置应用音量,接着更改所有用此别名的流,确保音量在A2DP设备上也达到最大。在applyDeviceVolume_syncVSS中会判断index是否为0,如果为0则是静音,否则会通过设备类型类设置index。
最终会走到setStreamVolumeIndex方法调用AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device)。
xref: /frameworks/base/media/java/android/media/AudioSystem.java
public static int setStreamVolumeIndexAS(int stream, int index, int device) {
if (DEBUG_VOLUME) {
Log.i(TAG, "setStreamVolumeIndex: " + STREAM_NAMES[stream]
+ " dev=" + Integer.toHexString(device) + " idx=" + index);
}
return setStreamVolumeIndex(stream, index, device);
}
.....................................................................................
private static native int setStreamVolumeIndex(int stream, int index, int device);
setStreamVolumeIndex是一个native方法,对应的是android_media_AudioSystem.cpp里面的setStreamVolumeIndex
xref: /frameworks/base/core/jni/android_media_AudioSystem.cpp
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
jobject thiz,
jint stream,
jint index,
jint device)
{
return (jint) check_AudioSystem_Command(
AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
index,
(audio_devices_t)device));
}
调用AudioSystem的setStreamVolumeIndex方法
xref: /frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index, device);
}
.................................................................................
const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service()
{
sp<IAudioPolicyService> ap;
sp<AudioPolicyServiceClient> apc;
{
Mutex::Autolock _l(gLockAPS);
if (gAudioPolicyService == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.audio_policy"));
if (binder != 0)
break;
ALOGW("AudioPolicyService not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (gAudioPolicyServiceClient == NULL) {
gAudioPolicyServiceClient = new AudioPolicyServiceClient();
}
binder->linkToDeath(gAudioPolicyServiceClient);
gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
LOG_ALWAYS_FATAL_IF(gAudioPolicyService == 0);
apc = gAudioPolicyServiceClient;
// Make sure callbacks can be received by gAudioPolicyServiceClient
ProcessState::self()->startThreadPool();
}
ap = gAudioPolicyService;
}
if (apc != 0) {
int64_t token = IPCThreadState::self()->clearCallingIdentity();
ap->registerClient(apc);
ap->setAudioPortCallbacksEnabled(apc->isAudioPortCbEnabled());
ap->setAudioVolumeGroupCallbacksEnabled(apc->isAudioVolumeGroupCbEnabled());
IPCThreadState::self()->restoreCallingIdentity(token);
}
return ap;
}
get_audio_policy_service通过Binder机制获取到一个Service,这个Service的实现类是AudioPolicyInterfaceImpl.cpp
xref: /frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->setStreamVolumeIndex(stream,
index,
device);
}
调用AudioPolicyManager的setStreamVolumeIndex方法
xref: /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
auto attributes = mEngine->getAttributesForStreamType(stream);
ALOGV("%s: stream %s attributes=%s", __func__,
toString(stream).c_str(), toString(attributes).c_str());
return setVolumeIndexForAttributes(attributes, index, device);
}
............................................................................................
status_t Audi

1万+

被折叠的 条评论
为什么被折叠?



