aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/AudioManagerHelper.java
blob: 4fca06acc65d764382692ce5e44184e93083aa52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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();
    }
}