aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/ui/sidepanel
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/ui/sidepanel')
-rw-r--r--src/com/android/tv/ui/sidepanel/ActionItem.java20
-rw-r--r--src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java108
-rw-r--r--src/com/android/tv/ui/sidepanel/CompoundButtonItem.java21
-rw-r--r--src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java116
-rw-r--r--src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java45
-rw-r--r--src/com/android/tv/ui/sidepanel/Item.java12
-rw-r--r--src/com/android/tv/ui/sidepanel/PipInputSelectorFragment.java170
-rw-r--r--src/com/android/tv/ui/sidepanel/SettingsFragment.java137
-rw-r--r--src/com/android/tv/ui/sidepanel/SideFragment.java158
-rw-r--r--src/com/android/tv/ui/sidepanel/SideFragmentManager.java38
-rw-r--r--src/com/android/tv/ui/sidepanel/SimpleActionItem.java (renamed from src/com/android/tv/ui/sidepanel/SimpleItem.java)6
-rw-r--r--src/com/android/tv/ui/sidepanel/SubMenuItem.java13
-rw-r--r--src/com/android/tv/ui/sidepanel/SwitchItem.java5
-rw-r--r--src/com/android/tv/ui/sidepanel/parentalcontrols/ParentalControlsFragment.java13
-rw-r--r--src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java42
-rw-r--r--src/com/android/tv/ui/sidepanel/parentalcontrols/SubRatingsFragment.java32
16 files changed, 418 insertions, 518 deletions
diff --git a/src/com/android/tv/ui/sidepanel/ActionItem.java b/src/com/android/tv/ui/sidepanel/ActionItem.java
index 23aff91c..cd70a886 100644
--- a/src/com/android/tv/ui/sidepanel/ActionItem.java
+++ b/src/com/android/tv/ui/sidepanel/ActionItem.java
@@ -17,7 +17,6 @@
package com.android.tv.ui.sidepanel;
import android.view.View;
-import android.widget.ImageView;
import android.widget.TextView;
import com.android.tv.R;
@@ -25,24 +24,14 @@ import com.android.tv.R;
public abstract class ActionItem extends Item {
private final String mTitle;
private final String mDescription;
- private final int mIconId;
public ActionItem(String title) {
- this(title, null, 0);
+ this(title, null);
}
public ActionItem(String title, String description) {
- this(title, description, 0);
- }
-
- public ActionItem(String title, int iconId) {
- this(title, null, iconId);
- }
-
- public ActionItem(String title, String description, int iconId) {
mTitle = title;
mDescription = description;
- mIconId = iconId;
}
@Override
@@ -62,12 +51,5 @@ public abstract class ActionItem extends Item {
} else {
descriptionView.setVisibility(View.GONE);
}
- ImageView iconView = (ImageView) view.findViewById(R.id.icon);
- if (mIconId != 0) {
- iconView.setVisibility(View.VISIBLE);
- iconView.setImageResource(mIconId);
- } else {
- iconView.setVisibility(View.GONE);
- }
}
} \ No newline at end of file
diff --git a/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java b/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java
index d6ccdf6b..341e4350 100644
--- a/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java
+++ b/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java
@@ -18,6 +18,7 @@ package com.android.tv.ui.sidepanel;
import android.media.tv.TvTrackInfo;
import android.os.Bundle;
+import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -25,7 +26,6 @@ import android.view.ViewGroup;
import com.android.tv.R;
import com.android.tv.util.CaptionSettings;
-import com.android.tv.util.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -38,8 +38,6 @@ public class ClosedCaptionFragment extends SideFragment {
private String mClosedCaptionLanguage;
private String mClosedCaptionTrackId;
private ClosedCaptionOptionItem mSelectedItem;
- private List<Item> mItems;
- private boolean mPaused;
public ClosedCaptionFragment() {
super(KeyEvent.KEYCODE_CAPTIONS, KeyEvent.KEYCODE_S);
@@ -63,37 +61,32 @@ public class ClosedCaptionFragment extends SideFragment {
mClosedCaptionLanguage = captionSettings.getLanguage();
mClosedCaptionTrackId = captionSettings.getTrackId();
- mItems = new ArrayList<>();
+ List<Item> items = new ArrayList<>();
mSelectedItem = null;
List<TvTrackInfo> tracks = getMainActivity().getTracks(TvTrackInfo.TYPE_SUBTITLE);
if (tracks != null && !tracks.isEmpty()) {
- String trackId = captionSettings.isEnabled() ?
+ String selectedTrackId = captionSettings.isEnabled() ?
getMainActivity().getSelectedTrack(TvTrackInfo.TYPE_SUBTITLE) : null;
- boolean isEnabled = trackId != null;
-
- ClosedCaptionOptionItem item = new ClosedCaptionOptionItem(
- getString(R.string.closed_caption_option_item_off),
- CaptionSettings.OPTION_OFF, null, null);
- // Pick 'Off' as default because we may fail to find the matching language.
- mSelectedItem = item;
- if (!isEnabled) {
+ ClosedCaptionOptionItem item = new ClosedCaptionOptionItem(null, null);
+ items.add(item);
+ if (selectedTrackId == null) {
+ mSelectedItem = item;
item.setChecked(true);
+ setSelectedPosition(0);
}
- mItems.add(item);
-
- for (final TvTrackInfo track : tracks) {
- item = new ClosedCaptionOptionItem(getLabel(track),
- CaptionSettings.OPTION_ON, track.getId(), track.getLanguage());
- if (isEnabled && track.getId().equals(trackId)) {
- item.setChecked(true);
+ for (int i = 0; i < tracks.size(); i++) {
+ item = new ClosedCaptionOptionItem(tracks.get(i), i);
+ if (TextUtils.equals(selectedTrackId, tracks.get(i).getId())) {
mSelectedItem = item;
+ item.setChecked(true);
+ setSelectedPosition(i + 1);
}
- mItems.add(item);
+ items.add(item);
}
}
if (getMainActivity().hasCaptioningSettingsActivity()) {
- mItems.add(new ActionItem(getString(R.string.closed_caption_system_settings),
+ items.add(new ActionItem(getString(R.string.closed_caption_system_settings),
getString(R.string.closed_caption_system_settings_description)) {
@Override
protected void onSelected() {
@@ -103,14 +96,14 @@ public class ClosedCaptionFragment extends SideFragment {
@Override
protected void onFocused() {
super.onFocused();
- if (!mPaused && mSelectedItem != null) {
+ if (mSelectedItem != null) {
getMainActivity().selectSubtitleTrack(
mSelectedItem.mOption, mSelectedItem.mTrackId);
}
}
});
}
- return mItems;
+ return items;
}
@Override
@@ -120,50 +113,6 @@ public class ClosedCaptionFragment extends SideFragment {
}
@Override
- public void onResume() {
- super.onResume();
- if (mPaused) {
- // Apply system's closed caption settings to the UI.
- CaptionSettings captionSettings = getMainActivity().getCaptionSettings();
- mClosedCaptionOption = CaptionSettings.OPTION_SYSTEM;
- mClosedCaptionLanguage = captionSettings.getSystemLanguage();
- ClosedCaptionOptionItem selectedItem = null;
- if (captionSettings.isSystemSettingEnabled()) {
- for (Item item : mItems) {
- if (!(item instanceof ClosedCaptionOptionItem)) {
- continue;
- }
- ClosedCaptionOptionItem captionItem = (ClosedCaptionOptionItem) item;
- if (Utils.isEqualLanguage(captionItem.mLanguage, mClosedCaptionLanguage)) {
- selectedItem = captionItem;
- break;
- }
- }
- }
- if (mSelectedItem != null) {
- mSelectedItem.setChecked(false);
- }
- if (selectedItem == null && mItems.get(0) instanceof ClosedCaptionOptionItem) {
- selectedItem = (ClosedCaptionOptionItem) mItems.get(0);
- }
- if (selectedItem != null) {
- selectedItem.setChecked(true);
- }
- // We shouldn't call MainActivity.selectSubtitleTrack() here because
- // 1. Tracks are not available because video is just started at this moment.
- // 2. MainActivity will apply system settings when video's tracks are available.
- mSelectedItem = selectedItem;
- }
- mPaused = false;
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mPaused = true;
- }
-
- @Override
public void onDestroyView() {
if (mResetClosedCaption) {
getMainActivity().selectSubtitleLanguage(mClosedCaptionOption, mClosedCaptionLanguage,
@@ -172,23 +121,28 @@ public class ClosedCaptionFragment extends SideFragment {
super.onDestroyView();
}
- private String getLabel(TvTrackInfo track) {
- if (track.getLanguage() != null) {
+ private String getLabel(TvTrackInfo track, Integer trackIndex) {
+ if (track == null) {
+ return getString(R.string.closed_caption_option_item_off);
+ } else if (track.getLanguage() != null) {
return new Locale(track.getLanguage()).getDisplayName();
}
- return getString(R.string.default_language);
+ return getString(R.string.closed_caption_unknown_language, trackIndex + 1);
}
private class ClosedCaptionOptionItem extends RadioButtonItem {
private final int mOption;
private final String mTrackId;
- private final String mLanguage;
- private ClosedCaptionOptionItem(String title, int option, String trackId, String language) {
- super(title);
- mOption = option;
- mTrackId = trackId;
- mLanguage = language;
+ private ClosedCaptionOptionItem(TvTrackInfo track, Integer trackIndex) {
+ super(getLabel(track, trackIndex));
+ if (track == null) {
+ mOption = CaptionSettings.OPTION_OFF;
+ mTrackId = null;
+ } else {
+ mOption = CaptionSettings.OPTION_ON;
+ mTrackId = track.getId();
+ }
}
@Override
diff --git a/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java b/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java
index 7613a9a2..c2746937 100644
--- a/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java
+++ b/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java
@@ -23,9 +23,12 @@ import android.widget.TextView;
import com.android.tv.R;
public abstract class CompoundButtonItem extends Item {
+ private static int sDefaultMaxLine = 0;
+
private final String mCheckedTitle;
private final String mUncheckedTitle;
private final String mDescription;
+ private final int mMaxLine;
private boolean mChecked;
private TextView mTextView;
private CompoundButton mCompoundButton;
@@ -38,6 +41,15 @@ public abstract class CompoundButtonItem extends Item {
mCheckedTitle = checkedTitle;
mUncheckedTitle = uncheckedTitle;
mDescription = description;
+ mMaxLine = 0;
+ }
+
+ public CompoundButtonItem(String checkedTitle, String uncheckedTitle, String description,
+ int maxLine) {
+ mCheckedTitle = checkedTitle;
+ mUncheckedTitle = uncheckedTitle;
+ mDescription = description;
+ mMaxLine = maxLine;
}
protected abstract int getCompoundButtonId();
@@ -57,6 +69,15 @@ public abstract class CompoundButtonItem extends Item {
mTextView = (TextView) view.findViewById(getTitleViewId());
TextView descriptionView = (TextView) view.findViewById(getDescriptionViewId());
if (mDescription != null) {
+ if (mMaxLine != 0) {
+ descriptionView.setMaxLines(mMaxLine);
+ } else {
+ if (sDefaultMaxLine == 0) {
+ sDefaultMaxLine = view.getContext().getResources()
+ .getInteger(R.integer.option_item_description_max_lines);
+ }
+ descriptionView.setMaxLines(sDefaultMaxLine);
+ }
descriptionView.setVisibility(View.VISIBLE);
descriptionView.setText(mDescription);
} else {
diff --git a/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java b/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
index 9cc54ed2..297e69d9 100644
--- a/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
+++ b/src/com/android/tv/ui/sidepanel/CustomizeChannelListFragment.java
@@ -16,6 +16,8 @@
package com.android.tv.ui.sidepanel;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.media.tv.TvContract.Channels;
import android.os.Bundle;
import android.support.v17.leanback.widget.VerticalGridView;
@@ -27,6 +29,7 @@ import android.widget.TextView;
import com.android.tv.MainActivity;
import com.android.tv.R;
+import com.android.tv.common.SharedPreferencesUtils;
import com.android.tv.data.Channel;
import com.android.tv.data.ChannelNumber;
import com.android.tv.ui.OnRepeatedKeyInterceptListener;
@@ -36,39 +39,38 @@ import com.android.tv.util.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.List;
import java.util.Iterator;
+import java.util.List;
public class CustomizeChannelListFragment extends SideFragment {
private static final int GROUP_BY_SOURCE = 0;
private static final int GROUP_BY_HD_SD = 1;
private static final String TRACKER_LABEL = "customize channel list";
- private final List<Channel> mChannels = new ArrayList<>();
- private final long mInitialChannelId;
+ private static final String PREF_KEY_GROUP_SETTINGS = "pref_key_group_settigns";
+ private final List<Channel> mChannels = new ArrayList<>();
+ private long mInitialChannelId = Channel.INVALID_ID;
private long mLastFocusedChannelId = Channel.INVALID_ID;
- private int mGroupingType = GROUP_BY_SOURCE;
+ private static Integer sGroupingType;
private TvInputManagerHelper mInputManager;
private Channel.DefaultComparator mChannelComparator;
private boolean mGroupByFragmentRunning;
private final List<Item> mItems = new ArrayList<>();
- public CustomizeChannelListFragment() {
- this(Channel.INVALID_ID);
- }
-
- public CustomizeChannelListFragment(long initialChannelId) {
- mInitialChannelId = initialChannelId;
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInputManager = getMainActivity().getTvInputManagerHelper();
+ mInitialChannelId = getMainActivity().getCurrentChannelId();
mChannelComparator = new Channel.DefaultComparator(getActivity(), mInputManager);
+ if (sGroupingType == null) {
+ SharedPreferences sharedPreferences = getContext().getSharedPreferences(
+ SharedPreferencesUtils.SHARED_PREF_UI_SETTINGS, Context.MODE_PRIVATE);
+ sGroupingType = sharedPreferences.getInt(PREF_KEY_GROUP_SETTINGS, GROUP_BY_SOURCE);
+ }
}
@Override
@@ -128,13 +130,16 @@ public class CustomizeChannelListFragment extends SideFragment {
@Override
public void onDestroyView() {
getChannelDataManager().applyUpdatedValuesToDb();
- if (!mGroupByFragmentRunning) {
- getMainActivity().endShrunkenTvView();
- }
super.onDestroyView();
}
@Override
+ public void onDestroy() {
+ super.onDestroy();
+ getMainActivity().endShrunkenTvView();
+ }
+
+ @Override
protected String getTitle() {
return getString(R.string.side_panel_title_edit_channels_for_an_input);
}
@@ -149,7 +154,7 @@ public class CustomizeChannelListFragment extends SideFragment {
mItems.clear();
mChannels.clear();
mChannels.addAll(getChannelDataManager().getChannelList());
- if (mGroupingType == GROUP_BY_SOURCE) {
+ if (sGroupingType == GROUP_BY_SOURCE) {
addItemForGroupBySource(mItems);
} else {
// GROUP_BY_HD_SD
@@ -321,6 +326,49 @@ public class CustomizeChannelListFragment extends SideFragment {
}
}
+ public static class GroupByFragment extends SideFragment {
+ @Override
+ protected String getTitle() {
+ return getString(R.string.side_panel_title_group_by);
+ }
+ @Override
+ public String getTrackerLabel() {
+ return GroupBySubMenu.TRACKER_LABEL;
+ }
+
+ @Override
+ protected List<Item> getItemList() {
+ List<Item> items = new ArrayList<>();
+ items.add(new RadioButtonItem(
+ getString(R.string.edit_channels_group_by_sources)) {
+ @Override
+ protected void onSelected() {
+ super.onSelected();
+ setGroupingType(GROUP_BY_SOURCE);
+ closeFragment();
+ }
+ });
+ items.add(new RadioButtonItem(
+ getString(R.string.edit_channels_group_by_hd_sd)) {
+ @Override
+ protected void onSelected() {
+ super.onSelected();
+ setGroupingType(GROUP_BY_HD_SD);
+ closeFragment();
+ }
+ });
+ ((RadioButtonItem) items.get(sGroupingType)).setChecked(true);
+ return items;
+ }
+
+ private void setGroupingType(int groupingType) {
+ sGroupingType = groupingType;
+ SharedPreferences sharedPreferences = getContext().getSharedPreferences(
+ SharedPreferencesUtils.SHARED_PREF_UI_SETTINGS, Context.MODE_PRIVATE);
+ sharedPreferences.edit().putInt(PREF_KEY_GROUP_SETTINGS, groupingType).apply();
+ }
+ }
+
private class GroupBySubMenu extends SubMenuItem {
private static final String TRACKER_LABEL = "Group by";
public GroupBySubMenu(String description) {
@@ -330,41 +378,7 @@ public class CustomizeChannelListFragment extends SideFragment {
@Override
protected SideFragment getFragment() {
- return new SideFragment() {
- @Override
- protected String getTitle() {
- return getString(R.string.side_panel_title_group_by);
- }
- @Override
- public String getTrackerLabel() {
- return GroupBySubMenu.TRACKER_LABEL;
- }
-
- @Override
- protected List<Item> getItemList() {
- List<Item> items = new ArrayList<>();
- items.add(new RadioButtonItem(
- getString(R.string.edit_channels_group_by_sources)) {
- @Override
- protected void onSelected() {
- super.onSelected();
- mGroupingType = GROUP_BY_SOURCE;
- closeFragment();
- }
- });
- items.add(new RadioButtonItem(
- getString(R.string.edit_channels_group_by_hd_sd)) {
- @Override
- protected void onSelected() {
- super.onSelected();
- mGroupingType = GROUP_BY_HD_SD;
- closeFragment();
- }
- });
- ((RadioButtonItem) items.get(mGroupingType)).setChecked(true);
- return items;
- }
- };
+ return new GroupByFragment();
}
@Override
diff --git a/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java b/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
index 0d189cca..f633fa5a 100644
--- a/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
+++ b/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
@@ -18,8 +18,6 @@ package com.android.tv.ui.sidepanel;
import android.accounts.Account;
import android.app.Activity;
-import android.app.ApplicationErrorReport;
-import android.content.Intent;
import android.support.annotation.NonNull;
import android.util.Log;
import android.widget.Toast;
@@ -27,9 +25,11 @@ import android.widget.Toast;
import com.android.tv.R;
import com.android.tv.TvApplication;
import com.android.tv.common.BuildConfig;
+import com.android.tv.common.feature.CommonFeatures;
import com.android.tv.data.epg.EpgFetcher;
import com.android.tv.experiments.Experiments;
import com.android.tv.tuner.TunerPreferences;
+import com.android.tv.util.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -54,7 +54,15 @@ public class DeveloperOptionFragment extends SideFragment {
@Override
protected List<Item> getItemList() {
List<Item> items = new ArrayList<>();
- if (BuildConfig.ENG) {
+ if (CommonFeatures.DVR.isEnabled(getContext())) {
+ items.add(new ActionItem(getString(R.string.dev_item_dvr_history)) {
+ @Override
+ protected void onSelected() {
+ getMainActivity().getOverlayManager().showDvrHistoryDialog();
+ }
+ });
+ }
+ if (Utils.isDeveloper()) {
items.add(new ActionItem(getString(R.string.dev_item_watch_history)) {
@Override
protected void onSelected() {
@@ -62,18 +70,6 @@ public class DeveloperOptionFragment extends SideFragment {
}
});
}
- items.add(new ActionItem(getString(R.string.dev_item_send_feedback)) {
- @Override
- protected void onSelected() {
- Intent intent = new Intent(Intent.ACTION_APP_ERROR);
- ApplicationErrorReport report = new ApplicationErrorReport();
- report.packageName = report.processName = getContext().getPackageName();
- report.time = System.currentTimeMillis();
- report.type = ApplicationErrorReport.TYPE_NONE;
- intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
- startActivityForResult(intent, 0);
- }
- });
items.add(new SwitchItem(getString(R.string.dev_item_store_ts_on),
getString(R.string.dev_item_store_ts_off),
getString(R.string.dev_item_store_ts_description)) {
@@ -89,13 +85,18 @@ public class DeveloperOptionFragment extends SideFragment {
TunerPreferences.setStoreTsStream(getContext(), isChecked());
}
});
+ if (Utils.isDeveloper()) {
+ items.add(
+ new ActionItem(getString(R.string.dev_item_show_performance_monitor_log)) {
+ @Override
+ protected void onSelected() {
+ TvApplication.getSingletons(getContext())
+ .getPerformanceMonitor()
+ .startPerformanceMonitorEventDebugActivity(getContext());
+ }
+ });
+ }
return items;
}
-
- /** True if there is the dev options menu */
- public static boolean shouldShow() {
- return Experiments.ENABLE_DEVELOPER_FEATURES.get() || BuildConfig.ENG;
- }
-
-}
+} \ No newline at end of file
diff --git a/src/com/android/tv/ui/sidepanel/Item.java b/src/com/android/tv/ui/sidepanel/Item.java
index 00f16427..4e47e75b 100644
--- a/src/com/android/tv/ui/sidepanel/Item.java
+++ b/src/com/android/tv/ui/sidepanel/Item.java
@@ -24,6 +24,7 @@ import android.view.ViewGroup;
public abstract class Item {
private View mItemView;
private boolean mEnabled = true;
+ private boolean mClickable = true;
public void setEnabled(boolean enabled) {
if (mEnabled != enabled) {
@@ -35,6 +36,16 @@ public abstract class Item {
}
/**
+ * Sets the item to be clickable or not.
+ */
+ public void setClickable(boolean clickable) {
+ mClickable = clickable;
+ if (mItemView != null) {
+ mItemView.setClickable(clickable);
+ }
+ }
+
+ /**
* Returns whether this item is enabled.
*/
public boolean isEnabled() {
@@ -64,6 +75,7 @@ public abstract class Item {
*/
protected void onUpdate() {
setEnabledInternal(mItemView, mEnabled);
+ mItemView.setClickable(mClickable);
}
protected abstract void onSelected();
diff --git a/src/com/android/tv/ui/sidepanel/PipInputSelectorFragment.java b/src/com/android/tv/ui/sidepanel/PipInputSelectorFragment.java
deleted file mode 100644
index dec017a8..00000000
--- a/src/com/android/tv/ui/sidepanel/PipInputSelectorFragment.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.ui.sidepanel;
-
-import android.media.tv.TvInputInfo;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.tv.R;
-import com.android.tv.util.PipInputManager;
-import com.android.tv.util.PipInputManager.PipInput;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-public class PipInputSelectorFragment extends SideFragment {
- private static final String TAG = "PipInputSelector";
- private static final String TRACKER_LABEL = "PIP input source";
-
- private final List<Item> mInputItems = new ArrayList<>();
- private PipInputManager mPipInputManager;
- private PipInput mInitialPipInput;
- private boolean mSelected;
-
- private final PipInputManager.Listener mPipInputListener = new PipInputManager.Listener() {
- @Override
- public void onPipInputStateUpdated() {
- notifyDataSetChanged();
- }
-
- @Override
- public void onPipInputListUpdated() {
- refreshInputList();
- setItems(mInputItems);
- }
- };
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- mPipInputManager = getMainActivity().getPipInputManager();
- mPipInputManager.addListener(mPipInputListener);
- getMainActivity().startShrunkenTvView(false, false);
- return super.onCreateView(inflater, container, savedInstanceState);
- }
-
- @Override
- public void onStart() {
- super.onStart();
- mInitialPipInput = mPipInputManager.getPipInput(getMainActivity().getPipChannel());
- if (mInitialPipInput == null) {
- Log.w(TAG, "PIP should be on");
- closeFragment();
- }
- int count = 0;
- for (Item item : mInputItems) {
- InputItem inputItem = (InputItem) item;
- if (Objects.equals(inputItem.mPipInput, mInitialPipInput)) {
- setSelectedPosition(count);
- break;
- }
- ++count;
- }
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- mPipInputManager.removeListener(mPipInputListener);
- if (!mSelected) {
- getMainActivity().tuneToChannelForPip(mInitialPipInput.getChannel());
- }
- getMainActivity().endShrunkenTvView();
- }
-
- @Override
- protected String getTitle() {
- return getString(R.string.side_panel_title_pip_input_source);
- }
-
- @Override
- public String getTrackerLabel() {
- return TRACKER_LABEL;
- }
-
- @Override
- protected List<Item> getItemList() {
- refreshInputList();
- return mInputItems;
- }
-
- private void refreshInputList() {
- mInputItems.clear();
- for (PipInput input : mPipInputManager.getPipInputList(false)) {
- mInputItems.add(new InputItem(input));
- }
- }
-
- private class InputItem extends RadioButtonItem {
- private final PipInput mPipInput;
-
- private InputItem(PipInput input) {
- super(input.getLongLabel());
- mPipInput = input;
- setEnabled(isAvailable());
- }
-
- @Override
- protected void onUpdate() {
- super.onUpdate();
- setEnabled(mPipInput.isAvailable());
- setChecked(mPipInput == mInitialPipInput);
- }
-
- @Override
- protected void onFocused() {
- super.onFocused();
- if (isEnabled()) {
- getMainActivity().tuneToChannelForPip(mPipInput.getChannel());
- }
- }
-
- @Override
- protected void onSelected() {
- super.onSelected();
- if (isEnabled()) {
- mSelected = true;
- closeFragment();
- }
- }
-
- private boolean isAvailable() {
- if (!mPipInput.isAvailable()) {
- return false;
- }
-
- // If this input shares the same parent with the current main input, you cannot select
- // it. (E.g. two HDMI CEC devices that are connected to HDMI port 1 through an A/V
- // receiver.)
- PipInput pipInput = mPipInputManager.getPipInput(getMainActivity().getCurrentChannel());
- if (pipInput == null) {
- return false;
- }
- TvInputInfo mainInputInfo = pipInput.getInputInfo();
- TvInputInfo pipInputInfo = mPipInput.getInputInfo();
- return mainInputInfo == null || pipInputInfo == null
- || !TextUtils.equals(mainInputInfo.getId(), pipInputInfo.getId())
- && !TextUtils.equals(mainInputInfo.getParentId(), pipInputInfo.getParentId());
- }
- }
-}
diff --git a/src/com/android/tv/ui/sidepanel/SettingsFragment.java b/src/com/android/tv/ui/sidepanel/SettingsFragment.java
index e8033a22..6a5b510c 100644
--- a/src/com/android/tv/ui/sidepanel/SettingsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/SettingsFragment.java
@@ -16,18 +16,25 @@
package com.android.tv.ui.sidepanel;
+import static com.android.tv.Features.TUNER;
+
+import android.app.ApplicationErrorReport;
+import android.content.Intent;
+import android.media.tv.TvInputInfo;
import android.view.View;
import android.widget.Toast;
import com.android.tv.MainActivity;
import com.android.tv.R;
import com.android.tv.TvApplication;
+import com.android.tv.customization.TvCustomizationManager;
import com.android.tv.dialog.PinDialogFragment;
-import com.android.tv.dialog.WebDialogFragment;
-import com.android.tv.license.LicenseUtils;
-import com.android.tv.ui.sidepanel.parentalcontrols.ParentalControlsFragment;
+import com.android.tv.license.LicenseSideFragment;
+import com.android.tv.license.Licenses;
+import com.android.tv.tuner.TunerPreferences;
import com.android.tv.util.PermissionUtils;
import com.android.tv.util.SetupUtils;
+import com.android.tv.util.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -38,33 +45,6 @@ import java.util.List;
public class SettingsFragment extends SideFragment {
private static final String TRACKER_LABEL = "settings";
- private final long mCurrentChannelId;
-
- public SettingsFragment(long currentChannelId) {
- mCurrentChannelId = currentChannelId;
- }
-
- /**
- * Opens a dialog showing open source licenses.
- */
- public static final class LicenseActionItem extends ActionItem {
- public final static String DIALOG_TAG = LicenseActionItem.class.getSimpleName();
- public static final String TRACKER_LABEL = "Open Source Licenses";
- private final MainActivity mMainActivity;
-
- public LicenseActionItem(MainActivity mainActivity) {
- super(mainActivity.getString(R.string.settings_menu_licenses));
- mMainActivity = mainActivity;
- }
-
- @Override
- protected void onSelected() {
- WebDialogFragment dialog = WebDialogFragment.newInstance(LicenseUtils.LICENSE_FILE,
- mMainActivity.getString(R.string.dialog_title_licenses), TRACKER_LABEL);
- mMainActivity.getOverlayManager().showDialogFragment(DIALOG_TAG, dialog, false);
- }
- }
-
@Override
protected String getTitle() {
return getResources().getString(R.string.side_panel_title_settings);
@@ -80,11 +60,11 @@ public class SettingsFragment extends SideFragment {
List<Item> items = new ArrayList<>();
final Item customizeChannelListItem = new SubMenuItem(
getString(R.string.settings_channel_source_item_customize_channels),
- getString(R.string.settings_channel_source_item_customize_channels_description), 0,
+ getString(R.string.settings_channel_source_item_customize_channels_description),
getMainActivity().getOverlayManager().getSideFragmentManager()) {
@Override
protected SideFragment getFragment() {
- return new CustomizeChannelListFragment(mCurrentChannelId);
+ return new CustomizeChannelListFragment();
}
@Override
@@ -122,25 +102,11 @@ public class SettingsFragment extends SideFragment {
: R.string.option_toggle_parental_controls_off)) {
@Override
protected void onSelected() {
- final MainActivity tvActivity = getMainActivity();
- final SideFragmentManager sideFragmentManager = tvActivity.getOverlayManager()
- .getSideFragmentManager();
- sideFragmentManager.hideSidePanel(true);
- PinDialogFragment fragment = new PinDialogFragment(
- PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN,
- new PinDialogFragment.ResultListener() {
- @Override
- public void done(boolean success) {
- if (success) {
- sideFragmentManager
- .show(new ParentalControlsFragment(), false);
- sideFragmentManager.showSidePanel(true);
- } else {
- sideFragmentManager.hideAll(false);
- }
- }
- });
- tvActivity.getOverlayManager()
+ getMainActivity().getOverlayManager()
+ .getSideFragmentManager().hideSidePanel(true);
+ PinDialogFragment fragment = PinDialogFragment
+ .create(PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN);
+ getMainActivity().getOverlayManager()
.showDialogFragment(PinDialogFragment.DIALOG_TAG, fragment, true);
}
});
@@ -149,12 +115,73 @@ public class SettingsFragment extends SideFragment {
// But, we may be able to turn on channel lock feature regardless of the permission.
// It's TBD.
}
- if (LicenseUtils.hasLicenses(activity.getAssets())) {
- items.add(new LicenseActionItem(activity));
+ boolean showTrickplaySetting = false;
+ if (TUNER.isEnabled(getContext())) {
+ for (TvInputInfo inputInfo : TvApplication.getSingletons(getContext())
+ .getTvInputManagerHelper().getTvInputInfos(true, true)) {
+ if (Utils.isInternalTvInput(getContext(), inputInfo.getId())) {
+ showTrickplaySetting = true;
+ break;
+ }
+ }
+ if (showTrickplaySetting) {
+ showTrickplaySetting =
+ TvCustomizationManager.getTrickplayMode(getContext())
+ == TvCustomizationManager.TRICKPLAY_MODE_ENABLED;
+ }
+ }
+ if (showTrickplaySetting) {
+ items.add(
+ new SwitchItem(getString(R.string.settings_trickplay),
+ getString(R.string.settings_trickplay),
+ getString(R.string.settings_trickplay_description),
+ getResources().getInteger(R.integer.trickplay_description_max_lines)) {
+ @Override
+ protected void onUpdate() {
+ super.onUpdate();
+ boolean enabled = TunerPreferences.getTrickplaySetting(getContext())
+ != TunerPreferences.TRICKPLAY_SETTING_DISABLED;
+ setChecked(enabled);
+ }
+
+ @Override
+ protected void onSelected() {
+ super.onSelected();
+ @TunerPreferences.TrickplaySetting int setting =
+ isChecked() ? TunerPreferences.TRICKPLAY_SETTING_ENABLED
+ : TunerPreferences.TRICKPLAY_SETTING_DISABLED;
+ TunerPreferences.setTrickplaySetting(getContext(), setting);
+ }
+ });
+ }
+ items.add(new ActionItem(getString(R.string.settings_send_feedback)) {
+ @Override
+ protected void onSelected() {
+ Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+ ApplicationErrorReport report = new ApplicationErrorReport();
+ report.packageName = report.processName = getContext().getPackageName();
+ report.time = System.currentTimeMillis();
+ report.type = ApplicationErrorReport.TYPE_NONE;
+ intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
+ startActivityForResult(intent, 0);
+ }
+ });
+ if (Licenses.hasLicenses(getContext())) {
+ items.add(
+ new SubMenuItem(
+ getString(R.string.settings_menu_licenses),
+ getMainActivity().getOverlayManager().getSideFragmentManager()) {
+ @Override
+ protected SideFragment getFragment() {
+ return new LicenseSideFragment();
+ }
+ });
}
// Show version.
- items.add(new SimpleItem(getString(R.string.settings_menu_version),
- ((TvApplication) activity.getApplicationContext()).getVersionName()));
+ SimpleActionItem version = new SimpleActionItem(getString(R.string.settings_menu_version),
+ ((TvApplication) activity.getApplicationContext()).getVersionName());
+ version.setClickable(false);
+ items.add(version);
return items;
}
diff --git a/src/com/android/tv/ui/sidepanel/SideFragment.java b/src/com/android/tv/ui/sidepanel/SideFragment.java
index 8df56cd2..6bd921a2 100644
--- a/src/com/android/tv/ui/sidepanel/SideFragment.java
+++ b/src/com/android/tv/ui/sidepanel/SideFragment.java
@@ -26,32 +26,36 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.tv.MainActivity;
import com.android.tv.R;
import com.android.tv.TvApplication;
-import com.android.tv.analytics.DurationTimer;
+import com.android.tv.util.DurationTimer;
import com.android.tv.analytics.HasTrackerLabel;
import com.android.tv.analytics.Tracker;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.ProgramDataManager;
import com.android.tv.util.SystemProperties;
+import com.android.tv.util.ViewCache;
import java.util.List;
-public abstract class SideFragment extends Fragment implements HasTrackerLabel {
+public abstract class SideFragment<T extends Item> extends Fragment implements HasTrackerLabel {
public static final int INVALID_POSITION = -1;
- private static final int RECYCLED_VIEW_POOL_SIZE = 7;
- private static final int[] PRELOADED_VIEW_IDS = {
+ private static final int PRELOAD_VIEW_SIZE = 7;
+ private static final int[] PRELOAD_VIEW_IDS = {
R.layout.option_item_radio_button,
R.layout.option_item_channel_lock,
R.layout.option_item_check_box,
- R.layout.option_item_channel_check
+ R.layout.option_item_channel_check,
+ R.layout.option_item_action
};
- private static RecyclerView.RecycledViewPool sRecycledViewPool;
+ private static RecyclerView.RecycledViewPool sRecycledViewPool =
+ new RecyclerView.RecycledViewPool();
private VerticalGridView mListView;
private ItemAdapter mAdapter;
@@ -89,14 +93,8 @@ public abstract class SideFragment extends Fragment implements HasTrackerLabel {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- if (sRecycledViewPool == null) {
- // sRecycledViewPool should be initialized by calling preloadRecycledViews()
- // before the entering animation of this fragment starts,
- // because it takes long time and if it is called after the animation starts (e.g. here)
- // it can affect the animation.
- throw new IllegalStateException("The RecyclerView pool has not been initialized.");
- }
- View view = inflater.inflate(getFragmentLayoutResourceId(), container, false);
+ View view = ViewCache.getInstance().getOrCreateView(
+ inflater, getFragmentLayoutResourceId(), container);
TextView textView = (TextView) view.findViewById(R.id.side_panel_title);
textView.setText(getTitle());
@@ -158,7 +156,7 @@ public abstract class SideFragment extends Fragment implements HasTrackerLabel {
return mListView.getSelectedPosition();
}
- public void setItems(List<Item> items) {
+ public void setItems(List<T> items) {
mAdapter.reset(items);
}
@@ -229,56 +227,50 @@ public abstract class SideFragment extends Fragment implements HasTrackerLabel {
protected abstract String getTitle();
@Override
public abstract String getTrackerLabel();
- protected abstract List<Item> getItemList();
+ protected abstract List<T> getItemList();
public interface SideFragmentListener {
void onSideFragmentViewDestroyed();
}
/**
- * Preloads the view holders.
+ * Preloads the item views.
*/
- public static void preloadRecycledViews(Context context) {
- if (sRecycledViewPool != null) {
- return;
- }
- sRecycledViewPool = new RecyclerView.RecycledViewPool();
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- for (int id : PRELOADED_VIEW_IDS) {
- sRecycledViewPool.setMaxRecycledViews(id, RECYCLED_VIEW_POOL_SIZE);
- for (int j = 0; j < RECYCLED_VIEW_POOL_SIZE; ++j) {
- ItemAdapter.ViewHolder viewHolder = new ItemAdapter.ViewHolder(
- inflater.inflate(id, null, false));
- sRecycledViewPool.putRecycledView(viewHolder);
- }
+ public static void preloadItemViews(Context context) {
+ ViewCache.getInstance().putView(
+ context, R.layout.option_fragment, new FrameLayout(context), 1);
+ VerticalGridView fakeParent = new VerticalGridView(context);
+ for (int id : PRELOAD_VIEW_IDS) {
+ sRecycledViewPool.setMaxRecycledViews(id, PRELOAD_VIEW_SIZE);
+ ViewCache.getInstance().putView(context, id, fakeParent, PRELOAD_VIEW_SIZE);
}
}
/**
- * Releases the pre-loaded view holders.
+ * Releases the recycled view pool.
*/
- public static void releasePreloadedRecycledViews() {
- sRecycledViewPool = null;
+ public static void releaseRecycledViewPool() {
+ sRecycledViewPool.clear();
}
- private static class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {
+ private static class ItemAdapter<T extends Item> extends RecyclerView.Adapter<ViewHolder> {
private final LayoutInflater mLayoutInflater;
- private List<Item> mItems;
+ private List<T> mItems;
- private ItemAdapter(LayoutInflater layoutInflater, List<Item> items) {
+ private ItemAdapter(LayoutInflater layoutInflater, List<T> items) {
mLayoutInflater = layoutInflater;
mItems = items;
}
- private void reset(List<Item> items) {
+ private void reset(List<T> items) {
mItems = items;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- return new ViewHolder(mLayoutInflater.inflate(viewType, parent, false));
+ View view = ViewCache.getInstance().getOrCreateView(mLayoutInflater, viewType, parent);
+ return new ViewHolder(view);
}
@Override
@@ -301,11 +293,11 @@ public abstract class SideFragment extends Fragment implements HasTrackerLabel {
return mItems == null ? 0 : mItems.size();
}
- private Item getItem(int position) {
+ private T getItem(int position) {
return mItems.get(position);
}
- private void clearRadioGroup(Item item) {
+ private void clearRadioGroup(T item) {
int position = mItems.indexOf(item);
for (int i = position - 1; i >= 0; --i) {
if ((item = mItems.get(i)) instanceof RadioButtonItem) {
@@ -322,55 +314,57 @@ public abstract class SideFragment extends Fragment implements HasTrackerLabel {
}
}
}
+ }
- private static class ViewHolder extends RecyclerView.ViewHolder
- implements View.OnClickListener, View.OnFocusChangeListener {
- private ItemAdapter mAdapter;
- public Item mItem;
+ private static class ViewHolder extends RecyclerView.ViewHolder
+ implements View.OnClickListener, View.OnFocusChangeListener {
+ private ItemAdapter mAdapter;
+ public Item mItem;
- private ViewHolder(View view) {
- super(view);
- itemView.setOnClickListener(this);
- itemView.setOnFocusChangeListener(this);
- }
+ private ViewHolder(View view) {
+ super(view);
+ itemView.setOnClickListener(this);
+ itemView.setOnFocusChangeListener(this);
+ }
- public void onBind(ItemAdapter adapter, Item item) {
- mAdapter = adapter;
- mItem = item;
- mItem.onBind(itemView);
- mItem.onUpdate();
- }
+ public void onBind(ItemAdapter adapter, Item item) {
+ mAdapter = adapter;
+ mItem = item;
+ mItem.onBind(itemView);
+ mItem.onUpdate();
+ }
- public void onUnbind() {
- mItem.onUnbind();
- mItem = null;
- mAdapter = null;
- }
+ public void onUnbind() {
+ mItem.onUnbind();
+ mItem = null;
+ mAdapter = null;
+ }
- @Override
- public void onClick(View view) {
- if (mItem instanceof RadioButtonItem) {
- mAdapter.clearRadioGroup(mItem);
- }
- if (view.getBackground() instanceof RippleDrawable) {
- view.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (mItem != null) {
- mItem.onSelected();
+ @Override
+ public void onClick(View view) {
+ if (mItem instanceof RadioButtonItem) {
+ mAdapter.clearRadioGroup(mItem);
+ }
+ if (view.getBackground() instanceof RippleDrawable) {
+ view.postDelayed(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (mItem != null) {
+ mItem.onSelected();
+ }
}
- }
- }, view.getResources().getInteger(R.integer.side_panel_ripple_anim_duration));
- } else {
- mItem.onSelected();
- }
+ },
+ view.getResources().getInteger(R.integer.side_panel_ripple_anim_duration));
+ } else {
+ mItem.onSelected();
}
+ }
- @Override
- public void onFocusChange(View view, boolean focusGained) {
- if (focusGained) {
- mItem.onFocused();
- }
+ @Override
+ public void onFocusChange(View view, boolean focusGained) {
+ if (focusGained) {
+ mItem.onFocused();
}
}
}
diff --git a/src/com/android/tv/ui/sidepanel/SideFragmentManager.java b/src/com/android/tv/ui/sidepanel/SideFragmentManager.java
index 553cd9d7..d02d3fb7 100644
--- a/src/com/android/tv/ui/sidepanel/SideFragmentManager.java
+++ b/src/com/android/tv/ui/sidepanel/SideFragmentManager.java
@@ -24,6 +24,7 @@ import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Handler;
import android.view.View;
+import android.view.ViewTreeObserver;
import com.android.tv.R;
@@ -34,6 +35,7 @@ public class SideFragmentManager {
private final FragmentManager mFragmentManager;
private final Runnable mPreShowRunnable;
private final Runnable mPostHideRunnable;
+ private ViewTreeObserver.OnGlobalLayoutListener mShowOnGlobalLayoutListener;
// To get the count reliably while using popBackStack(),
// instead of using getBackStackEntryCount() with popBackStackImmediate().
@@ -99,17 +101,10 @@ public class SideFragmentManager {
* Shows the given {@link SideFragment}.
*/
public void show(SideFragment sideFragment, boolean showEnterAnimation) {
- SideFragment.preloadRecycledViews(mActivity);
if (isHiding()) {
mHideAnimator.end();
}
boolean isFirst = (mFragmentCount == 0);
- if (isFirst) {
- if (mPreShowRunnable != null) {
- mPreShowRunnable.run();
- }
- }
-
FragmentTransaction ft = mFragmentManager.beginTransaction();
if (!isFirst) {
ft.setCustomAnimations(
@@ -123,8 +118,22 @@ public class SideFragmentManager {
mFragmentCount++;
if (isFirst) {
+ // We should wait for fragment transition and intital layouting finished to start the
+ // slide-in animation to prevent jankiness resulted by performing transition and
+ // layouting at the same time with animation.
mPanel.setVisibility(View.VISIBLE);
- mShowAnimator.start();
+ mShowOnGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ mPanel.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ mShowOnGlobalLayoutListener = null;
+ if (mPreShowRunnable != null) {
+ mPreShowRunnable.run();
+ }
+ mShowAnimator.start();
+ }
+ };
+ mPanel.getViewTreeObserver().addOnGlobalLayoutListener(mShowOnGlobalLayoutListener);
}
scheduleHideAll();
}
@@ -142,6 +151,18 @@ public class SideFragmentManager {
}
public void hideAll(boolean withAnimation) {
+ if (mShowAnimator.isStarted()) {
+ mShowAnimator.end();
+ }
+ if (mShowOnGlobalLayoutListener != null) {
+ // The show operation maybe requested but the show animator is not started yet, in this
+ // case, we show still run mPreShowRunnable.
+ mPanel.getViewTreeObserver().removeOnGlobalLayoutListener(mShowOnGlobalLayoutListener);
+ mShowOnGlobalLayoutListener = null;
+ if (mPreShowRunnable != null) {
+ mPreShowRunnable.run();
+ }
+ }
if (withAnimation) {
if (!isHiding()) {
mHideAnimator.start();
@@ -178,7 +199,6 @@ public class SideFragmentManager {
* @param withAnimation specifies if animation should be shown.
*/
public void showSidePanel(boolean withAnimation) {
- SideFragment.preloadRecycledViews(mActivity);
if (mFragmentCount == 0) {
return;
}
diff --git a/src/com/android/tv/ui/sidepanel/SimpleItem.java b/src/com/android/tv/ui/sidepanel/SimpleActionItem.java
index 52a5f13f..42553b66 100644
--- a/src/com/android/tv/ui/sidepanel/SimpleItem.java
+++ b/src/com/android/tv/ui/sidepanel/SimpleActionItem.java
@@ -19,12 +19,12 @@ package com.android.tv.ui.sidepanel;
/**
* A simple item which shows title and description.
*/
-public class SimpleItem extends ActionItem {
- public SimpleItem(String title) {
+public class SimpleActionItem extends ActionItem {
+ public SimpleActionItem(String title) {
super(title);
}
- public SimpleItem(String title, String description) {
+ public SimpleActionItem(String title, String description) {
super(title, description);
}
diff --git a/src/com/android/tv/ui/sidepanel/SubMenuItem.java b/src/com/android/tv/ui/sidepanel/SubMenuItem.java
index aa349dbd..4b0e8e2c 100644
--- a/src/com/android/tv/ui/sidepanel/SubMenuItem.java
+++ b/src/com/android/tv/ui/sidepanel/SubMenuItem.java
@@ -21,20 +21,11 @@ public abstract class SubMenuItem extends ActionItem {
private final SideFragmentManager mSideFragmentManager;
public SubMenuItem(String title, SideFragmentManager fragmentManager) {
- this(title, null, 0, fragmentManager);
+ this(title, null, fragmentManager);
}
public SubMenuItem(String title, String description, SideFragmentManager fragmentManager) {
- this(title, description, 0, fragmentManager);
- }
-
- public SubMenuItem(String title, int iconId, SideFragmentManager fragmentManager) {
- this(title, null, iconId, fragmentManager);
- }
-
- public SubMenuItem(String title, String description, int iconId,
- SideFragmentManager fragmentManager) {
- super(title, description, iconId);
+ super(title, description);
mSideFragmentManager = fragmentManager;
}
diff --git a/src/com/android/tv/ui/sidepanel/SwitchItem.java b/src/com/android/tv/ui/sidepanel/SwitchItem.java
index ef9966a5..06591b62 100644
--- a/src/com/android/tv/ui/sidepanel/SwitchItem.java
+++ b/src/com/android/tv/ui/sidepanel/SwitchItem.java
@@ -31,6 +31,11 @@ public class SwitchItem extends CompoundButtonItem {
super(checkedTitle, uncheckedTitle, description);
}
+ public SwitchItem(String checkedTitle, String uncheckedTitle, String description,
+ int maxLines) {
+ super(checkedTitle, uncheckedTitle, description, maxLines);
+ }
+
@Override
protected int getResourceId() {
return R.layout.option_item_switch;
diff --git a/src/com/android/tv/ui/sidepanel/parentalcontrols/ParentalControlsFragment.java b/src/com/android/tv/ui/sidepanel/parentalcontrols/ParentalControlsFragment.java
index da712924..9a4879fc 100644
--- a/src/com/android/tv/ui/sidepanel/parentalcontrols/ParentalControlsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/parentalcontrols/ParentalControlsFragment.java
@@ -130,17 +130,8 @@ public class ParentalControlsFragment extends SideFragment {
protected void onSelected() {
final MainActivity tvActivity = getMainActivity();
tvActivity.getOverlayManager().getSideFragmentManager().hideSidePanel(true);
-
- PinDialogFragment fragment =
- new PinDialogFragment(
- PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN,
- new PinDialogFragment.ResultListener() {
- @Override
- public void done(boolean success) {
- tvActivity.getOverlayManager().getSideFragmentManager()
- .showSidePanel(true);
- }
- });
+ PinDialogFragment fragment = PinDialogFragment.create(
+ PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN);
tvActivity.getOverlayManager().showDialogFragment(PinDialogFragment.DIALOG_TAG,
fragment, true);
}
diff --git a/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java b/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
index 6bc47939..7c8cecbe 100644
--- a/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/parentalcontrols/RatingsFragment.java
@@ -17,16 +17,17 @@
package com.android.tv.ui.sidepanel.parentalcontrols;
import android.graphics.drawable.Drawable;
+import android.media.tv.TvContentRating;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.SparseIntArray;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
-
import com.android.tv.MainActivity;
import com.android.tv.R;
import com.android.tv.dialog.WebDialogFragment;
+import com.android.tv.experiments.Experiments;
import com.android.tv.license.LicenseUtils;
import com.android.tv.parental.ContentRatingSystem;
import com.android.tv.parental.ContentRatingSystem.Rating;
@@ -38,7 +39,6 @@ import com.android.tv.ui.sidepanel.RadioButtonItem;
import com.android.tv.ui.sidepanel.SideFragment;
import com.android.tv.util.TvSettings;
import com.android.tv.util.TvSettings.ContentRatingLevel;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -77,6 +77,7 @@ public class RatingsFragment extends SideFragment {
private final List<RatingLevelItem> mRatingLevelItems = new ArrayList<>();
// A map from the rating system ID string to RatingItem objects.
private final Map<String, List<RatingItem>> mContentRatingSystemItemMap = new ArrayMap<>();
+ private CheckBoxItem mBlockUnratedItem;
private ParentalControlSettings mParentalControlSettings;
public static String getDescription(MainActivity tvActivity) {
@@ -102,6 +103,12 @@ public class RatingsFragment extends SideFragment {
protected List<Item> getItemList() {
List<Item> items = new ArrayList<>();
+ if (mBlockUnratedItem != null
+ && Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
+ items.add(mBlockUnratedItem);
+ items.add(new DividerItem());
+ }
+
mRatingLevelItems.clear();
for (int i = 0; i < sLevelResourceIdMap.size(); ++i) {
mRatingLevelItems.add(new RatingLevelItem(sLevelResourceIdMap.keyAt(i)));
@@ -152,6 +159,28 @@ public class RatingsFragment extends SideFragment {
super.onCreate(savedInstanceState);
mParentalControlSettings = getMainActivity().getParentalControlSettings();
mParentalControlSettings.loadRatings();
+ if (Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
+ mBlockUnratedItem =
+ new CheckBoxItem(
+ getResources().getString(R.string.option_block_unrated_programs)) {
+
+ @Override
+ protected void onUpdate() {
+ super.onUpdate();
+ setChecked(
+ mParentalControlSettings.isRatingBlocked(
+ new TvContentRating[] {TvContentRating.UNRATED}));
+ }
+
+ @Override
+ protected void onSelected() {
+ super.onSelected();
+ if (mParentalControlSettings.setUnratedBlocked(isChecked())) {
+ updateRatingLevels();
+ }
+ }
+ };
+ }
}
@Override
@@ -202,6 +231,13 @@ public class RatingsFragment extends SideFragment {
super.onSelected();
mParentalControlSettings.setContentRatingLevel(
getMainActivity().getContentRatingsManager(), mRatingLevel);
+ if (mBlockUnratedItem != null
+ && Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
+ // set checked if UNRATED is blocked, and set unchecked otherwise.
+ mBlockUnratedItem.setChecked(
+ mParentalControlSettings.isRatingBlocked(
+ new TvContentRating[] {TvContentRating.UNRATED}));
+ }
notifyItemsChanged(mRatingLevelItems.size());
}
}
@@ -302,7 +338,7 @@ public class RatingsFragment extends SideFragment {
@Override
protected void onSelected() {
getMainActivity().getOverlayManager().getSideFragmentManager()
- .show(new SubRatingsFragment(mContentRatingSystem, mRating));
+ .show(SubRatingsFragment.create(mContentRatingSystem, mRating.getName()));
}
@Override
diff --git a/src/com/android/tv/ui/sidepanel/parentalcontrols/SubRatingsFragment.java b/src/com/android/tv/ui/sidepanel/parentalcontrols/SubRatingsFragment.java
index f6612fdb..4634b74c 100644
--- a/src/com/android/tv/ui/sidepanel/parentalcontrols/SubRatingsFragment.java
+++ b/src/com/android/tv/ui/sidepanel/parentalcontrols/SubRatingsFragment.java
@@ -17,6 +17,7 @@
package com.android.tv.ui.sidepanel.parentalcontrols;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
@@ -36,13 +37,34 @@ import java.util.List;
public class SubRatingsFragment extends SideFragment {
private static final String TRACKER_LABEL = "Sub ratings";
- private final ContentRatingSystem mContentRatingSystem;
- private final Rating mRating;
+ private static final String ARGS_CONTENT_RATING_SYSTEM_ID = "args_content_rating_system_id";
+ private static final String ARGS_RATING_NAME = "args_rating_name";
+
+ private ContentRatingSystem mContentRatingSystem;
+ private Rating mRating;
private final List<SubRatingItem> mSubRatingItems = new ArrayList<>();
- public SubRatingsFragment(ContentRatingSystem contentRatingSystem, Rating rating) {
- mContentRatingSystem = contentRatingSystem;
- mRating = rating;
+ public static SubRatingsFragment create(ContentRatingSystem contentRatingSystem,
+ String ratingName) {
+ SubRatingsFragment fragment = new SubRatingsFragment();
+ Bundle args = new Bundle();
+ args.putString(ARGS_CONTENT_RATING_SYSTEM_ID, contentRatingSystem.getId());
+ args.putString(ARGS_RATING_NAME, ratingName);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContentRatingSystem = getMainActivity().getContentRatingsManager()
+ .getContentRatingSystem(getArguments().getString(ARGS_CONTENT_RATING_SYSTEM_ID));
+ if (mContentRatingSystem != null) {
+ mRating = mContentRatingSystem.getRating(getArguments().getString(ARGS_RATING_NAME));
+ }
+ if (mRating == null) {
+ closeFragment();
+ }
}
@Override