| package com.android.tv; |
| |
| import android.app.Activity; |
| import android.content.Context; |
| import android.media.AudioManager; |
| import android.os.Build; |
| |
| import com.android.tv.receiver.AudioCapabilitiesReceiver; |
| import com.android.tv.ui.TunableTvView; |
| |
| /** |
| * A helper class to help {@link MainActivity} to handle audio-related stuffs. |
| */ |
| class AudioManagerHelper implements AudioManager.OnAudioFocusChangeListener { |
| private static final float AUDIO_MAX_VOLUME = 1.0f; |
| private static final float AUDIO_MIN_VOLUME = 0.0f; |
| private static final float AUDIO_DUCKING_VOLUME = 0.3f; |
| |
| private final Activity mActivity; |
| private final TunableTvView mTvView; |
| private final AudioManager mAudioManager; |
| private final AudioCapabilitiesReceiver mAudioCapabilitiesReceiver; |
| |
| private boolean mAc3PassthroughSupported; |
| private int mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS; |
| |
| AudioManagerHelper(Activity activity, TunableTvView tvView) { |
| mActivity = activity; |
| mTvView = tvView; |
| mAudioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE); |
| mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(activity, |
| new AudioCapabilitiesReceiver.OnAc3PassthroughCapabilityChangeListener() { |
| @Override |
| public void onAc3PassthroughCapabilityChange(boolean capability) { |
| mAc3PassthroughSupported = capability; |
| } |
| }); |
| mAudioCapabilitiesReceiver.register(); |
| } |
| |
| /** |
| * Sets suitable volume to {@link TunableTvView} according to the current audio focus. |
| * If the focus status is {@link AudioManager#AUDIOFOCUS_LOSS} and the activity is under PIP |
| * mode, this method will finish the activity. |
| */ |
| void setVolumeByAudioFocusStatus() { |
| if (mTvView.isPlaying()) { |
| switch (mAudioFocusStatus) { |
| case AudioManager.AUDIOFOCUS_GAIN: |
| mTvView.setStreamVolume(AUDIO_MAX_VOLUME); |
| break; |
| case AudioManager.AUDIOFOCUS_LOSS: |
| if (Features.PICTURE_IN_PICTURE.isEnabled(mActivity) |
| && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N |
| && mActivity.isInPictureInPictureMode()) { |
| mActivity.finish(); |
| break; |
| } |
| case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
| mTvView.setStreamVolume(AUDIO_MIN_VOLUME); |
| break; |
| case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
| mTvView.setStreamVolume(AUDIO_DUCKING_VOLUME); |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Tries to request audio focus from {@link AudioManager} and set volume according to the |
| * returned result. |
| */ |
| void requestAudioFocus() { |
| int result = mAudioManager.requestAudioFocus(this, |
| AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); |
| mAudioFocusStatus = (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) ? |
| AudioManager.AUDIOFOCUS_GAIN : AudioManager.AUDIOFOCUS_LOSS; |
| setVolumeByAudioFocusStatus(); |
| } |
| |
| /** |
| * Abandons audio focus. |
| */ |
| void abandonAudioFocus() { |
| mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS; |
| mAudioManager.abandonAudioFocus(this); |
| } |
| |
| /** |
| * Returns {@code true} if the device supports AC3 pass-through. |
| */ |
| boolean isAc3PassthroughSupported() { |
| return mAc3PassthroughSupported; |
| } |
| |
| /** |
| * Release the resources the helper class may occupied. |
| */ |
| void release() { |
| mAudioCapabilitiesReceiver.unregister(); |
| } |
| |
| @Override |
| public void onAudioFocusChange(int focusChange) { |
| mAudioFocusStatus = focusChange; |
| setVolumeByAudioFocusStatus(); |
| } |
| } |