blob: 942d431df5f1bf62174128f66e2f090a7f939b5b [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
import com.android.tv.ui.TunableTvViewPlayingApi;
/** 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 TunableTvViewPlayingApi mTvView;
private final AudioManager mAudioManager;
private final AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
private boolean mAc3PassthroughSupported;
private int mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
AudioManagerHelper(Activity activity, TunableTvViewPlayingApi 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:
if (mTvView.isTimeShiftAvailable()) {
mTvView.timeshiftPlay();
} else {
mTvView.setStreamVolume(AUDIO_MAX_VOLUME);
}
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (TvFeatures.PICTURE_IN_PICTURE.isEnabled(mActivity)
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& mActivity.isInPictureInPictureMode()) {
mActivity.finish();
break;
}
// fall through
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mTvView.isTimeShiftAvailable()) {
mTvView.timeshiftPause();
} else {
mTvView.setStreamVolume(AUDIO_MIN_VOLUME);
}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mTvView.isTimeShiftAvailable()) {
mTvView.timeshiftPause();
} else {
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();
}
}