FileDocCategorySizeDatePackage
VolumePanel.javaAPI DocAndroid 1.5 API14354Wed May 06 22:41:56 BST 2009android.view

VolumePanel

public class VolumePanel extends android.os.Handler
Handle the volume up and down keys. This code really should be moved elsewhere.
hide

Fields Summary
private static final String
TAG
private static boolean
LOGD
public static final int
PLAY_SOUND_DELAY
The delay before playing a sound. This small period exists so the user can press another key (non-volume keys, too) to have it NOT be audible.

PhoneWindow will implement this part.

public static final int
VIBRATE_DELAY
The delay before vibrating. This small period exists so if the user is moving to silent mode, it will not emit a short vibrate (it normally would since vibrate is between normal mode and silent mode using hardware keys).
private static final int
VIBRATE_DURATION
private static final int
BEEP_DURATION
private static final int
MAX_VOLUME
private static final int
FREE_DELAY
private static final int
MSG_VOLUME_CHANGED
private static final int
MSG_FREE_RESOURCES
private static final int
MSG_PLAY_SOUND
private static final int
MSG_STOP_SOUNDS
private static final int
MSG_VIBRATE
private static final int
RINGTONE_VOLUME_TEXT
private static final int
MUSIC_VOLUME_TEXT
private static final int
INCALL_VOLUME_TEXT
private static final int
ALARM_VOLUME_TEXT
private static final int
UNKNOWN_VOLUME_TEXT
private static final int
NOTIFICATION_VOLUME_TEXT
private static final int
BLUETOOTH_INCALL_VOLUME_TEXT
protected android.content.Context
mContext
private android.media.AudioManager
mAudioManager
protected android.media.AudioService
mAudioService
private final android.widget.Toast
mToast
private final View
mView
private final android.widget.TextView
mMessage
private final android.widget.TextView
mAdditionalMessage
private final android.widget.ImageView
mSmallStreamIcon
private final android.widget.ImageView
mLargeStreamIcon
private final android.widget.ProgressBar
mLevel
private android.media.ToneGenerator[]
mToneGenerators
private android.os.Vibrator
mVibrator
Constructors Summary
public VolumePanel(android.content.Context context, android.media.AudioService volumeService)


         
        mContext = context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioService = volumeService;
        mToast = new Toast(context);

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = mView = inflater.inflate(com.android.internal.R.layout.volume_adjust, null);
        mMessage = (TextView) view.findViewById(com.android.internal.R.id.message);
        mAdditionalMessage =
                (TextView) view.findViewById(com.android.internal.R.id.additional_message);
        mSmallStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.other_stream_icon);
        mLargeStreamIcon = (ImageView) view.findViewById(com.android.internal.R.id.ringer_stream_icon);
        mLevel = (ProgressBar) view.findViewById(com.android.internal.R.id.level);

        mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
        mVibrator = new Vibrator();
    
Methods Summary
private android.media.ToneGeneratorgetOrCreateToneGenerator(int streamType)
Lock on this VolumePanel instance as long as you use the returned ToneGenerator.

        synchronized (this) {
            if (mToneGenerators[streamType] == null) {
                return mToneGenerators[streamType] = new ToneGenerator(streamType, MAX_VOLUME);
            } else {
                return mToneGenerators[streamType];
            }
        }
    
