Merge Android 14 QPR2 to AOSP main

Bug: 319669529
Merged-In: Ia1cb202ec5dedbf85d1327d461186913b1a3003f
Change-Id: I5e4ab378829094e0011deecc0fc0457546c0a0b5
diff --git a/Android.bp b/Android.bp
index 6abdb3c..463c5e2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,6 +62,7 @@
     libs: ["tv-guava-android-jar"],
 
     static_libs: [
+        "androidx-constraintlayout_constraintlayout",
         "android-support-annotations",
         "android-support-compat",
         "android-support-v7-recyclerview",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7f5be2e..5d9492a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,6 +20,18 @@
      xmlns:tools="http://schemas.android.com/tools"
      package="com.android.tv">
 
+    <queries>
+        <intent>
+            <action android:name="android.intent.action.MAIN" />
+        </intent>
+        <intent>
+            <action android:name="android.media.tv.TvInputService" />
+        </intent>
+        <intent>
+            <action android:name="android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS" />
+        </intent>
+    </queries>
+
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
@@ -167,6 +179,7 @@
         </activity>
         <activity android:name="com.android.tv.SelectInputActivity"
              android:exported="true"
+             android:label="@string/select_inputs"
              android:configChanges="keyboard|keyboardHidden"
              android:launchMode="singleTask"
              android:theme="@style/Theme.SelectInputActivity">
diff --git a/common/src/com/android/tv/common/feature/ResourceConfigFeature.java b/common/src/com/android/tv/common/feature/ResourceConfigFeature.java
new file mode 100644
index 0000000..7519a35
--- /dev/null
+++ b/common/src/com/android/tv/common/feature/ResourceConfigFeature.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.common.feature;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+public class ResourceConfigFeature implements Feature{
+
+    private final int mResId;
+    private final boolean mDefaultValue;
+
+    public ResourceConfigFeature(int resId, boolean defaultValue) {
+        mResId = resId;
+        mDefaultValue = defaultValue;
+    }
+    @Override
+    public boolean isEnabled(Context context) {
+        try {
+            return context.getResources().getBoolean(mResId);
+        } catch (Resources.NotFoundException e) {
+            return mDefaultValue;
+        }
+    }
+}
diff --git a/res/drawable/empty_input_background.png b/res/drawable/empty_input_background.png
new file mode 100644
index 0000000..2dc3970
--- /dev/null
+++ b/res/drawable/empty_input_background.png
Binary files differ
diff --git a/res/drawable/ic_empty_input_hdmi.xml b/res/drawable/ic_empty_input_hdmi.xml
new file mode 100644
index 0000000..b2150a1
--- /dev/null
+++ b/res/drawable/ic_empty_input_hdmi.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="@color/empty_input_status_icon_tint_color">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M306,896L306,767L184,530L184,275L224,275L224,136Q224,108.05 245.84,86.03Q267.69,64 297,64L663,64Q692.05,64 714.03,86.03Q736,108.05 736,136L736,275L776,275L776,530L654,767L654,896L306,896ZM297,275L395,275L395,194L432,194L432,275L528,275L528,194L565,194L565,275L663,275L663,137Q663,137 663,137Q663,137 663,137L297,137Q297,137 297,137Q297,137 297,137L297,275ZM379,823L581,823L581,749L703,510L703,348L257,348L257,510L379,749L379,823ZM480,510L480,510L480,510L480,510L480,510L480,510L480,510L480,510L480,510Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_empty_input_tuner.xml b/res/drawable/ic_empty_input_tuner.xml
new file mode 100644
index 0000000..9f694e9
--- /dev/null
+++ b/res/drawable/ic_empty_input_tuner.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="@color/empty_input_status_icon_tint_color">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M199,689Q138,630 106.5,552.5Q75,475 75,400Q75,325 105,248.5Q135,172 199,111L242,154Q191,205 163.5,271.5Q136,338 136,400Q136,462 163.5,528.5Q191,595 242,646L199,689ZM289,599Q247,560 227,506.5Q207,453 207,400Q207,351 226.5,296Q246,241 289,201L332,244Q302,274 285,318Q268,362 268,400Q268,434 285.5,479Q303,524 332,556L289,599ZM285,886L420,477Q403,464 393.5,444.5Q384,425 384,400Q384,359 411.5,331Q439,303 480,303Q521,303 549,331Q577,359 577,400Q577,425 567,444.5Q557,464 541,477L675,886L602,886L573,796L388,796L358,886L285,886ZM411,723L549,723L480,512L411,723ZM671,599L628,556Q658,526 675.5,482Q693,438 693,400Q693,366 675,321Q657,276 628,244L671,201Q714,241 734.5,296.5Q755,352 754,400Q754,448 733.5,503.5Q713,559 671,599ZM761,689L718,646Q769,595 797,528.5Q825,462 825,400Q825,338 797,271.5Q769,205 718,154L761,111Q823,171 854.5,248Q886,325 886,400Q886,476 856,552Q826,628 761,689Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/input_banner_v2_background.xml b/res/drawable/input_banner_v2_background.xml
new file mode 100644
index 0000000..ac93e32
--- /dev/null
+++ b/res/drawable/input_banner_v2_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="16dp" />
+    <solid android:color="#E6252A34"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/block_screen.xml b/res/layout/block_screen.xml
index c564efd..7edc983 100644
--- a/res/layout/block_screen.xml
+++ b/res/layout/block_screen.xml
@@ -71,4 +71,11 @@
             android:lineSpacingExtra="@dimen/tvview_block_line_spacing_extra"
             android:textColor="@color/tvview_block_text_color" />
     </LinearLayout>
+
+    <!-- b/302992748 new config-controlled no signal page -->
+    <com.android.tv.ui.EmptyInputStatusBlockView
+        android:id="@+id/empty_input_status_block_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"/>
 </com.android.tv.ui.BlockScreenView>
diff --git a/res/layout/empty_input_status_block.xml b/res/layout/empty_input_status_block.xml
new file mode 100644
index 0000000..d44a2f0
--- /dev/null
+++ b/res/layout/empty_input_status_block.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/block_screen_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+  android:background="@drawable/empty_input_background">
+
+    <ImageView
+        android:id="@+id/empty_input_status_icon"
+        android:layout_width="@dimen/empty_input_status_block_icon_width"
+        android:layout_height="@dimen/empty_input_status_block_icon_height"
+        android:contentDescription="@null"
+        android:src="@drawable/ic_empty_input_hdmi"
+        android:layout_marginTop="@dimen/empty_input_status_block_icon_margin_top"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/empty_input_status_title_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="google-sans-text-regular"
+        android:textColor="@color/empty_input_status_title_text_color"
+        android:textSize="@dimen/empty_input_status_block_title_text_size"
+        android:text="@string/empty_input_status_title_format"
+        android:layout_marginTop="@dimen/empty_input_status_block_title_margin_top"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/empty_input_status_icon"/>
+
+    <TextView
+        android:id="@+id/empty_input_status_info_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:fontFamily="google-sans-text-regular"
+        android:textColor="@color/empty_input_status_info_text_color"
+        android:textSize="@dimen/empty_input_status_block_info_text_size"
+        android:text="@string/empty_input_status_info"
+        android:layout_marginTop="@dimen/empty_input_status_block_info_margin_top"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/empty_input_status_title_text" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/res/layout/input_banner_v2.xml b/res/layout/input_banner_v2.xml
new file mode 100644
index 0000000..8f89782
--- /dev/null
+++ b/res/layout/input_banner_v2.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+
+<!--  All info banners have the same id for use by TvTransitionManager. -->
+<com.android.tv.ui.InputBannerViewV2 xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scene_transition_common"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="start|top"
+    android:layout_marginStart="24dp"
+    android:layout_marginTop="24dp"
+    android:background="@drawable/input_banner_v2_background"
+    android:maxWidth="@dimen/input_banner_item_label_max_width"
+    android:minWidth="76dp"
+    android:minHeight="39dp"
+    android:orientation="vertical"
+    android:elevation="8dp"
+    android:focusable="false"
+    android:paddingStart="20dp"
+    android:paddingTop="16dp"
+    android:paddingEnd="20dp"
+    android:paddingBottom="16dp">
+
+    <TextView
+        android:id="@+id/input_info"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:ellipsize="end"
+        android:fontFamily="google-sans-text-medium"
+        android:gravity="start"
+        android:singleLine="true"
+        android:text="@string/input_banner_v2_active_input"
+        android:textColor="#CCD2E3FC"
+        android:textSize="12sp" />
+
+    <TextView
+        android:id="@+id/input_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:layout_marginTop="2dp"
+        android:ellipsize="end"
+        android:fontFamily="google-sans-text-medium"
+        android:gravity="start"
+        android:singleLine="true"
+        android:textColor="#E8F0FE"
+        android:textSize="18sp" />
+
+</com.android.tv.ui.InputBannerViewV2>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f46d7b9..e372c15 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -111,6 +111,11 @@
     <color name="tvview_block_text_color">#80EEEEEE</color>
     <color name="tvview_block_image_color_filter">#99000000</color>
 
+    <!-- Empty input status -->
+    <color name="empty_input_status_icon_tint_color">#FF445664</color>
+    <color name="empty_input_status_title_text_color">#FFE8F0FE</color>
+    <color name="empty_input_status_info_text_color">#99D2E3FC</color>
+
     <!-- Channel banner -->
     <color name="channel_banner_text_color">#FFEEEEEE</color>
     <color name="channel_banner_episode_text_color">#B3EEEEEE</color>
diff --git a/res/values/configs.xml b/res/values/configs.xml
new file mode 100644
index 0000000..15481b0
--- /dev/null
+++ b/res/values/configs.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 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.
+  -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <bool name="use_gtv_livetv_v2">false</bool>
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 9d8941f..8b1e9e2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -248,6 +248,15 @@
     <dimen name="shrunken_tvview_margin_start">56dp</dimen>
     <dimen name="shrunken_tvview_margin_end">32dp</dimen>
 
+    <!-- Empty input status -->
+    <dimen name="empty_input_status_block_title_text_size">28sp</dimen>
+    <dimen name="empty_input_status_block_info_text_size">16sp</dimen>
+    <dimen name="empty_input_status_block_icon_width">170dp</dimen>
+    <dimen name="empty_input_status_block_icon_height">170dp</dimen>
+    <dimen name="empty_input_status_block_icon_margin_top">100dp</dimen>
+    <dimen name="empty_input_status_block_title_margin_top">44dp</dimen>
+    <dimen name="empty_input_status_block_info_margin_top">16dp</dimen>
+
     <!-- Channel banner -->
     <dimen name="channel_banner_width">696dp</dimen>
     <dimen name="channel_banner_channel_number_large_text_size">54sp</dimen>
diff --git a/res/values/strings-custom.xml b/res/values/strings-custom.xml
index 5ecb859..0055937 100644
--- a/res/values/strings-custom.xml
+++ b/res/values/strings-custom.xml
@@ -27,5 +27,6 @@
         meaning="Live TV version of setup_sources_description2"
         ><xliff:g id="app_name">Live TV</xliff:g> combines the experience of traditional TV channels with streaming channels provided by apps.
 \n\nGet started by setting up the channel sources already installed. Or browse Google Play Store for more apps that offer live channels.</string>
-
+    <!-- Name of SelectInputActivity [CHAR LIMIT=NONE] -->
+    <string name="select_inputs">Inputs</string>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b36827d..a839351 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -420,6 +420,20 @@
 \n\nPress Right to adjust recording schedule.</item>
     </plurals>
 
+    <!-- Empty input status -->
+
+    <!-- The text used when external input source is weak signal or not connected [CHAR LIMIT=NONE] -->
+    <string name="empty_input_status_title_format"><xliff:g id="input_label" example="HDMI 1">%1$s</xliff:g> - No signal</string>
+    <!-- The text used to indicate the action when external input source is weak signal or not connected [CHAR LIMIT=NONE] -->
+    <string name="empty_input_status_info">Check the connection or select a different input source</string>
+
+    <!-- Input Banner -->
+    <eat-comment />
+    <!-- The text used to show in the input banner [CHAR LIMIT=NONE] -->
+    <string name="input_banner_v2_active_input">Active input</string>
+    <!-- The text used when switching to a new input source. [CHAR LIMIT=NONE] -->
+    <string name="input_banner_v2_input_label_format"><xliff:g example="HDMI 1" id="label">%1$s</xliff:g> · <xliff:g example="Play Station" id="custom_label">%2$s</xliff:g></string>
+
     <!-- Channel Banner -->
     <eat-comment />
     <!-- The text used when there is no program title. [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/tv/MainActivity.java b/src/com/android/tv/MainActivity.java
index cea293d..5b35948 100644
--- a/src/com/android/tv/MainActivity.java
+++ b/src/com/android/tv/MainActivity.java
@@ -134,7 +134,7 @@
 import com.android.tv.tunerinputcontroller.BuiltInTunerManager;
 import com.android.tv.ui.ChannelBannerView;
 import com.android.tv.ui.DetailsActivity;
-import com.android.tv.ui.InputBannerView;
+import com.android.tv.ui.InputBannerViewBase;
 import com.android.tv.ui.KeypadChannelSwitchView;
 import com.android.tv.ui.SelectInputView;
 import com.android.tv.ui.SelectInputView.OnInputSelectedCallback;
@@ -455,7 +455,7 @@
                 public void onLoadFinished() {
                     Debug.getTimer(Debug.TAG_START_UP_TIMER)
                             .log("MainActivity.mChannelTunerListener.onLoadFinished");
-                    mSetupUtils.markNewChannelsBrowsable();
+                    mSetupUtils.markNewChannelsBrowsableIfEnabled();
                     if (mActivityResumed) {
                         resumeTvIfNeeded();
                     }
@@ -677,9 +677,13 @@
                 (KeypadChannelSwitchView)
                         getLayoutInflater()
                                 .inflate(R.layout.keypad_channel_switch, sceneContainer, false);
-        InputBannerView inputBannerView =
-                (InputBannerView)
-                        getLayoutInflater().inflate(R.layout.input_banner, sceneContainer, false);
+
+
+        boolean useV2 = TvFeatures.USE_GTV_LIVETV_V2.isEnabled(this);
+        int inputBannerLayoutId = useV2 ? R.layout.input_banner_v2 : R.layout.input_banner;
+        InputBannerViewBase inputBannerView =
+                (InputBannerViewBase)
+                        getLayoutInflater().inflate(inputBannerLayoutId, sceneContainer, false);
         SelectInputView selectInputView =
                 (SelectInputView)
                         getLayoutInflater().inflate(R.layout.select_input, sceneContainer, false);
@@ -922,7 +926,7 @@
         }
 
         if (mChannelTuner.areAllChannelsLoaded()) {
-            mSetupUtils.markNewChannelsBrowsable();
+            mSetupUtils.markNewChannelsBrowsableIfEnabled();
             resumeTvIfNeeded();
         }
         mOverlayManager.showMenuWithTimeShiftPauseIfNeeded();
@@ -1094,7 +1098,10 @@
         }
 
         if (channelUri == null) {
-            mChannelTuner.moveToChannel(mChannelTuner.findNearestBrowsableChannel(0));
+            if (!mChannelTuner.moveToChannel(mChannelTuner.findNearestBrowsableChannel(0))) {
+                Log.w(TAG, "No browsable channel, show setup");
+                showSettingsFragment();
+            }
         } else {
             if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
                 ChannelImpl channel = ChannelImpl.createPassthroughChannel(channelUri);
@@ -1103,13 +1110,17 @@
                 long channelId = ContentUris.parseId(channelUri);
                 Channel channel = mChannelDataManager.getChannel(channelId);
                 if (channel == null || !mChannelTuner.moveToChannel(channel)) {
-                    mChannelTuner.moveToChannel(mChannelTuner.findNearestBrowsableChannel(0));
                     Log.w(
                             TAG,
                             "The requested channel (id="
                                     + channelId
                                     + ") doesn't exist. "
                                     + "The first channel will be tuned to.");
+                    if (!mChannelTuner.moveToChannel(
+                            mChannelTuner.findNearestBrowsableChannel(0))) {
+                        Log.w(TAG, "No browsable channel, show setup");
+                        showSettingsFragment();
+                    }
                 }
             }
         }
