blob: fb0622463514a7a37e74eeabcb76b5df658f0efc [file] [log] [blame]
/*
* Copyright (C) 2015 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.menu;
import android.content.Context;
import android.media.tv.TvTrackInfo;
import android.support.annotation.VisibleForTesting;
import com.android.tv.Features;
import com.android.tv.R;
import com.android.tv.TvOptionsManager;
import com.android.tv.customization.CustomAction;
import com.android.tv.data.DisplayMode;
import com.android.tv.ui.TvViewUiManager;
import com.android.tv.ui.sidepanel.ClosedCaptionFragment;
import com.android.tv.ui.sidepanel.DeveloperOptionFragment;
import com.android.tv.ui.sidepanel.DisplayModeFragment;
import com.android.tv.ui.sidepanel.MultiAudioFragment;
import com.android.tv.util.PipInputManager;
import java.util.ArrayList;
import java.util.List;
/*
* An adapter of options.
*/
public class TvOptionsRowAdapter extends CustomizableOptionsRowAdapter {
private static final boolean ENABLE_IN_APP_PIP = false;
private int mPositionPipAction;
// If mInAppPipAction is false, system-wide PIP is used.
private boolean mInAppPipAction = true;
public TvOptionsRowAdapter(Context context, List<CustomAction> customActions) {
super(context, customActions);
}
@Override
protected List<MenuAction> createBaseActions() {
List<MenuAction> actionList = new ArrayList<>();
actionList.add(MenuAction.SELECT_CLOSED_CAPTION_ACTION);
setOptionChangedListener(MenuAction.SELECT_CLOSED_CAPTION_ACTION);
actionList.add(MenuAction.SELECT_DISPLAY_MODE_ACTION);
setOptionChangedListener(MenuAction.SELECT_DISPLAY_MODE_ACTION);
actionList.add(MenuAction.PIP_IN_APP_ACTION);
setOptionChangedListener(MenuAction.PIP_IN_APP_ACTION);
mPositionPipAction = actionList.size() - 1;
actionList.add(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
setOptionChangedListener(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
actionList.add(MenuAction.MORE_CHANNELS_ACTION);
if (DeveloperOptionFragment.shouldShow()) {
actionList.add(MenuAction.DEV_ACTION);
}
actionList.add(MenuAction.SETTINGS_ACTION);
if (getCustomActions() != null) {
// Adjust Pip action position which will be changed by applying custom actions.
for (CustomAction customAction : getCustomActions()) {
if (customAction.isFront()) {
mPositionPipAction++;
}
}
}
return actionList;
}
@Override
protected boolean updateActions() {
boolean changed = false;
if (updatePipAction()) {
changed = true;
}
if (updateMultiAudioAction()) {
changed = true;
}
if (updateDisplayModeAction()) {
changed = true;
}
return changed;
}
private boolean updatePipAction() {
// There are four states.
// Case 1. The device doesn't even have any input for PIP. (e.g. OTT box without HDMI input)
// => Remove the icon.
// Case 2. The device has one or more inputs for PIP but none of them are currently
// available.
// => Show the icon but disable it.
// Case 3. The device has one or more available PIP inputs and now it's tuned off.
// => Show the icon with "Off".
// Case 4. The device has one or more available PIP inputs but it's already turned on.
// => Show the icon with "On".
boolean changed = false;
// Case 1
PipInputManager pipInputManager = getMainActivity().getPipInputManager();
if (ENABLE_IN_APP_PIP && pipInputManager.getPipInputSize(false) > 1) {
if (!mInAppPipAction) {
removeAction(mPositionPipAction);
addAction(mPositionPipAction, MenuAction.PIP_IN_APP_ACTION);
mInAppPipAction = true;
changed = true;
}
} else {
if (mInAppPipAction) {
removeAction(mPositionPipAction);
mInAppPipAction = false;
if (Features.PICTURE_IN_PICTURE.isEnabled(getMainActivity())) {
addAction(mPositionPipAction, MenuAction.SYSTEMWIDE_PIP_ACTION);
}
return true;
}
return false;
}
// Case 2
boolean isPipEnabled = getMainActivity().isPipEnabled();
boolean oldEnabled = MenuAction.PIP_IN_APP_ACTION.isEnabled();
boolean newEnabled = pipInputManager.getPipInputSize(true) > 0;
if (oldEnabled != newEnabled) {
// Should not disable the item if the PIP is already turned on so that the user can
// force exit it.
if (newEnabled || !isPipEnabled) {
MenuAction.PIP_IN_APP_ACTION.setEnabled(newEnabled);
changed = true;
}
}
// Case 3 & 4 - we just need to update the icon.
MenuAction.PIP_IN_APP_ACTION.setDrawableResId(
isPipEnabled ? R.drawable.ic_tvoption_pip : R.drawable.ic_tvoption_pip_off);
return changed;
}
@VisibleForTesting
boolean updateMultiAudioAction() {
List<TvTrackInfo> audioTracks = getMainActivity().getTracks(TvTrackInfo.TYPE_AUDIO);
boolean oldEnabled = MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled();
boolean newEnabled = audioTracks != null && audioTracks.size() > 1;
if (oldEnabled != newEnabled) {
MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.setEnabled(newEnabled);
return true;
}
return false;
}
private boolean updateDisplayModeAction() {
TvViewUiManager uiManager = getMainActivity().getTvViewUiManager();
boolean oldEnabled = MenuAction.SELECT_DISPLAY_MODE_ACTION.isEnabled();
boolean newEnabled = uiManager.isDisplayModeAvailable(DisplayMode.MODE_FULL)
|| uiManager.isDisplayModeAvailable(DisplayMode.MODE_ZOOM);
if (oldEnabled != newEnabled) {
MenuAction.SELECT_DISPLAY_MODE_ACTION.setEnabled(newEnabled);
return true;
}
return false;
}
@Override
protected void executeBaseAction(int type) {
switch (type) {
case TvOptionsManager.OPTION_CLOSED_CAPTIONS:
getMainActivity().getOverlayManager().getSideFragmentManager()
.show(new ClosedCaptionFragment());
break;
case TvOptionsManager.OPTION_DISPLAY_MODE:
getMainActivity().getOverlayManager().getSideFragmentManager()
.show(new DisplayModeFragment());
break;
case TvOptionsManager.OPTION_IN_APP_PIP:
getMainActivity().togglePipView();
break;
case TvOptionsManager.OPTION_SYSTEMWIDE_PIP:
getMainActivity().enterPictureInPictureMode();
break;
case TvOptionsManager.OPTION_MULTI_AUDIO:
getMainActivity().getOverlayManager().getSideFragmentManager()
.show(new MultiAudioFragment());
break;
case TvOptionsManager.OPTION_MORE_CHANNELS:
getMainActivity().showMerchantCollection();
break;
case TvOptionsManager.OPTION_DEVELOPER:
getMainActivity().getOverlayManager().getSideFragmentManager()
.show(new DeveloperOptionFragment());
break;
case TvOptionsManager.OPTION_SETTINGS:
getMainActivity().showSettingsFragment();
break;
}
}
}