zoukankan      html  css  js  c++  java
  • Android 8 声音调整过程

    记录Android 8声音调整过程。

    frameworksaseservicescorejavacomandroidserverpolicyPhoneWindowManager.java
        private void dispatchDirectAudioEvent(KeyEvent event) {
            if (event.getAction() != KeyEvent.ACTION_DOWN) {
                return;
            }
            int keyCode = event.getKeyCode();
            int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND
                    | AudioManager.FLAG_FROM_KEY;
            String pkgName = mContext.getOpPackageName();
            switch (keyCode) {
                case KeyEvent.KEYCODE_VOLUME_UP:
                    try {
                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
                    } catch (Exception e) {
                        Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
                    }
                    break;
                case KeyEvent.KEYCODE_VOLUME_DOWN:
                    try {
                        getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
                                AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
                    } catch (Exception e) {
                        Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
                    }
                    break;
                case KeyEvent.KEYCODE_VOLUME_MUTE:
                    try {
                        if (event.getRepeatCount() == 0) {
                            getAudioService().adjustSuggestedStreamVolume(
                                    AudioManager.ADJUST_TOGGLE_MUTE,
                                    AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
                    }
                    break;
            }
        }
    
    frameworksaseservicescorejavacomandroidserveraudioAudioService.java
    	   /** @see AudioManager#adjustVolume(int, int) */
        public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
                String callingPackage, String caller) {
            adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
                    caller, Binder.getCallingUid());
        }
    
        private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
                String callingPackage, String caller, int uid) {
            mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
                    direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
                            .append("/").append(caller).append(" uid:").append(uid).toString()));
            final int streamType;
            synchronized (mForceControlStreamLock) {
                if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
                        + ", flags=" + flags + ", caller=" + caller
                        + ", volControlStream=" + mVolumeControlStream
                        + ", userSelect=" + mUserSelectedVolumeControlStream);
                if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
                    streamType = mVolumeControlStream;
                } else {
                    // 获取当前StreamType类型,传入的是AudioManager.USE_DEFAULT_STREAM_TYPE
                    // AudioSystem.STREAM_MUSIC
                    final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
                    final boolean activeForReal;
                    if (maybeActiveStreamType == AudioSystem.STREAM_MUSIC) {
                        // 判断AudioFlinger当前是否是用AudioSystem.STREAM_MUSIC
                        activeForReal = isAfMusicActiveRecently(0);
                    } else {
                        activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
                    }
                    // 获取声音类型, 就是前面getActiveStreamType得到的AudioSystem.STREAM_MUSIC
                    if (activeForReal || mVolumeControlStream == -1) {
                        streamType = maybeActiveStreamType;
                    } else {
                        streamType = mVolumeControlStream;
                    }
                }
            }
            // 判断是否是MUTE操作
            final boolean isMute = isMuteAdjust(direction);
            // 判断类型是否合法
            ensureValidStreamType(streamType);
            final int resolvedStream = mStreamVolumeAlias[streamType];
            // RING类型声音处理
            // Play sounds on STREAM_RING only.
            if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
                    resolvedStream != AudioSystem.STREAM_RING) {
                flags &= ~AudioManager.FLAG_PLAY_SOUND;
            }
            // 通知或者电话,显示UI,但是不进行MUTE操作
            // For notifications/ring, show the ui before making any adjustments
            // Don't suppress mute/unmute requests
            if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
                direction = 0;
                // 将相应的位清零
                flags &= ~AudioManager.FLAG_PLAY_SOUND;
                flags &= ~AudioManager.FLAG_VIBRATE;
                if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
            }
    
            adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
        }
    
        /** @see AudioManager#adjustStreamVolume(int, int, int) */
        public void adjustStreamVolume(int streamType, int direction, int flags,
                String callingPackage) {
            if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
                Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
                        + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
                return;
            }
            mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
                    direction/*val1*/, flags/*val2*/, callingPackage));
            adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
                    Binder.getCallingUid());
        }
    
        private void adjustStreamVolume(int streamType, int direction, int flags,
                String callingPackage, String caller, int uid) {
            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);
            // 判断声音是否受MUTE影响
            if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
                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];
            // 获取声音对应的device
            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 not an a2dp device
            if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
                (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
                return;
            }
            // 获取UID
            // 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;
            }
    
            // reset any pending volume command
            synchronized (mSafeMediaVolumeState) {
                mPendingVolumeCommand = null;
            }
    
            flags &= ~AudioManager.FLAG_FIXED_VOLUME;
            if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                   ((device & mFixedVolumeDevices) != 0)) {
                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 &&
                        (device & mSafeMediaVolumeDevices) != 0) {
                    step = safeMediaVolumeIndex(device);
                } else {
                    step = streamState.getMaxIndex();
                }
                if (aliasIndex != 0) {
                    aliasIndex = step;
                }
            } else {
                // 更改UI上的显示,增加/减少一格
                // convert one UI step (+/-1) into a number of internal units on the stream alias
                step = rescaleIndex(10, streamType, streamTypeAlias);
            }
            // 对与RINGER_MODES有关的声音组处理
            // 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 == getUiSoundsStreamType())) {
                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 ringermode is suppressing media, prevent changes
            if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
                adjustVolume = false;
            }
            int oldIndex = mStreamStates[streamType].getIndex(device);
    
            if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
                mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
                // 判断是否要更新蓝牙的音量
                // Check if volume update should be send to AVRCP
                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.adjustAvrcpAbsoluteVolume(direction);
                        }
                    }
                }
    
                if (isMuteAdjust) {
                    boolean state;
                    if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
                        state = !streamState.mIsMuted;
                    } else {
                        state = direction == AudioManager.ADJUST_MUTE;
                    }
                    if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                        setSystemAudioMute(state);
                    }
                    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)
                        || streamState.mIsMuted) {
                    // Post message to set system volume (it in turn will post a
                    // message to persist).
                    if (streamState.mIsMuted) {
                        // 静音的情况下先unmute设备
                        // 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);
                }
    
                // Check if volume update should be sent to Hdmi system audio.
                int newIndex = mStreamStates[streamType].getIndex(device);
                if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
                    setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
                }
                if (mHdmiManager != null) {
                    synchronized (mHdmiManager) {
                        // mHdmiCecSink true => mHdmiPlaybackClient != null
                        if (mHdmiCecSink &&
                                streamTypeAlias == AudioSystem.STREAM_MUSIC &&
                                oldIndex != newIndex) {
                            synchronized (mHdmiPlaybackClient) {
                                int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
                                        KeyEvent.KEYCODE_VOLUME_UP;
                                final long ident = Binder.clearCallingIdentity();
                                try {
                                    mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
                                    mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
                                } finally {
                                    Binder.restoreCallingIdentity(ident);
                                }
                            }
                        }
                    }
                }
            }
            int index = mStreamStates[streamType].getIndex(device);
            sendVolumeUpdate(streamType, oldIndex, index, flags);		//更新UI显示 
        }
    	
    frameworksaseservicescorejavacomandroidserveraudioAudioService.java
    	 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;
    
                    case MSG_PERSIST_VOLUME:
                        persistVolume((VolumeStreamState) msg.obj, msg.arg1);
                        break;
    
                    case MSG_PERSIST_RINGER_MODE:
                        // note that the value persisted is the current ringer mode, not the
                        // value of ringer mode as of the time the request was made to persist
                        persistRingerMode(getRingerModeInternal());
                        break;
    					
           private void setDeviceVolume(VolumeStreamState streamState, int device) {
    
                synchronized (VolumeStreamState.class) {
                    // Apply volume
                    streamState.applyDeviceVolume_syncVSS(device);				// 将声音的数据写到底层
    
                    // 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) && mAvrcpAbsVolSupported &&
                                    ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
                                mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
                            }
                            mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
                        }
                    }
                }
                // Post a persist volume msg
                sendMsg(mAudioHandler,
                        MSG_PERSIST_VOLUME,
                        SENDMSG_QUEUE,
                        device,
                        0,
                        streamState,
                        PERSIST_DELAY);
    
            }
    		
    		  private void persistVolume(VolumeStreamState streamState, int device) {
                if (mUseFixedVolume) {
                    return;
                }
                if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
                    return;
                }
                if (streamState.hasValidSettingsName()) {
                    // 将参数保存
                    System.putIntForUser(mContentResolver,
                            streamState.getSettingNameForDevice(device),
                            (streamState.getIndex(device) + 5)/ 10,
                            UserHandle.USER_CURRENT);
                }
            }
    
  • 相关阅读:
    Mac环境下svn的使用
    ionic动态切换主题皮肤
    NodeJS中的require和import
    ionic3.x开发小坑记录(一)
    ios微信浏览器中video视频播放问题
    微信内置浏览器在使用video标签时(安卓)默认全屏的原因及解决办法
    转《发布ionic应用到App Store的完整步骤 》
    Tomcat内存问题解决办法
    linux系统的文件保护
    linux系统一些信息(待整理)
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/9553788.html
Copyright © 2011-2022 走看看