Home | History | Annotate | Download | only in tv
      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 
    202     private Features() {
    203     }
    204 }
    205