FileDocCategorySizeDatePackage
VolumeControlAction.javaAPI DocAndroid 5.1 API7290Thu Mar 12 22:22:42 GMT 2015com.android.server.hdmi

VolumeControlAction

public final class VolumeControlAction extends HdmiCecFeatureAction
Feature action that transmits volume change to Audio Receiver.

This action is created when a user pressed volume up/down. However, Android only provides a listener for delta of some volume change instead of individual key event. Also it's hard to know Audio Receiver's number of volume steps for a single volume control key. Because of this, it sends key-down event until IRT timeout happens, and it will send key-up event if no additional volume change happens; otherwise, it will send again key-down as press and hold feature does.

Fields Summary
private static final String
TAG
private static final int
STATE_WAIT_FOR_NEXT_VOLUME_PRESS
private static final int
MAX_VOLUME
private static final int
UNKNOWN_AVR_VOLUME
private final int
mAvrAddress
private boolean
mIsVolumeUp
private long
mLastKeyUpdateTime
private int
mLastAvrVolume
private boolean
mLastAvrMute
private boolean
mSentKeyPressed
Constructors Summary
VolumeControlAction(HdmiCecLocalDevice source, int avrAddress, boolean isVolumeUp)

        super(source);
        mAvrAddress = avrAddress;
        mIsVolumeUp = isVolumeUp;
        mLastAvrVolume = UNKNOWN_AVR_VOLUME;
        mLastAvrMute = false;
        mSentKeyPressed = false;

        updateLastKeyUpdateTime();
    
Methods Summary
protected voidclear()

        super.clear();
        if (mSentKeyPressed) {
            sendVolumeKeyReleased();
        }
        if (mLastAvrVolume != UNKNOWN_AVR_VOLUME) {
            tv().setAudioStatus(mLastAvrMute, mLastAvrVolume);
            mLastAvrVolume = UNKNOWN_AVR_VOLUME;
            mLastAvrMute = false;
        }
    
private booleanhandleFeatureAbort(HdmiCecMessage cmd)

        int originalOpcode = cmd.getParams()[0] & 0xFF;
        // Since it sends <User Control Released> only when it finishes this action,
        // it takes care of <User Control Pressed> only here.
        if (originalOpcode == MESSAGE_USER_CONTROL_PRESSED) {
            finish();
            return true;
        }
        return false;
    
private booleanhandleReportAudioStatus(HdmiCecMessage cmd)

        byte params[] = cmd.getParams();
        boolean mute = (params[0] & 0x80) == 0x80;
        int volume = params[0] & 0x7F;
        mLastAvrVolume = volume;
        mLastAvrMute = mute;
        if (shouldUpdateAudioVolume(mute)) {
            HdmiLogger.debug("Force volume change[mute:%b, volume=%d]", mute, volume);
            tv().setAudioStatus(mute, volume);
            mLastAvrVolume = UNKNOWN_AVR_VOLUME;
            mLastAvrMute = false;
        }
        return true;
    
voidhandleTimerEvent(int state)

        if (state != STATE_WAIT_FOR_NEXT_VOLUME_PRESS) {
            return;
        }

        if (System.currentTimeMillis() - mLastKeyUpdateTime >= IRT_MS) {
            finish();
        } else {
            sendVolumeKeyPressed();
            resetTimer();
        }
    
voidhandleVolumeChange(boolean isVolumeUp)

        if (mIsVolumeUp != isVolumeUp) {
            HdmiLogger.debug("Volume Key Status Changed[old:%b new:%b]", mIsVolumeUp, isVolumeUp);
            sendVolumeKeyReleased();
            mIsVolumeUp = isVolumeUp;
            sendVolumeKeyPressed();
            resetTimer();
        }
        updateLastKeyUpdateTime();
    
booleanprocessCommand(HdmiCecMessage cmd)

        if (mState != STATE_WAIT_FOR_NEXT_VOLUME_PRESS || cmd.getSource() != mAvrAddress) {
            return false;
        }

        switch (cmd.getOpcode()) {
            case MESSAGE_REPORT_AUDIO_STATUS:
                return handleReportAudioStatus(cmd);
            case MESSAGE_FEATURE_ABORT:
                return handleFeatureAbort(cmd);
        }
        return false;
    
private voidresetTimer()

        mActionTimer.clearTimerMessage();
        addTimer(STATE_WAIT_FOR_NEXT_VOLUME_PRESS, IRT_MS);
    
public static intscaleToCecVolume(int volume, int scale)
Scale a custom volume value to cec volume scale.

param
volume volume value in custom scale
param
scale scale of volume (max volume)
return
a volume scaled to cec volume range


                                        
           
        return (volume * MAX_VOLUME) / scale;
    
public static intscaleToCustomVolume(int cecVolume, int scale)
Scale a cec volume which is in range of 0 to 100 to custom volume level.

param
cecVolume volume value in cec volume scale. It should be in a range of [0-100]
param
scale scale of custom volume (max volume)
return
a volume scaled to custom volume range

        return (cecVolume * scale) / MAX_VOLUME;
    
private voidsendVolumeKeyPressed()

        sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), mAvrAddress,
                mIsVolumeUp ? HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
                        : HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
        mSentKeyPressed = true;
    
private voidsendVolumeKeyReleased()

        sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
                getSourceAddress(), mAvrAddress));
        mSentKeyPressed = false;
    
private booleanshouldUpdateAudioVolume(boolean mute)

        // Do nothing if in mute.
        if (mute) {
            return true;
        }

        // Update audio status if current volume position is edge of volume bar,
        // i.e max or min volume.
        AudioManager audioManager = tv().getService().getAudioManager();
        int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        if (mIsVolumeUp) {
            int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            return currentVolume == maxVolume;
        } else {
            return currentVolume == 0;
        }
    
booleanstart()

        mState = STATE_WAIT_FOR_NEXT_VOLUME_PRESS;
        sendVolumeKeyPressed();
        resetTimer();
        return true;
    
private voidupdateLastKeyUpdateTime()

        mLastKeyUpdateTime = System.currentTimeMillis();