Home | History | Annotate | Download | only in tv
      1 package com.android.tv;
      2 
      3 import android.app.Activity;
      4 import android.content.Context;
      5 import android.media.AudioManager;
      6 import android.os.Build;
      7 
      8 import com.android.tv.receiver.AudioCapabilitiesReceiver;
      9 import com.android.tv.ui.TunableTvView;
     10 
     11 /**
     12  * A helper class to help {@link MainActivity} to handle audio-related stuffs.
     13  */
     14 class AudioManagerHelper implements AudioManager.OnAudioFocusChangeListener {
     15     private static final float AUDIO_MAX_VOLUME = 1.0f;
     16     private static final float AUDIO_MIN_VOLUME = 0.0f;
     17     private static final float AUDIO_DUCKING_VOLUME = 0.3f;
     18 
     19     private final Activity mActivity;
     20     private final TunableTvView mTvView;
     21     private final AudioManager mAudioManager;
     22     private final AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
     23 
     24     private boolean mAc3PassthroughSupported;
     25     private int mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
     26 
     27     AudioManagerHelper(Activity activity, TunableTvView tvView) {
     28         mActivity = activity;
     29         mTvView = tvView;
     30         mAudioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
     31         mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(activity,
     32                 new AudioCapabilitiesReceiver.OnAc3PassthroughCapabilityChangeListener() {
     33                     @Override
     34                     public void onAc3PassthroughCapabilityChange(boolean capability) {
     35                         mAc3PassthroughSupported = capability;
     36                     }
     37                 });
     38         mAudioCapabilitiesReceiver.register();
     39     }
     40 
     41     /**
     42      * Sets suitable volume to {@link TunableTvView} according to the current audio focus.
     43      * If the focus status is {@link AudioManager#AUDIOFOCUS_LOSS} and the activity is under PIP
     44      * mode, this method will finish the activity.
     45      */
     46     void setVolumeByAudioFocusStatus() {
     47         if (mTvView.isPlaying()) {
     48             switch (mAudioFocusStatus) {
     49                 case AudioManager.AUDIOFOCUS_GAIN:
     50                     mTvView.setStreamVolume(AUDIO_MAX_VOLUME);
     51                     break;
     52                 case AudioManager.AUDIOFOCUS_LOSS:
     53                     if (Features.PICTURE_IN_PICTURE.isEnabled(mActivity)
     54                             && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
     55                             && mActivity.isInPictureInPictureMode()) {
     56                         mActivity.finish();
     57                         break;
     58                     }
     59                 case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
     60                     mTvView.setStreamVolume(AUDIO_MIN_VOLUME);
     61                     break;
     62                 case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
     63                     mTvView.setStreamVolume(AUDIO_DUCKING_VOLUME);
     64                     break;
     65             }
     66         }
     67     }
     68 
     69     /**
     70      * Tries to request audio focus from {@link AudioManager} and set volume according to the
     71      * returned result.
     72      */
     73     void requestAudioFocus() {
     74         int result = mAudioManager.requestAudioFocus(this,
     75                 AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
     76         mAudioFocusStatus = (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) ?
     77                 AudioManager.AUDIOFOCUS_GAIN : AudioManager.AUDIOFOCUS_LOSS;
     78         setVolumeByAudioFocusStatus();
     79     }
     80 
     81     /**
     82      * Abandons audio focus.
     83      */
     84     void abandonAudioFocus() {
     85         mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
     86         mAudioManager.abandonAudioFocus(this);
     87     }
     88 
     89     /**
     90      * Returns {@code true} if the device supports AC3 pass-through.
     91      */
     92     boolean isAc3PassthroughSupported() {
     93         return mAc3PassthroughSupported;
     94     }
     95 
     96     /**
     97      * Release the resources the helper class may occupied.
     98      */
     99     void release() {
    100         mAudioCapabilitiesReceiver.unregister();
    101     }
    102 
    103     @Override
    104     public void onAudioFocusChange(int focusChange) {
    105         mAudioFocusStatus = focusChange;
    106         setVolumeByAudioFocusStatus();
    107     }
    108 }
    109