public voidhandleMessage(android.os.Message msg)

        switch (msg.what) {

            case MSG_VOLUME_CHANGED: {
                onVolumeChanged(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;
            }

        }
    
protected voidonFreeResources()

        // We'll keep the views, just ditch the cached drawable and hence
        // bitmaps
        mSmallStreamIcon.setImageDrawable(null);
        mLargeStreamIcon.setImageDrawable(null);

        synchronized (this) {
            for (int i = mToneGenerators.length - 1; i >= 0; i--) {
                if (mToneGenerators[i] != null) {
                    mToneGenerators[i].release();
                }
                mToneGenerators[i] = null;
            }
        }
    
protected voidonPlaySound(int streamType, int flags)


        if (hasMessages(MSG_STOP_SOUNDS)) {
            removeMessages(MSG_STOP_SOUNDS);
            // Force stop right now
            onStopSounds();
        }

        synchronized (this) {
            ToneGenerator toneGen = getOrCreateToneGenerator(streamType);
            toneGen.startTone(ToneGenerator.TONE_PROP_BEEP);
        }

        sendMessageDelayed(obtainMessage(MSG_STOP_SOUNDS), BEEP_DURATION);
    
protected voidonShowVolumeChanged(int streamType, int flags)

        int index = mAudioService.getStreamVolume(streamType);
        int message = UNKNOWN_VOLUME_TEXT;
        int additionalMessage = 0;

        if (LOGD) {
            Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType
                    + ", flags: " + flags + "), index: " + index);
        }

        // get max volume for progress bar
        int max = mAudioService.getStreamMaxVolume(streamType);

        switch (streamType) {

            case AudioManager.STREAM_RING: {
                message = RINGTONE_VOLUME_TEXT;
                setRingerIcon(index);
                break;
            }

            case AudioManager.STREAM_MUSIC: {
                message = MUSIC_VOLUME_TEXT;
                if (mAudioManager.isBluetoothA2dpOn()) {
                    additionalMessage =
                        com.android.internal.R.string.volume_music_hint_playing_through_bluetooth;
                    setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p);
                } else {
                    setSmallIcon(index);
                }
                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++;
                message = INCALL_VOLUME_TEXT;
                setSmallIcon(index);
                break;
            }

            case AudioManager.STREAM_ALARM: {
                message = ALARM_VOLUME_TEXT;
                setSmallIcon(index);
                break;
            }

            case AudioManager.STREAM_NOTIFICATION: {
                message = NOTIFICATION_VOLUME_TEXT;
                setSmallIcon(index);
                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++;
                message = BLUETOOTH_INCALL_VOLUME_TEXT;
                setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_in_call);
                break;
            }
        }

        String messageString = Resources.getSystem().getString(message);
        if (!mMessage.getText().equals(messageString)) {
            mMessage.setText(messageString);
        }

        if (additionalMessage == 0) {
            mAdditionalMessage.setVisibility(View.GONE);
        } else {
            mAdditionalMessage.setVisibility(View.VISIBLE);
            mAdditionalMessage.setText(Resources.getSystem().getString(additionalMessage));
        }

        if (max != mLevel.getMax()) {
            mLevel.setMax(max);
        }
        mLevel.setProgress(index);

        mToast.setView(mView);
        mToast.setDuration(Toast.LENGTH_SHORT);
        mToast.setGravity(Gravity.TOP, 0, 0);
        mToast.show();

        // Do a little vibrate if applicable (only when going into vibrate mode)
        if ((flags & AudioManager.FLAG_VIBRATE) != 0 &&
                mAudioService.isStreamAffectedByRingerMode(streamType) &&
                mAudioService.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE &&
                mAudioService.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
            sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY);
        }

    
protected voidonStopSounds()


        synchronized (this) {
            int numStreamTypes = AudioSystem.getNumStreamTypes();
            for (int i = numStreamTypes - 1; i >= 0; i--) {
                ToneGenerator toneGen = mToneGenerators[i];
                if (toneGen != null) {
                    toneGen.stopTone();
                }
            }
        }
    
protected voidonVibrate()


        // Make sure we ended up in vibrate ringer mode
        if (mAudioService.getRingerMode() != AudioManager.RINGER_MODE_VIBRATE) {
            return;
        }

        mVibrator.vibrate(VIBRATE_DURATION);
    
protected voidonVolumeChanged(int streamType, int flags)
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.


        if (LOGD) Log.d(TAG, "onVolumeChanged(streamType: " + streamType + ", flags: " + flags + ")");

        if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
            onShowVolumeChanged(streamType, flags);
        }

        if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
            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);
    
public voidpostVolumeChanged(int streamType, int flags)

        if (hasMessages(MSG_VOLUME_CHANGED)) return;
        removeMessages(MSG_FREE_RESOURCES);
        obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
    
private voidsetLargeIcon(int resId)
Makes the large image view visible with the given icon.

param
resId The icon to display.

        mSmallStreamIcon.setVisibility(View.GONE);
        mLargeStreamIcon.setVisibility(View.VISIBLE);
        mLargeStreamIcon.setImageResource(resId);
    
private voidsetRingerIcon(int index)
Makes the ringer icon visible with an icon that is chosen based on the current ringer mode.

param
index

        mSmallStreamIcon.setVisibility(View.GONE);
        mLargeStreamIcon.setVisibility(View.VISIBLE);

        int ringerMode = mAudioService.getRingerMode();
        int icon;

        if (LOGD) Log.d(TAG, "setRingerIcon(index: " + index+ "), ringerMode: " + ringerMode);

        if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
            icon = com.android.internal.R.drawable.ic_volume_off;
        } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
            icon = com.android.internal.R.drawable.ic_vibrate;
        } else {
            icon = com.android.internal.R.drawable.ic_volume;
        }
        mLargeStreamIcon.setImageResource(icon);
    
private voidsetSmallIcon(int index)
Makes the small icon visible, and hides the large icon.

param
index The volume index, where 0 means muted.

        mLargeStreamIcon.setVisibility(View.GONE);
        mSmallStreamIcon.setVisibility(View.VISIBLE);

        mSmallStreamIcon.setImageResource(index == 0
                ? com.android.internal.R.drawable.ic_volume_off_small
                : com.android.internal.R.drawable.ic_volume_small);