1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.settings.device.displaysound;
18 
19 import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_CLASSIC;
20 import static com.android.tv.settings.util.InstrumentationUtils.logToggleInteracted;
21 
22 import android.app.tvsettings.TvSettingsEnums;
23 import android.content.Context;
24 import android.os.Bundle;
25 import android.provider.Settings;
26 
27 import androidx.annotation.Keep;
28 import androidx.annotation.VisibleForTesting;
29 import androidx.preference.Preference;
30 import androidx.preference.PreferenceGroup;
31 
32 import com.android.tv.settings.R;
33 import com.android.tv.settings.RadioPreference;
34 import com.android.tv.settings.SettingsPreferenceFragment;
35 import com.android.tv.settings.overlay.FlavorUtils;
36 
37 /**
38  * This Fragment is responsible for allowing the user to express a preference for matching the
39  * display frame rate to to the frame rate of a video being played.
40  */
41 @Keep
42 public class MatchContentFrameRateFragment extends SettingsPreferenceFragment {
43 
44     private static final String KEY_MATCH_CONTENT_FRAME_RATE = "match_content_frame_rate_option";
45 
46     private static final String KEY_MATCH_CONTENT_FRAME_RATE_SEAMLESS =
47             "match_content_frame_rate_seamless";
48     private static final String KEY_MATCH_CONTENT_FRAME_RATE_NON_SEAMLESS =
49             "match_content_frame_rate_non_seamless";
50     private static final String KEY_MATCH_CONTENT_FRAME_RATE_NEVER =
51             "match_content_frame_rate_never";
52 
53     private String mCurrentPreferenceKey;
54 
55 
56     /** @return the new instance of the class */
newInstance()57     public static MatchContentFrameRateFragment newInstance() {
58         return new MatchContentFrameRateFragment();
59     }
60 
61     @Override
onAttach(Context context)62     public void onAttach(Context context) {
63         super.onAttach(context);
64     }
65 
66     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)67     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
68         setPreferencesFromResource(R.xml.match_content_frame_rate, null);
69 
70         // Do not show sidebar info texts in case of 1 panel settings.
71         if (FlavorUtils.getFlavor(getContext()) != FLAVOR_CLASSIC) {
72             createInfoFragments();
73         }
74         mCurrentPreferenceKey = preferenceKeyFromSetting();
75         getRadioPreference(mCurrentPreferenceKey).setChecked(true);
76         getRadioPreference(mCurrentPreferenceKey).clearOtherRadioPreferences(getPreferenceGroup());
77     }
78 
79     @VisibleForTesting
getPreferenceGroup()80     PreferenceGroup getPreferenceGroup() {
81         return (PreferenceGroup) findPreference(KEY_MATCH_CONTENT_FRAME_RATE);
82     }
83 
84     @VisibleForTesting
getRadioPreference(String key)85     RadioPreference getRadioPreference(String key) {
86         return (RadioPreference) findPreference(key);
87     }
88 
89     @Override
onResume()90     public void onResume() {
91         super.onResume();
92     }
93 
94 
95     @Override
onPreferenceTreeClick(Preference preference)96     public boolean onPreferenceTreeClick(Preference preference) {
97         final String key = preference.getKey();
98         if (key == null) {
99             return super.onPreferenceTreeClick(preference);
100         }
101         if (preference instanceof RadioPreference) {
102             final RadioPreference radioPreference = (RadioPreference) preference;
103             radioPreference.setChecked(true);
104             radioPreference.clearOtherRadioPreferences(getPreferenceGroup());
105 
106             if (key != mCurrentPreferenceKey) {
107                 int newValue;
108                 switch (key) {
109                     case KEY_MATCH_CONTENT_FRAME_RATE_SEAMLESS: {
110                         newValue = Settings.Secure.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY;
111                         break;
112                     }
113                     case KEY_MATCH_CONTENT_FRAME_RATE_NON_SEAMLESS: {
114                         newValue = Settings.Secure.MATCH_CONTENT_FRAMERATE_ALWAYS;
115                         break;
116                     }
117                     case KEY_MATCH_CONTENT_FRAME_RATE_NEVER: {
118                         newValue = Settings.Secure.MATCH_CONTENT_FRAMERATE_NEVER;
119                         break;
120                     }
121                     default:
122                         throw new IllegalArgumentException(
123                                 "Unknown match content frame rate pref value"
124                                         + ": " + key);
125                 }
126 
127                 int oldValue = getCurrentSettingValue();
128                 if (newValue != oldValue) {
129                     Settings.Secure.putInt(
130                             getContext().getContentResolver(),
131                             Settings.Secure.MATCH_CONTENT_FRAME_RATE,
132                             newValue);
133                     logToggleInteracted(toggleIdFromSetting(oldValue), false);
134                     logToggleInteracted(toggleIdFromSetting(newValue), true);
135                 }
136             }
137         }
138         return super.onPreferenceTreeClick(preference);
139     }
140 
141     @Override
getPageId()142     protected int getPageId() {
143         return TvSettingsEnums.DISPLAY_SOUND_MATCH_CONTENT_FRAMERATE;
144     }
145 
getCurrentSettingValue()146     private int getCurrentSettingValue() {
147         return Settings.Secure.getInt(
148                 getContext().getContentResolver(),
149                 Settings.Secure.MATCH_CONTENT_FRAME_RATE,
150                 Settings.Secure.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY);
151     }
152 
preferenceKeyFromSetting()153     private String preferenceKeyFromSetting() {
154         int matchContentSetting = getCurrentSettingValue();
155         switch (matchContentSetting) {
156             case (Settings.Secure.MATCH_CONTENT_FRAMERATE_NEVER): {
157                 return KEY_MATCH_CONTENT_FRAME_RATE_NEVER;
158             }
159             case (Settings.Secure.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY): {
160                 return KEY_MATCH_CONTENT_FRAME_RATE_SEAMLESS;
161             }
162             case (Settings.Secure.MATCH_CONTENT_FRAMERATE_ALWAYS): {
163                 return KEY_MATCH_CONTENT_FRAME_RATE_NON_SEAMLESS;
164             }
165             default:
166                 throw new IllegalArgumentException("Unknown match content frame rate pref "
167                         + "value in stored settings");
168         }
169     }
170 
toggleIdFromSetting(int matchContentSetting)171     private int toggleIdFromSetting(int matchContentSetting) {
172         switch (matchContentSetting) {
173             case Settings.Secure.MATCH_CONTENT_FRAMERATE_NEVER:
174                 return TvSettingsEnums.DISPLAY_SOUND_MATCH_CONTENT_FRAMERATE_NEVER;
175             case Settings.Secure.MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY:
176                 return TvSettingsEnums.DISPLAY_SOUND_MATCH_CONTENT_FRAMERATE_SEAMLESS;
177             case Settings.Secure.MATCH_CONTENT_FRAMERATE_ALWAYS:
178                 return TvSettingsEnums.DISPLAY_SOUND_MATCH_CONTENT_FRAMERATE_NON_SEAMLESS;
179             default:
180                 throw new IllegalArgumentException("Unknown match content frame rate pref value");
181         }
182     }
183 
createInfoFragments()184     private void createInfoFragments() {
185         Preference seamlessPreference = findPreference(KEY_MATCH_CONTENT_FRAME_RATE_SEAMLESS);
186         seamlessPreference.setFragment(
187                 MatchContentFrameRateInfo.SeamlessInfoFragment.class.getName());
188 
189         Preference nonSeamlessPreference = findPreference(
190                 KEY_MATCH_CONTENT_FRAME_RATE_NON_SEAMLESS);
191         nonSeamlessPreference.setFragment(
192                 MatchContentFrameRateInfo.NonSeamlessInfoFragment.class.getName());
193 
194         Preference neverPreference = findPreference(KEY_MATCH_CONTENT_FRAME_RATE_NEVER);
195         neverPreference.setFragment(MatchContentFrameRateInfo.NeverInfoFragment.class.getName());
196     }
197 }