@@ -2960,6 +2971,7 @@
                     allowAutoSelectionOfTrack ? null : getSelectedTrack(TvTrackInfo.TYPE_AUDIO));
             applyClosedCaption();
             mOverlayManager.getMenu().onStreamInfoChanged();
+            mOverlayManager.updateInputBannerIfNeeded(info);
             if (mTvView.isVideoAvailable()) {
                 mTvViewUiManager.fadeInTvView();
             }
diff --git a/src/com/android/tv/TvApplication.java b/src/com/android/tv/TvApplication.java
index c5e4f32..738759f 100644
--- a/src/com/android/tv/TvApplication.java
+++ b/src/com/android/tv/TvApplication.java
@@ -409,9 +409,17 @@
                 ++inputCount;
             }
         }
-        if (inputCount < 2) {
+
+        if (inputCount < 1) {
+            Log.w(TAG, "No available input to be selected.");
             return;
         }
+
+        if (mMainActivityWrapper.isResumed() && inputCount < 2) {
+            // if no other inputs can be switched to, keep in the same input
+            return;
+        }
+
         Activity activityToHandle =
                 mMainActivityWrapper.isResumed()
                         ? mMainActivityWrapper.getMainActivity()
diff --git a/src/com/android/tv/data/ChannelDataManager.java b/src/com/android/tv/data/ChannelDataManager.java
index 67c3230..fb7ab02 100644
--- a/src/com/android/tv/data/ChannelDataManager.java
+++ b/src/com/android/tv/data/ChannelDataManager.java
@@ -301,6 +301,22 @@
     }
 
     /**
+     * Returns the total browsable channel count for a given input.
+     *
+     * @param inputId The ID of the input.
+     */
+    public int getBrowsableChannelCountForInput(String inputId) {
+        int count = 0;
+        for (Channel channel : mData.channels) {
+            if (channel.getInputId().equals(inputId) && channel.isBrowsable()) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+
+    /**
      * Checks if the channel exists in DB.
      *
      * <p>Note that the channels of the removed inputs can not be obtained from {@link #getChannel}.
diff --git a/src/com/android/tv/features/TvFeatures.java b/src/com/android/tv/features/TvFeatures.java
index ebd7cb9..c4e388a 100644
--- a/src/com/android/tv/features/TvFeatures.java
+++ b/src/com/android/tv/features/TvFeatures.java
@@ -28,10 +28,13 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 
+import androidx.core.R;
+
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.common.feature.Feature;
 import com.android.tv.common.feature.FeatureUtils;
 import com.android.tv.common.feature.FlagFeature;
+import com.android.tv.common.feature.ResourceConfigFeature;
 import com.android.tv.common.feature.Sdk;
 import com.android.tv.common.feature.TestableFeature;
 import com.android.tv.common.flags.has.HasUiFlags;
@@ -104,5 +107,9 @@
     /** Support for interactive applications using the TIAF **/
     public static final Feature HAS_TIAF = Sdk.AT_LEAST_T;
 
+    /** Use new components that are consistent with other Google TV styles b/302992748 */
+    public static final Feature USE_GTV_LIVETV_V2 =
+            new ResourceConfigFeature(R.bool.use_gtv_livetv_v2, false);
+
     private TvFeatures() {}
 }
diff --git a/src/com/android/tv/onboarding/OnboardingActivity.java b/src/com/android/tv/onboarding/OnboardingActivity.java
index 0ce5d93..6eb1a89 100644
--- a/src/com/android/tv/onboarding/OnboardingActivity.java
+++ b/src/com/android/tv/onboarding/OnboardingActivity.java
@@ -66,7 +66,7 @@
                 @Override
                 public void onLoadFinished() {
                     mChannelDataManager.removeListener(this);
-                    mSetupUtils.markNewChannelsBrowsable();
+                    mSetupUtils.markNewChannelsBrowsableIfEnabled();
                 }
 
                 @Override
@@ -97,9 +97,9 @@
         mInputManager = singletons.getTvInputManagerHelper();
         if (PermissionUtils.hasAccessAllEpg(this) || PermissionUtils.hasReadTvListings(this)) {
             // Make the channels of the new inputs which have been setup outside TV app
-            // browsable.
+            // browsable if enabled.
             if (mChannelDataManager.isDbLoadFinished()) {
-                mSetupUtils.markNewChannelsBrowsable();
+                mSetupUtils.markNewChannelsBrowsableIfEnabled();
             } else {
                 mChannelDataManager.addListener(mChannelListener);
             }
diff --git a/src/com/android/tv/onboarding/SetupSourcesFragment.java b/src/com/android/tv/onboarding/SetupSourcesFragment.java
index b97c780..855fb27 100644
--- a/src/com/android/tv/onboarding/SetupSourcesFragment.java
+++ b/src/com/android/tv/onboarding/SetupSourcesFragment.java
@@ -313,7 +313,7 @@
                 TvInputInfo input = mInputs.get(i);
                 String inputId = input.getId();
                 String description;
-                int channelCount = mChannelDataManager.getChannelCountForInput(inputId);
+                int channelCount = mChannelDataManager.getBrowsableChannelCountForInput(inputId);
                 if (mSetupUtils.isSetupDone(inputId) || channelCount > 0) {
                     if (channelCount == 0) {
                         description = getString(R.string.setup_input_no_channels);
diff --git a/src/com/android/tv/ui/BlockScreenView.java b/src/com/android/tv/ui/BlockScreenView.java
index b7a2dd9..9f61bf0 100644
--- a/src/com/android/tv/ui/BlockScreenView.java
+++ b/src/com/android/tv/ui/BlockScreenView.java
@@ -16,12 +16,15 @@
 
 package com.android.tv.ui;
 
+import static com.android.tv.R.animator.tvview_block_screen_fade_out;
+
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.media.tv.TvInputInfo;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -30,6 +33,7 @@
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 import android.widget.TextView;
+
 import com.android.tv.R;
 import com.android.tv.ui.TunableTvView.BlockScreenType;
 
@@ -42,6 +46,8 @@
     private TextView mBlockingInfoTextView;
     private ImageView mBackgroundImageView;
 
+    private EmptyInputStatusBlockView mEmptyInputStatusBlockView;
+
     private final int mSpacingNormal;
     private final int mSpacingShrunken;
 
@@ -79,6 +85,7 @@
         mSpace = findViewById(R.id.space);
         mBlockingInfoTextView = (TextView) findViewById(R.id.block_screen_text);
         mBackgroundImageView = (ImageView) findViewById(R.id.background_image);
+        mEmptyInputStatusBlockView = findViewById(R.id.empty_input_status_block_view);
         mFadeOut =
                 AnimatorInflater.loadAnimator(
                         getContext(), R.animator.tvview_block_screen_fade_out);
@@ -261,4 +268,12 @@
     public void setInfoTextClickable(boolean clickable) {
         mBlockingInfoTextView.setClickable(clickable);
     }
+
+    public void setEmptyInputStatusInputInfo(TvInputInfo inputInfo) {
+        mEmptyInputStatusBlockView.setIconAndLabelByInputInfo(inputInfo);
+    }
+
+    public void setEmptyInputStatusBlockVisibility(boolean visible) {
+        mEmptyInputStatusBlockView.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/src/com/android/tv/ui/EmptyInputStatusBlockView.java b/src/com/android/tv/ui/EmptyInputStatusBlockView.java
new file mode 100644
index 0000000..a7f9166
--- /dev/null
+++ b/src/com/android/tv/ui/EmptyInputStatusBlockView.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2023 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;
+
+import android.content.Context;
+import android.media.tv.TvInputInfo;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.tv.R;
+
+public class EmptyInputStatusBlockView extends FrameLayout {
+    private ImageView mEmptyInputStatusIcon;
+    private TextView mEmptyInputTitleTextView;
+
+    public EmptyInputStatusBlockView(Context context) {
+        this(context, null, 0);
+    }
+
+    public EmptyInputStatusBlockView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public EmptyInputStatusBlockView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        inflate(context, R.layout.empty_input_status_block, this);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mEmptyInputStatusIcon = findViewById(R.id.empty_input_status_icon);
+        mEmptyInputTitleTextView = findViewById(R.id.empty_input_status_title_text);
+    }
+
+    public void setIconAndLabelByInputInfo(TvInputInfo inputInfo) {
+        CharSequence label = inputInfo.loadLabel(getContext());
+        String title = getResources().getString(R.string.empty_input_status_title_format, label);
+        mEmptyInputTitleTextView.setText(title);
+
+        if (inputInfo.isPassthroughInput()) {
+            mEmptyInputStatusIcon.setImageDrawable(
+                    getResources().getDrawable(R.drawable.ic_empty_input_hdmi, null)
+            );
+        } else {
+            mEmptyInputStatusIcon.setImageDrawable(
+                    getResources().getDrawable(R.drawable.ic_empty_input_tuner, null)
+            );
+        }
+    }
+}
diff --git a/src/com/android/tv/ui/InputBannerView.java b/src/com/android/tv/ui/InputBannerView.java
index d060918..598d18a 100644
--- a/src/com/android/tv/ui/InputBannerView.java
+++ b/src/com/android/tv/ui/InputBannerView.java
@@ -21,49 +21,38 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
-import android.widget.LinearLayout;
 import android.widget.TextView;
+
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.data.api.Channel;
 
-public class InputBannerView extends LinearLayout implements TvTransitionManager.TransitionLayout {
-    private final long mShowDurationMillis;
+public class InputBannerView extends InputBannerViewBase
+        implements TvTransitionManager.TransitionLayout {
 
-    private final Runnable mHideRunnable =
-            () ->
-                    ((MainActivity) getContext())
-                            .getOverlayManager()
-                            .hideOverlays(
-                                    TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_DIALOG
-                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANELS
-                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_PROGRAM_GUIDE
-                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_MENU
-                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_FRAGMENT);
     private TextView mInputLabelTextView;
     private TextView mSecondaryInputLabelTextView;
 
     public InputBannerView(Context context) {
-        this(context, null, 0);
+        super(context);
     }
 
     public InputBannerView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
+        super(context, attrs);
     }
 
     public InputBannerView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        mShowDurationMillis =
-                context.getResources().getInteger(R.integer.select_input_show_duration);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mInputLabelTextView = (TextView) findViewById(R.id.input_label);
-        mSecondaryInputLabelTextView = (TextView) findViewById(R.id.secondary_input_label);
+        mInputLabelTextView = findViewById(R.id.input_label);
+        mSecondaryInputLabelTextView = findViewById(R.id.secondary_input_label);
     }
 
+    @Override
     public void updateLabel() {
         MainActivity mainActivity = (MainActivity) getContext();
         Channel channel = mainActivity.getCurrentChannel();
@@ -83,15 +72,4 @@
             mSecondaryInputLabelTextView.setVisibility(View.VISIBLE);
         }
     }
-
-    @Override
-    public void onEnterAction(boolean fromEmptyScene) {
-        removeCallbacks(mHideRunnable);
-        postDelayed(mHideRunnable, mShowDurationMillis);
-    }
-
-    @Override
-    public void onExitAction() {
-        removeCallbacks(mHideRunnable);
-    }
 }
diff --git a/src/com/android/tv/ui/InputBannerViewBase.java b/src/com/android/tv/ui/InputBannerViewBase.java
new file mode 100644
index 0000000..c20e1da
--- /dev/null
+++ b/src/com/android/tv/ui/InputBannerViewBase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 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;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import com.android.tv.MainActivity;
+import com.android.tv.R;
+import com.android.tv.data.StreamInfo;
+
+public abstract class InputBannerViewBase extends LinearLayout
+        implements TvTransitionManager.TransitionLayout {
+    protected final long mShowDurationMillis;
+    protected final Runnable mHideRunnable =
+            () ->
+                    ((MainActivity) getContext())
+                            .getOverlayManager()
+                            .hideOverlays(
+                                    TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_DIALOG
+                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANELS
+                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_PROGRAM_GUIDE
+                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_MENU
+                                            | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_FRAGMENT);
+    public InputBannerViewBase(Context context) {
+        this(context, null, 0);
+    }
+
+    public InputBannerViewBase(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InputBannerViewBase(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mShowDurationMillis =
+                context.getResources().getInteger(R.integer.select_input_show_duration);
+
+    }
+
+    public abstract void updateLabel();
+
+    @Override
+    public void onEnterAction(boolean fromEmptyScene) {
+        removeCallbacks(mHideRunnable);
+        postDelayed(mHideRunnable, mShowDurationMillis);
+    }
+
+    @Override
+    public void onExitAction() {
+        removeCallbacks(mHideRunnable);
+    }
+
+    public void onStreamInfoUpdated(StreamInfo info) {}
+}
diff --git a/src/com/android/tv/ui/InputBannerViewV2.java b/src/com/android/tv/ui/InputBannerViewV2.java
new file mode 100644
index 0000000..e340819
--- /dev/null
+++ b/src/com/android/tv/ui/InputBannerViewV2.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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;
+
+import android.content.Context;
+import android.media.tv.TvInputInfo;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.TextView;
+
+import com.android.tv.MainActivity;
+import com.android.tv.R;
+import com.android.tv.data.StreamInfo;
+import com.android.tv.data.api.Channel;
+
+public class InputBannerViewV2 extends InputBannerViewBase
+        implements TvTransitionManager.TransitionLayout {
+    private static final String TAG = "InputBannerViewV2";
+
+    private TextView mInputLabelTextView;
+    public InputBannerViewV2(Context context) {
+        super(context);
+    }
+
+    public InputBannerViewV2(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public InputBannerViewV2(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mInputLabelTextView = findViewById(R.id.input_label);
+    }
+
+    @Override
+    public void updateLabel() {
+        MainActivity mainActivity = (MainActivity) getContext();
+        Channel channel = mainActivity.getCurrentChannel();
+        if (channel == null || !channel.isPassthrough()) {
+            return;
+        }
+
+        TvInputInfo input =
+                mainActivity.getTvInputManagerHelper().getTvInputInfo(channel.getInputId());
+        if (input == null) {
+            Log.e(TAG, "unable to get TvInputInfo of id " + channel.getInputId());
+            return;
+        }
+
+        updateInputLabel(input);
+    }
+
+    private void updateInputLabel(TvInputInfo input) {
+        CharSequence customLabel = input.loadCustomLabel(getContext());
+        CharSequence label = input.loadLabel(getContext());
+
+        if (customLabel == null) {
+            mInputLabelTextView.setText(label);
+        } else {
+            String inputLabel = getResources().getString(
+                    R.string.input_banner_v2_input_label_format, label, customLabel);
+            mInputLabelTextView.setText(inputLabel);
+        }
+
+    }
+}
diff --git a/src/com/android/tv/ui/TunableTvView.java b/src/com/android/tv/ui/TunableTvView.java
index 3ac841c..76fb0a1 100644
--- a/src/com/android/tv/ui/TunableTvView.java
+++ b/src/com/android/tv/ui/TunableTvView.java
@@ -1017,6 +1017,12 @@
                 return;
             }
             mBlockScreenView.setVisibility(VISIBLE);
+            if (shouldShowEmptyInputStatusBlock()){
+                mBlockScreenView.setEmptyInputStatusInputInfo(mInputInfo);
+                mBlockScreenView.setEmptyInputStatusBlockVisibility(true);
+            } else {
+                mBlockScreenView.setEmptyInputStatusBlockVisibility(false);
+            }
             if (mTvIAppView != null) {
                 mTvIAppView.setVisibility(INVISIBLE);
             }
@@ -1255,6 +1261,13 @@
         }
     }
 
+    private boolean shouldShowEmptyInputStatusBlock() {
+        return TvFeatures.USE_GTV_LIVETV_V2.isEnabled(getContext()) &&
+                (mVideoUnavailableReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL ||
+                        mVideoUnavailableReason ==
+                                CommonConstants.VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED);
+    }
+
     private boolean isBundledInput() {
         return mInputInfo != null
                 && mInputInfo.getType() == TvInputInfo.TYPE_TUNER
diff --git a/src/com/android/tv/ui/TvOverlayManager.java b/src/com/android/tv/ui/TvOverlayManager.java
index 19af23b..dc4a27a 100644
--- a/src/com/android/tv/ui/TvOverlayManager.java
+++ b/src/com/android/tv/ui/TvOverlayManager.java
@@ -49,6 +49,7 @@
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.ProgramDataManager;
+import com.android.tv.data.StreamInfo;
 import com.android.tv.dialog.DvrHistoryDialogFragment;
 import com.android.tv.dialog.FullscreenDialogFragment;
 import com.android.tv.dialog.HalfSizedDialogFragment;
@@ -212,6 +213,7 @@
     private final SideFragmentManager mSideFragmentManager;
     private final ProgramGuide mProgramGuide;
     private final ChannelBannerView mChannelBannerView;
+    private final InputBannerViewBase mInputBannerView;
     private final KeypadChannelSwitchView mKeypadChannelSwitchView;
     private final SelectInputView mSelectInputView;
     private final ProgramGuideSearchFragment mSearchFragment;
@@ -237,7 +239,7 @@
             TvOptionsManager optionsManager,
             KeypadChannelSwitchView keypadChannelSwitchView,
             ChannelBannerView channelBannerView,
-            InputBannerView inputBannerView,
+            InputBannerViewBase inputBannerView,
             SelectInputView selectInputView,
             ViewGroup sceneContainer,
             ProgramGuideSearchFragment searchFragment,
@@ -253,6 +255,7 @@
         mInputManager = tvInputManager;
         mTvView = tvView;
         mChannelBannerView = channelBannerView;
+        mInputBannerView = inputBannerView;
         mKeypadChannelSwitchView = keypadChannelSwitchView;
         mSelectInputView = selectInputView;
         mSearchFragment = searchFragment;
@@ -875,6 +878,12 @@
         }
     }
 
