1 /* 2 * Copyright (C) 2015 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; 18 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.os.Build; 22 import android.support.annotation.VisibleForTesting; 23 import android.text.TextUtils; 24 import android.util.Log; 25 26 import com.android.tv.common.feature.Feature; 27 import com.android.tv.common.feature.GServiceFeature; 28 import com.android.tv.common.feature.PropertyFeature; 29 import com.android.tv.config.RemoteConfig; 30 import com.android.tv.experiments.Experiments; 31 import com.android.tv.util.LocationUtils; 32 import com.android.tv.util.PermissionUtils; 33 import com.android.tv.util.Utils; 34 35 import java.util.Locale; 36 37 import static com.android.tv.common.feature.EngOnlyFeature.ENG_ONLY_FEATURE; 38 import static com.android.tv.common.feature.FeatureUtils.AND; 39 import static com.android.tv.common.feature.FeatureUtils.OFF; 40 import static com.android.tv.common.feature.FeatureUtils.ON; 41 import static com.android.tv.common.feature.FeatureUtils.OR; 42 43 /** 44 * List of {@link Feature} for the Live TV App. 45 * 46 * <p>Remove the {@code Feature} once it is launched. 47 */ 48 public final class Features { 49 private static final String TAG = "Features"; 50 private static final boolean DEBUG = false; 51 52 /** 53 * UI for opting in to analytics. 54 * 55 * <p>Do not turn this on until the splash screen asking existing users to opt-in is launched. 56 * See <a href="http://b/20228119">b/20228119</a> 57 */ 58 public static final Feature ANALYTICS_OPT_IN = ENG_ONLY_FEATURE; 59 60 /** 61 * Analytics that include sensitive information such as channel or program identifiers. 62 * 63 * <p>See <a href="http://b/22062676">b/22062676</a> 64 */ 65 public static final Feature ANALYTICS_V2 = AND(ON, ANALYTICS_OPT_IN); 66 67 public static final Feature EPG_SEARCH = 68 new PropertyFeature("feature_tv_use_epg_search", false); 69 70 public static final Feature TUNER = 71 new Feature() { 72 @Override 73 public boolean isEnabled(Context context) { 74 75 if (Utils.isDeveloper()) { 76 // we enable tuner for developers to test tuner in any platform. 77 return true; 78 } 79 80 // This is special handling just for USB Tuner. 81 // It does not require any N API's but relies on a improvements in N for AC3 support 82 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; 83 } 84 }; 85 86 /** 87 * Use network tuner if it is available and there is no other tuner types. 88 */ 89 public static final Feature NETWORK_TUNER = 90 new Feature() { 91 @Override 92 public boolean isEnabled(Context context) { 93 if (!TUNER.isEnabled(context)) { 94 return false; 95 } 96 if (Utils.isDeveloper()) { 97 // Network tuner will be enabled for developers. 98 return true; 99 } 100 return Locale.US.getCountry().equalsIgnoreCase( 101 LocationUtils.getCurrentCountry(context)); 102 } 103 }; 104 105 private static final String GSERVICE_KEY_UNHIDE = "live_channels_unhide"; 106 /** 107 * A flag which indicates that LC app is unhidden even when there is no input. 108 */ 109 public static final Feature UNHIDE = 110 OR(new GServiceFeature(GSERVICE_KEY_UNHIDE, false), new Feature() { 111 @Override 112 public boolean isEnabled(Context context) { 113 // If LC app runs as non-system app, we unhide the app. 114 return !PermissionUtils.hasAccessAllEpg(context); 115 } 116 }); 117 118 public static final Feature PICTURE_IN_PICTURE = 119 new Feature() { 120 private Boolean mEnabled; 121 122 @Override 123 public boolean isEnabled(Context context) { 124 if (mEnabled == null) { 125 mEnabled = 126 Build.VERSION.SDK_INT >= Build.VERSION_CODES.N 127 && context.getPackageManager() 128 .hasSystemFeature( 129 PackageManager.FEATURE_PICTURE_IN_PICTURE); 130 } 131 return mEnabled; 132 } 133 }; 134 135 /** Use AC3 software decode. */ 136 public static final Feature AC3_SOFTWARE_DECODE = 137 new Feature() { 138 private final String[] SUPPORTED_REGIONS = {}; 139 140 private Boolean mEnabled; 141 142 @Override 143 public boolean isEnabled(Context context) { 144 if (mEnabled == null) { 145 if (mEnabled == null) { 146 // We will not cache the result of fallback solution. 147 String country = LocationUtils.getCurrentCountry(context); 148 for (int i = 0; i < SUPPORTED_REGIONS.length; ++i) { 149 if (SUPPORTED_REGIONS[i].equalsIgnoreCase(country)) { 150 return true; 151 } 152 } 153 if (DEBUG) Log.d(TAG, "AC3 flag false after country check"); 154 return false; 155 } 156 } 157 if (DEBUG) Log.d(TAG, "AC3 flag " + mEnabled); 158 return mEnabled; 159 } 160 }; 161 162 /** Show postal code fragment before channel scan. */ 163 public static final Feature ENABLE_CLOUD_EPG_REGION = 164 new Feature() { 165 private final String[] SUPPORTED_REGIONS = { 166 }; 167 168 169 @Override 170 public boolean isEnabled(Context context) { 171 if (!Experiments.CLOUD_EPG.get()) { 172 if (DEBUG) Log.d(TAG, "Experiments.CLOUD_EPG is false"); 173 return false; 174 } 175 String country = LocationUtils.getCurrentCountry(context); 176 for (int i = 0; i < SUPPORTED_REGIONS.length; i++) { 177 if (SUPPORTED_REGIONS[i].equalsIgnoreCase(country)) { 178 return true; 179 } 180 } 181 if (DEBUG) Log.d(TAG, "EPG flag false after country check"); 182 return false; 183 } 184 }; 185 186 /** Enable a conflict dialog between currently watched channel and upcoming recording. */ 187 public static final Feature SHOW_UPCOMING_CONFLICT_DIALOG = OFF; 188 189 /** 190 * Use input blacklist to disable partner's tuner input. 191 */ 192 public static final Feature USE_PARTNER_INPUT_BLACKLIST = ON; 193 194 /** 195 * Enable Dvb parsers and listeners. 196 */ 197 public static final Feature ENABLE_FILE_DVB = OFF; 198 199 @VisibleForTesting 200 public static final Feature TEST_FEATURE = new PropertyFeature("test_feature", false); 201 Features()202 private Features() { 203 } 204 } 205