系統(tǒng)設(shè)置界面中就是使用AudioManager.setStreamVolume(),
源碼:
/** * Sets the volume index for a particular stream. * <p>This method has no effect if the device implements a fixed volume policy * as indicated by {@link #isVolumeFixed()}. * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless * the app has been granted Do Not Disturb access. * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. * @param streamType The stream whose volume index should be set. * @param index The volume index to set. See * {@link #getStreamMaxVolume(int)} for the largest valid value. * @param flags One or more flags. * @see #getStreamMaxVolume(int) * @see #getStreamVolume(int) * @see #isVolumeFixed() */ public void setStreamVolume(int streamType, int index, int flags) { IAudioService service = getService(); try { service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }只是簡(jiǎn)單的調(diào)用了AudioService的setStreamVolume()方法,下面是AudioService#setStreamVolume()源碼:PRivate void setStreamVolume(int streamType, int index, int flags, String callingPackage, String caller, int uid) { if (mUseFixedVolume) { return; } ensureValidStreamType(streamType);//下面兩句是進(jìn)行流類型轉(zhuǎn)換,后面會(huì)詳細(xì)介紹。mStreamVolumeAlias保存了源類型//和目標(biāo)類型的映射關(guān)系。mStreamStates是保存了各種流的對(duì)應(yīng)的VolumeStreamState//VolumeStreamState保存與一個(gè)流類型所有音量相關(guān)的信息,每種流分配了一個(gè)VolumeStreamState對(duì)象 int streamTypeAlias = mStreamVolumeAlias[streamType]; VolumeStreamState streamState = mStreamStates[streamTypeAlias];//獲取當(dāng)前流使用哪一個(gè)音頻設(shè)備進(jìn)行播放,最終會(huì)被調(diào)用到AudioPolicyService中 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; //獲取當(dāng)前流的音量 oldIndex = streamState.getIndex(device);//由于流類型轉(zhuǎn)換需要轉(zhuǎn)換設(shè)置的音量值 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) {//和藍(lán)牙耳機(jī)協(xié)議有關(guān) if (mA2dp != null && mAvrcpAbsVolSupported) { mA2dp.setAvrcpAbsoluteVolume(index / 10); } } } 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 = mSafeMediaVolumeIndex; } 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);//獲取設(shè)置的結(jié)果 index = mStreamStates[streamType].getIndex(device); } }//廣播通知 sendVolumeUpdate(streamType, oldIndex, index, flags); }當(dāng)VolumeStreamState#muteCount() != 0則是靜音。應(yīng)該是調(diào)用VolumeStreamState#setIndext()設(shè)置音量值的,但是API24的AudioService的setStreamVolume()代碼中找不到這句。
int streamTypeAlias = mStreamVolumeAlias[streamType];
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
以上兩句涉及到滿足所謂的“將鈴聲音量作為通知音量”這種需求,如,實(shí)現(xiàn)“以鈴聲音量用作音樂(lè)音量”代碼如下:
mStreamVolumeAlias[AudioSystem.STREAM_MUSIC] = AudioSystem.STREAM_RING;
這樣,當(dāng)傳入AudioSystem.STREAM_MUSIC參數(shù)時(shí),實(shí)際操作的回事AudioSystem.STREAM_RING這個(gè)流對(duì)應(yīng)的VolumeStreamState。
|
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注