+    public void updateInputBannerIfNeeded(StreamInfo info) {
+        if (mTransitionManager.isInputBannerActive()) {
+            mInputBannerView.onStreamInfoUpdated(info);
+        }
+    }
+
     @TvOverlayType
     private int convertSceneToOverlayType(@SceneType int sceneType) {
         switch (sceneType) {
diff --git a/src/com/android/tv/ui/TvTransitionManager.java b/src/com/android/tv/ui/TvTransitionManager.java
index f60337f..579fcfc 100644
--- a/src/com/android/tv/ui/TvTransitionManager.java
+++ b/src/com/android/tv/ui/TvTransitionManager.java
@@ -56,7 +56,7 @@
     private final MainActivity mMainActivity;
     private final ViewGroup mSceneContainer;
     private final ChannelBannerView mChannelBannerView;
-    private final InputBannerView mInputBannerView;
+    private final InputBannerViewBase mInputBannerView;
     private final KeypadChannelSwitchView mKeypadChannelSwitchView;
     private final SelectInputView mSelectInputView;
     private final FrameLayout mEmptyView;
@@ -78,7 +78,7 @@
             MainActivity mainActivity,
             ViewGroup sceneContainer,
             ChannelBannerView channelBannerView,
-            InputBannerView inputBannerView,
+            InputBannerViewBase inputBannerView,
             KeypadChannelSwitchView keypadChannelSwitchView,
             SelectInputView selectInputView) {
         mMainActivity = mainActivity;
@@ -159,6 +159,10 @@
         return mCurrentScene != null && mCurrentScene == mSelectInputScene;
     }
 
+    public boolean isInputBannerActive() {
+        return mCurrentScene != null && mCurrentScene == mInputBannerScene;
+    }
+
     public void setListener(Listener listener) {
         mListener = listener;
     }
diff --git a/src/com/android/tv/util/SetupUtils.java b/src/com/android/tv/util/SetupUtils.java
index aaee104..858114d 100644
--- a/src/com/android/tv/util/SetupUtils.java
+++ b/src/com/android/tv/util/SetupUtils.java
@@ -63,6 +63,8 @@
     // Recognized inputs means that the user already knows the inputs are installed.
     private static final String PREF_KEY_RECOGNIZED_INPUTS = "recognized_inputs";
     private static final String PREF_KEY_IS_FIRST_TUNE = "is_first_tune";
+    // Whether to mark new channels to browsable.
+    private static final boolean MARK_NEW_CHANNELS_BROWSABLE = false;
 
     private final Context mContext;
     private final SharedPreferences mSharedPreferences;
@@ -132,11 +134,11 @@
                     boolean browsableChanged = false;
                     for (Channel channel : manager.getChannelList()) {
                         if (channel.getInputId().equals(inputId)) {
-                            if (!channel.isBrowsable()) {
+                            if (!channel.isBrowsable() && MARK_NEW_CHANNELS_BROWSABLE) {
                                 manager.updateBrowsable(channel.getId(), true, true);
                                 browsableChanged = true;
                             }
-                            if (firstChannelForInput == null) {
+                            if (firstChannelForInput == null && channel.isBrowsable()) {
                                 firstChannelForInput = channel;
                             }
                         }
@@ -154,9 +156,15 @@
                 });
     }
 
-    /** Marks the channels in newly installed inputs browsable. */
+    /** Marks the channels in newly installed inputs browsable if enabled. */
     @UiThread
-    public void markNewChannelsBrowsable() {
+    public void markNewChannelsBrowsableIfEnabled() {
+        // TODO(b/288499376): Handle browsable field for channels added outside Live TV app in a
+        // better way.
+        if (!MARK_NEW_CHANNELS_BROWSABLE) {
+            return;
+        }
+
         Set<String> newInputsWithChannels = new HashSet<>();
         TvSingletons singletons = TvSingletons.getSingletons(mContext);
         TvInputManagerHelper tvInputManagerHelper = singletons.getTvInputManagerHelper();