在android\frameworks\base\media\java\android\media\AudioManager.java中

 /**     * @hide     */    public void handleKeyDown(KeyEvent event, int stream) {        int keyCode = event.getKeyCode();    Log.d("zmq","AudioManager handleKeyDown keyCode = "+keyCode);        switch (keyCode) {            case KeyEvent.KEYCODE_VOLUME_UP:            case KeyEvent.KEYCODE_VOLUME_DOWN:                /*                 * Adjust the volume in on key down since it is more                 * responsive to the user.   在按键按下去的时候处理,给用户响应更快。                 */                int flags = FLAG_SHOW_UI | FLAG_VIBRATE;         //1|16得到的值为17Log.d("zmq","AudioManager handleKeyDown flags = "+flags);Log.d("zmq","AudioManager handleKeyDown mUseMasterVolume = "+mUseMasterVolume);                if (mUseMasterVolume) {            //使用主音量,在config中定义,为true                    adjustMasterVolume(                            keyCode == KeyEvent.KEYCODE_VOLUME_UP                                    ? ADJUST_RAISE                                    : ADJUST_LOWER,                            flags);                } else {                    adjustSuggestedStreamVolume(                            keyCode == KeyEvent.KEYCODE_VOLUME_UP                                    ? ADJUST_RAISE                                    : ADJUST_LOWER,                            stream,                            flags);                }                break;            case KeyEvent.KEYCODE_VOLUME_MUTE:                if (event.getRepeatCount() == 0) {                    if (mUseMasterVolume) {                        setMasterMute(!isMasterMute());                    } else {                        // TODO: Actually handle MUTE.                    }                }                break;        }    }    /**     * Show a toast containing the current volume.     *     * @see #adjustStreamVolume(int, int, int)     * @see #adjustVolume(int, int)     * @see #setStreamVolume(int, int, int)     * @see #setRingerMode(int)     */    public static final int FLAG_SHOW_UI = 1 << 0;      //其值为1     /**     * Whether to vibrate if going into the vibrate ringer mode.     */    public static final int FLAG_VIBRATE = 1 << 4;     //其值为16    private final boolean mUseMasterVolume;    //在AudioManager的构造函数中进行初始化    /**     * @hide     */    public AudioManager(Context context) {        mContext = context;        mUseMasterVolume = mContext.getResources().getBoolean(                com.android.internal.R.bool.config_useMasterVolume);          //在config.xml中定义初始值        mUseVolumeKeySounds = mContext.getResources().getBoolean(                com.android.internal.R.bool.config_useVolumeKeySounds);    }
变量config_useMasterVolume在android\device\mstar\mango\overlay\frameworks\base\core\res\res\values\config.xml中定义

    true/**     * Adjusts the master volume for the device's audio amplifier.     * @param steps The number of volume steps to adjust. A positive     *            value will raise the volume.     * @param flags One or more flags.     * @hide     */    public void adjustMasterVolume(int steps, int flags) {        Log.d("zmq","AudioManager adjustMasterVolume ");            IAudioService service = getService();        try {            service.adjustMasterVolume(steps, flags, mContext.getOpPackageName());        } catch (RemoteException e) {            Log.e(TAG, "Dead object in adjustMasterVolume", e);        }    }
调用到android\frameworks\base\media\java\android\media\AudioService.java中,真正有实现功能的地方

/** @see AudioManager#adjustMasterVolume(int, int) */    public void adjustMasterVolume(int steps, int flags, String callingPackage) {        Log.d("zmq","AudioService adjustMasterVolume");        if (mUseFixedVolume) {            return;        }        ensureValidSteps(steps);          //确保steps的绝对值不超过4Log.d("zmq","AudioService adjustMasterVolume AudioSystem.getMasterVolume() = "                +AudioSystem.getMasterVolume());        int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);   //需要*100,从AudioSystem中得到的是0.0~1.0Log.d("zmq","AudioService adjustMasterVolume volume1 = "+volume);        int delta = 0;                       //需要增加的音量坡度        int numSteps = Math.abs(steps);Log.d("zmq","AudioService adjustMasterVolume numSteps = "+numSteps);        int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;Log.d("zmq", "AudioService adjustMasterVolume direction = "+direction);        for (int i = 0; i < numSteps; ++i) {            delta = findVolumeDelta(direction, volume);Log.d("zmq","AudioService adjustMasterVolume delta = "+delta);            volume += delta;Log.d("zmq", "AudioService adjustMasterVolume volume2 = "+volume);        }        //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);        setMasterVolume(volume, flags, callingPackage);    } private final boolean mUseFixedVolume; mUseFixedVolume = mContext.getResources().getBoolean(                com.android.internal.R.bool.config_useFixedVolume);
变量在config_useFixedVolume在android\frameworks\base\core\res\res\values\config.xml中

     false    private void ensureValidSteps(int steps) {        if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {            throw new IllegalArgumentException("Bad volume adjust steps " + steps);        }    }// Maximum volume adjust steps allowed in a single batch call.    private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
调用到android\frameworks\base\media\java\android\media\AudioSystem.java中,会调用本地层,先不做追踪。
public static native float getMasterVolume();
// Internally master volume is a float in the 0.0 - 1.0 range,    // but to support integer based AudioManager API we translate it to 0 - 100    private static final int MAX_MASTER_VOLUME = 100;private int findVolumeDelta(int direction, int volume) {Log.d("zmq"," AudioService findVolumeDelta");        int delta = 0;        if (direction == AudioManager.ADJUST_RAISE) {            if (volume == MAX_MASTER_VOLUME) {                return 0;            }            // This is the default value if we make it to the end            delta = mMasterVolumeRamp[1];    //为1    Log.d("zmq", "AudioService findVolumeDelta delta = "+delta);            // If we're raising the volume move down the ramp array until we            // find the volume we're above and use that groups delta.            for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {    // 没有执行    Log.d("zmq","AudioService findVolumeDelta for ");                if (volume >= mMasterVolumeRamp[i - 1]) {                    delta = mMasterVolumeRamp[i];                    break;                }            }        } else if (direction == AudioManager.ADJUST_LOWER){            if (volume == 0) {                return 0;            }            int length = mMasterVolumeRamp.length;    Log.d("zmq","AudioService findVolumeDelta length = "+length);            // This is the default value if we make it to the end            delta = -mMasterVolumeRamp[length - 1];Log.d("zmq","AudioService findVolumeDelta delta = "+delta);            // If we're lowering the volume move up the ramp array until we            // find the volume we're below and use the group below it's delta            for (int i = 2; i < length; i += 2) {     //没有执行Log.d("zmq","AudioService findVolumeDelta for ");                if (volume <= mMasterVolumeRamp[i]) {                    delta = -mMasterVolumeRamp[i - 1];                    break;                }            }        }        return delta;    }private final int[] mMasterVolumeRamp; mMasterVolumeRamp = context.getResources().getIntArray(                com.android.internal.R.array.config_masterVolumeRamp);
变量config_masterVolumeRamp在android\frameworks\base\core\res\res\values\config.xml中

            0  5      
一般可以在android\device\mstar\mango\overlay\frameworks\base\core\res\res\values\config.xml中覆盖
        0  1      
public void setMasterVolume(int volume, int flags, String callingPackage) {Log.d("zmq","AudioService setMasterVolume");        if (mUseFixedVolume) {            return;        }        if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),                callingPackage) != AppOpsManager.MODE_ALLOWED) {            return;        }        if (volume < 0) {            volume = 0;        } else if (volume > MAX_MASTER_VOLUME) {            volume = MAX_MASTER_VOLUME;        }        doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);    }
doSetMasterVolume经过了原厂的修改

private void doSetMasterVolume(float volume, int flags) {        boolean bSetA2dpVolume = false;        if ((isPipOn() == false) && isBluetoothA2dpOn()) {            bSetA2dpVolume = true;        } else {            bSetA2dpVolume = false;        } if (isMasterMute() ) {            if(bSetA2dpVolume){                AudioSystem.setA2dpMute(false);            } else {            //disappear mute                AudioSystem.setMasterMute(false);                // Post a persist master volume msg                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, false ? 1                    : 0, 0, null, PERSIST_DELAY);            }            sendMasterMuteUpdate(false, flags);        }        int oldVolume = getMasterVolume();AudioSystem.setMasterVolume(volume);        int newVolume = getMasterVolume();        if (newVolume != oldVolume) {            // Post a persist master volume msg            if(bSetA2dpVolume){                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,                    Math.round(volume * (float)1000.0), 1, null, PERSIST_DELAY);            } else {                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,                    Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);            }        }// Send the volume update regardless whether there was a change.        sendMasterVolumeUpdate(flags, oldVolume, newVolume);         }

最终调用AudioSystem.java中的setMasterVolume。 下面为显示音量UI部分
// UI update and Broadcast Intent    private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {        mVolumePanel.postMasterVolumeChanged(flags);        Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);        intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);        intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);        sendBroadcastToAll(intent);    }

在android\frameworks\base\core\java\android\view\VolumePanel.java中

public void postMasterVolumeChanged(int flags) {        postVolumeChanged(STREAM_MASTER, flags);    } public void postVolumeChanged(int streamType, int flags) {        if (hasMessages(MSG_VOLUME_CHANGED)) return;        synchronized (this) {            if (mStreamControls == null) {                createSliders();            }        }        removeMessages(MSG_FREE_RESOURCES);        obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();    } private void createSliders() {        LayoutInflater inflater = (LayoutInflater) mContext                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);        mStreamControls = new HashMap(STREAMS.length);        Resources res = mContext.getResources();        for (int i = 0; i < STREAMS.length; i++) {     //STREAMS.length=8            StreamResources streamRes = STREAMS[i];            int streamType = streamRes.streamType;            if (mVoiceCapable && streamRes == StreamResources.NotificationStream) {                streamRes = StreamResources.RingerStream;            }            StreamControl sc = new StreamControl();            sc.streamType = streamType;            sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);            sc.group.setTag(sc);            sc.icon = (ImageView) sc.group.findViewById(R.id.stream_icon);            sc.icon.setTag(sc);            sc.icon.setContentDescription(res.getString(streamRes.descRes));            sc.iconRes = streamRes.iconRes;            sc.iconMuteRes = streamRes.iconMuteRes;            sc.icon.setImageResource(sc.iconRes);            sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);            int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||                    streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;            sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);sc.seekbarView.setProgress(getStreamVolume(sc.streamType));            sc.seekbarView.setOnSeekBarChangeListener(this);            sc.seekbarView.setTag(sc);                       sc.seekBarValue = (TextView) sc.group.findViewById(R.id.seekbarvalue);sc.seekBarValue.setText(String.valueOf(getStreamVolume(sc.streamType)));                        mStreamControls.put(streamType, sc);        }    } public void handleMessage(Message msg) {        switch (msg.what) {            case MSG_VOLUME_CHANGED: {                onVolumeChanged(msg.arg1, msg.arg2);                break;            }            case MSG_MUTE_CHANGED: {                onMuteChanged(msg.arg1, msg.arg2);                break;            }            case MSG_FREE_RESOURCES: {                onFreeResources();                break;            }            case MSG_STOP_SOUNDS: {                onStopSounds();                break;            }            case MSG_PLAY_SOUND: {                onPlaySound(msg.arg1, msg.arg2);                break;            }            case MSG_VIBRATE: {                onVibrate();                break;            }            case MSG_TIMEOUT: {                if (mDialog.isShowing()) {                    // MStar Android Patch Begin                    // Don't dismiss mute panel.                    if ((mActiveStreamType != -1) && (!isMuted(mActiveStreamType))) {                        mDialog.dismiss();                        mActiveStreamType = -1;                    }                    // MStar Android Patch End                }                synchronized (sConfirmSafeVolumeLock) {                    if (sConfirmSafeVolumeDialog != null) {                        sConfirmSafeVolumeDialog.dismiss();                    }                }                break;            }            case MSG_RINGER_MODE_CHANGED: {                if (mDialog.isShowing()) {                    updateStates();                }                break;            }            case MSG_REMOTE_VOLUME_CHANGED: {                onRemoteVolumeChanged(msg.arg1, msg.arg2);                break;            }            case MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN:                onRemoteVolumeUpdateIfShown();                break;            case MSG_SLIDER_VISIBILITY_CHANGED:                onSliderVisibilityChanged(msg.arg1, msg.arg2);                break;            case MSG_DISPLAY_SAFE_VOLUME_WARNING:                onDisplaySafeVolumeWarning(msg.arg1);                break;        }    }/**     * Override this if you have other work to do when the volume changes (for     * example, vibrating, playing a sound, etc.). Make sure to call through to     * the superclass implementation.     */    protected void onVolumeChanged(int streamType, int flags) {        if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");        if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {            synchronized (this) {                if (mActiveStreamType != streamType) {                    reorderSliders(streamType);                }                onShowVolumeChanged(streamType, flags);            }        }        if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) {            removeMessages(MSG_PLAY_SOUND);            sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY);        }        if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) {            removeMessages(MSG_PLAY_SOUND);            removeMessages(MSG_VIBRATE);            onStopSounds();        }        removeMessages(MSG_FREE_RESOURCES);        sendMessageDelayed(obtainMessage(MSG_FREE_RESOURCES), FREE_DELAY);        resetTimeout();    } private void reorderSliders(int activeStreamType) {        mSliderGroup.removeAllViews();        StreamControl active = mStreamControls.get(activeStreamType);        if (active == null) {            Log.e("VolumePanel", "Missing stream type! - " + activeStreamType);            mActiveStreamType = -1;        } else {            mSliderGroup.addView(active.group);            mActiveStreamType = activeStreamType;            active.group.setVisibility(View.VISIBLE);            updateSlider(active);        }        addOtherVolumes();    }/** Update the mute and progress state of a slider */    private void updateSlider(StreamControl sc) {        sc.seekbarView.setProgress(getStreamVolume(sc.streamType));        final boolean muted = isMuted(sc.streamType);        // Force reloading the image resource        sc.icon.setImageDrawable(null);        sc.icon.setImageResource(muted ? sc.iconMuteRes : sc.iconRes);        if (((sc.streamType == AudioManager.STREAM_RING) ||                (sc.streamType == AudioManager.STREAM_NOTIFICATION)) &&                mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {            sc.icon.setImageResource(R.drawable.ic_audio_ring_notif_vibrate);        }        if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {            // never disable touch interactions for remote playback, the muting is not tied to            // the state of the phone.            sc.seekbarView.setEnabled(true);        } else if ((sc.streamType != mAudioManager.getMasterStreamType() && muted) ||                        (sConfirmSafeVolumeDialog != null)) {            sc.seekbarView.setEnabled(false);        } else {            sc.seekbarView.setEnabled(true);        }    }private void addOtherVolumes() {        if (!mShowCombinedVolumes) return;        for (int i = 0; i < STREAMS.length; i++) {            // Skip the phone specific ones and the active one            final int streamType = STREAMS[i].streamType;            if (!STREAMS[i].show || streamType == mActiveStreamType) {                continue;            }            StreamControl sc = mStreamControls.get(streamType);            mSliderGroup.addView(sc.group);            updateSlider(sc);        }    } protected void onShowVolumeChanged(int streamType, int flags) {        int index = getStreamVolume(streamType);        mRingIsSilent = false;        if (LOGD) {            Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType                    + ", flags: " + flags + "), index: " + index);        }        // get max volume for progress bar        int max = getStreamMaxVolume(streamType);        switch (streamType) {            case AudioManager.STREAM_RING: {//                setRingerIcon();                Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(                        mContext, RingtoneManager.TYPE_RINGTONE);                if (ringuri == null) {                    mRingIsSilent = true;                }                break;            }            case AudioManager.STREAM_MUSIC: {                // Special case for when Bluetooth is active for music                if ((mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC) &                        (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |                        AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |                        AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {                    setMusicIcon(R.drawable.ic_audio_bt, R.drawable.ic_audio_bt_mute);                } else {                    setMusicIcon(R.drawable.ic_audio_vol, R.drawable.ic_audio_vol_mute);                }                break;            }            case AudioManager.STREAM_VOICE_CALL: {                /*                 * For in-call voice call volume, there is no inaudible volume.                 * Rescale the UI control so the progress bar doesn't go all                 * the way to zero and don't show the mute icon.                 */                index++;                max++;                break;            }            case AudioManager.STREAM_ALARM: {                break;            }            case AudioManager.STREAM_NOTIFICATION: {                Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(                        mContext, RingtoneManager.TYPE_NOTIFICATION);                if (ringuri == null) {                    mRingIsSilent = true;                }                break;            }            case AudioManager.STREAM_BLUETOOTH_SCO: {                /*                 * For in-call voice call volume, there is no inaudible volume.                 * Rescale the UI control so the progress bar doesn't go all                 * the way to zero and don't show the mute icon.                 */                index++;                max++;                break;            }            case AudioService.STREAM_REMOTE_MUSIC: {                if (LOGD) { Log.d(TAG, "showing remote volume "+index+" over "+ max); }                break;            }        }        StreamControl sc = mStreamControls.get(streamType);        if (sc != null) {            if (sc.seekbarView.getMax() != max) {                sc.seekbarView.setMax(max);            }            sc.seekbarView.setProgress(index);            if (((flags & AudioManager.FLAG_FIXED_VOLUME) != 0) ||                    (streamType != mAudioManager.getMasterStreamType() &&                     streamType != AudioService.STREAM_REMOTE_MUSIC &&                     isMuted(streamType)) ||                     sConfirmSafeVolumeDialog != null) {                sc.seekbarView.setEnabled(false);            } else {                sc.seekbarView.setEnabled(true);            }        }        if (!mDialog.isShowing()) {            int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType;            // when the stream is for remote playback, use -1 to reset the stream type evaluation            mAudioManager.forceVolumeControlStream(stream);            mDialog.setContentView(mView);            // Showing dialog - use collapsed state            if (mShowCombinedVolumes) {                collapse();            }            mDialog.show();        }        // Do a little vibrate if applicable (only when going into vibrate mode)        if ((streamType != AudioService.STREAM_REMOTE_MUSIC) &&                ((flags & AudioManager.FLAG_VIBRATE) != 0) &&                mAudioService.isStreamAffectedByRingerMode(streamType) &&                mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {            sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY);        }    } protected void onPlaySound(int streamType, int flags) {        if (hasMessages(MSG_STOP_SOUNDS)) {            removeMessages(MSG_STOP_SOUNDS);            // Force stop right now            onStopSounds();        }        synchronized (this) {            ToneGenerator toneGen = getOrCreateToneGenerator(streamType);            if (toneGen != null) {                toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);                sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION);            }        }    } protected void onStopSounds() {        synchronized (this) {            int numStreamTypes = AudioSystem.getNumStreamTypes();            for (int i = numStreamTypes - 1; i >= 0; i--) {                ToneGenerator toneGen = mToneGenerators[i];                if (toneGen != null) {                    toneGen.stopTone();                }            }        }    } protected void onFreeResources() {        synchronized (this) {            for (int i = mToneGenerators.length - 1; i >= 0; i--) {                if (mToneGenerators[i] != null) {                    mToneGenerators[i].release();                }                mToneGenerators[i] = null;            }        }    }
framework层调用,不涉及JNI层。

更多相关文章

  1. Android--自定义SeekBarPreference控件
  2. [AndroidTips]Android预定义样式
  3. Android中自定义属性的使用
  4. 修改官方Twitter For Android,自定义 API

随机推荐

  1. Android版本及API等级关系
  2. java.lang.NullPointerException: Attemp
  3. android 操作文件
  4. Android更新UI的五种方式
  5. Duplicate files copied (Android(安卓)S
  6. android 之simpleAdapter详解
  7. android google directions
  8. Android(安卓)OpenCV 灰度图转化
  9. android使用shape设置下边框
  10. Android中使用TabHost实现类似标签栏的效